2 * pppdump - print out the contents of a record file generated by
3 * pppd in readable form.
5 * Copyright (C) 1999 Paul Mackerras. All rights reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
14 #include <sys/types.h>
35 while ((i = getopt(ac, av, "hprdm:")) != -1) {
53 fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [file ...]\n", av[0]);
60 for (i = optind; i < ac; ++i) {
62 if ((f = fopen(p, "r")) == NULL) {
82 unsigned char buf[16];
85 while ((c = getc(f)) != EOF) {
91 printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
94 n = (n << 8) + getc(f);
105 for (k = 0; k < nb; ++k) {
107 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
115 k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
116 if ((col += k) >= 78) {
134 for (k = nb; k < 16; ++k)
137 for (k = 0; k < nb; ++k) {
139 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
147 printf("end %s\n", c==3? "send": "recv");
153 for (c = 3; c > 0; --c)
154 n = (n << 8) + getc(f);
156 printf("time %.1fs\n", (double) n / 10);
160 t = (t << 8) + getc(f);
161 t = (t << 8) + getc(f);
162 t = (t << 8) + getc(f);
163 printf("start %s", ctime(&t));
172 * FCS lookup table as calculated by genfcstab.
174 static u_short fcstab[256] = {
175 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
176 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
177 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
178 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
179 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
180 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
181 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
182 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
183 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
184 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
185 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
186 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
187 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
188 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
189 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
190 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
191 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
192 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
193 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
194 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
195 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
196 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
197 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
198 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
199 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
200 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
201 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
202 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
203 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
204 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
205 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
206 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
213 struct compressor *comp;
215 unsigned char buf[8192];
218 /* Values for flags */
221 #define CCP_FATALERROR 4
222 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
223 #define CCP_DECOMP_RUN 8
225 unsigned char dbuf[8192];
231 int nb, nl, dn, proto, rv;
233 unsigned char *p, *r, *endp;
239 spkt.cnt = rpkt.cnt = 0;
240 spkt.esc = rpkt.esc = 0;
241 while ((c = getc(f)) != EOF) {
247 dir = c==1? "sent": "rcvd";
248 pkt = c==1? &spkt: &rpkt;
250 n = (n << 8) + getc(f);
257 printf("[%d bytes in incomplete send packet]\n",
260 printf("[%d bytes in incomplete recv packet]\n",
267 printf("%s aborted packet:\n ", dir);
275 printf("%s short packet [%d bytes]:", q, nb);
276 for (k = 0; k < nb; ++k)
277 printf(" %.2x", p[k]);
282 for (k = 0; k < nb; ++k)
283 fcs = PPP_FCS(fcs, p[k]);
288 if (r[0] == 0xff && r[1] == 3)
294 printf(" ERROR: length (%d) > MRU (%d)\n",
296 if (decompress && fcs == PPP_GOODFCS) {
297 /* See if this is a CCP or compressed packet */
300 if (r[0] == 0xff && r[1] == 3) {
305 if ((proto & 1) == 0)
306 proto = (proto << 8) + r[1];
307 if (proto == PPP_CCP) {
308 handle_ccp(pkt, r + 2, endp - r - 2);
309 } else if (proto == PPP_COMP) {
310 if ((pkt->flags & CCP_ISUP)
311 && (pkt->flags & CCP_DECOMP_RUN)
313 && (pkt->flags & CCP_ERR) == 0) {
314 rv = pkt->comp->decompress(pkt->state, r,
324 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
327 printf(" DECOMPRESSION ERROR\n");
328 pkt->flags |= CCP_ERROR;
330 case DECOMP_FATALERROR:
331 printf(" FATAL DECOMPRESSION ERROR\n");
332 pkt->flags |= CCP_FATALERROR;
336 } else if (pkt->state
337 && (pkt->flags & CCP_DECOMP_RUN)) {
338 pkt->comp->incomp(pkt->state, r, endp - r);
342 nl = nb < 16? nb: 16;
344 for (k = 0; k < nl; ++k)
345 printf(" %.2x", p[k]);
349 for (k = 0; k < nl; ++k) {
351 putchar((' ' <= c && c <= '~')? c: '.');
358 if (fcs != PPP_GOODFCS)
359 printf(" BAD FCS: (residue = %x)\n", fcs);
367 /* else fall through */
373 pkt->buf[pkt->cnt++] = c;
382 dir = c==3? "send": "recv";
383 pkt = c==3? &spkt: &rpkt;
384 printf("end %s", dir);
386 printf(" [%d bytes in incomplete packet]", pkt->cnt);
393 for (c = 3; c > 0; --c)
394 n = (n << 8) + getc(f);
396 printf("time %.1fs\n", (double) n / 10);
400 t = (t << 8) + getc(f);
401 t = (t << 8) + getc(f);
402 t = (t << 8) + getc(f);
403 printf("start %s", ctime(&t));
411 extern struct compressor ppp_bsd_compress, ppp_deflate;
413 struct compressor *compressors[] = {
423 handle_ccp(cp, dp, len)
429 struct compressor **comp;
431 if (len < CCP_HDRLEN)
433 clen = CCP_LENGTH(dp);
437 switch (CCP_CODE(dp)) {
439 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
440 if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
441 || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
445 for (comp = compressors; *comp != NULL; ++comp) {
446 if ((*comp)->compress_proto == dp[0]) {
447 if (cp->state != NULL) {
448 (*cp->comp->decomp_free)(cp->state);
452 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
453 cp->flags |= CCP_ISUP;
454 if (cp->state != NULL
455 && (*cp->comp->decomp_init)
456 (cp->state, dp, clen, 0, 0, 8192, 1))
457 cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
465 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
469 if (cp->flags & CCP_ISUP) {
470 if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
471 (*cp->comp->decomp_reset)(cp->state);
472 cp->flags &= ~CCP_ERROR;