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>
34 while ((i = getopt(ac, av, "hprdm:")) != -1) {
52 fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [file ...]\n", av[0]);
59 for (i = optind; i < ac; ++i) {
61 if ((f = fopen(p, "r")) == NULL) {
81 unsigned char buf[16];
84 while ((c = getc(f)) != EOF) {
90 printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
93 n = (n << 8) + getc(f);
104 for (k = 0; k < nb; ++k) {
106 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
114 k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
115 if ((col += k) >= 78) {
133 for (k = nb; k < 16; ++k)
136 for (k = 0; k < nb; ++k) {
138 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
146 printf("end %s\n", c==3? "send": "recv");
152 for (c = 3; c > 0; --c)
153 n = (n << 8) + getc(f);
155 printf("time %.1fs\n", (double) n / 10);
159 t = (t << 8) + getc(f);
160 t = (t << 8) + getc(f);
161 t = (t << 8) + getc(f);
162 printf("start %s", ctime(&t));
171 * FCS lookup table as calculated by genfcstab.
173 static u_short fcstab[256] = {
174 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
175 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
176 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
177 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
178 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
179 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
180 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
181 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
182 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
183 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
184 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
185 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
186 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
187 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
188 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
189 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
190 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
191 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
192 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
193 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
194 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
195 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
196 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
197 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
198 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
199 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
200 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
201 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
202 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
203 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
204 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
205 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
212 struct compressor *comp;
214 unsigned char buf[8192];
217 /* Values for flags */
220 #define CCP_FATALERROR 4
221 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
222 #define CCP_DECOMP_RUN 8
224 unsigned char dbuf[8192];
230 int nb, nl, dn, proto, rv;
232 unsigned char *p, *r, *endp;
238 spkt.cnt = rpkt.cnt = 0;
239 spkt.esc = rpkt.esc = 0;
240 while ((c = getc(f)) != EOF) {
246 dir = c==1? "sent": "rcvd";
247 pkt = c==1? &spkt: &rpkt;
249 n = (n << 8) + getc(f);
256 printf("[%d bytes in incomplete send packet]\n",
259 printf("[%d bytes in incomplete recv packet]\n",
266 printf("%s aborted packet:\n ", dir);
274 printf("%s short packet [%d bytes]:", q, nb);
275 for (k = 0; k < nb; ++k)
276 printf(" %.2x", p[k]);
281 for (k = 0; k < nb; ++k)
282 fcs = PPP_FCS(fcs, p[k]);
287 if (r[0] == 0xff && r[1] == 3)
293 printf(" ERROR: length (%d) > MRU (%d)\n",
295 if (decompress && fcs == PPP_GOODFCS) {
296 /* See if this is a CCP or compressed packet */
299 if (r[0] == 0xff && r[1] == 3) {
304 if ((proto & 1) == 0)
305 proto = (proto << 8) + r[1];
306 if (proto == PPP_CCP) {
307 handle_ccp(pkt, r + 2, endp - r - 2);
308 } else if (proto == PPP_COMP) {
309 if ((pkt->flags & CCP_ISUP)
310 && (pkt->flags & CCP_DECOMP_RUN)
312 && (pkt->flags & CCP_ERR) == 0) {
313 rv = pkt->comp->decompress(pkt->state, r,
323 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
326 printf(" DECOMPRESSION ERROR\n");
327 pkt->flags |= CCP_ERROR;
329 case DECOMP_FATALERROR:
330 printf(" FATAL DECOMPRESSION ERROR\n");
331 pkt->flags |= CCP_FATALERROR;
335 } else if (pkt->state
336 && (pkt->flags & CCP_DECOMP_RUN)) {
337 pkt->comp->incomp(pkt->state, r, endp - r);
341 nl = nb < 16? nb: 16;
343 for (k = 0; k < nl; ++k)
344 printf(" %.2x", p[k]);
348 for (k = 0; k < nl; ++k) {
350 putchar((' ' <= c && c <= '~')? c: '.');
357 if (fcs != PPP_GOODFCS)
358 printf(" BAD FCS: (residue = %x)\n", fcs);
366 /* else fall through */
372 pkt->buf[pkt->cnt++] = c;
381 dir = c==3? "send": "recv";
382 pkt = c==3? &spkt: &rpkt;
383 printf("end %s", dir);
385 printf(" [%d bytes in incomplete packet]", pkt->cnt);
392 for (c = 3; c > 0; --c)
393 n = (n << 8) + getc(f);
395 printf("time %.1fs\n", (double) n / 10);
399 t = (t << 8) + getc(f);
400 t = (t << 8) + getc(f);
401 t = (t << 8) + getc(f);
402 printf("start %s", ctime(&t));
410 extern struct compressor ppp_bsd_compress, ppp_deflate;
412 struct compressor *compressors[] = {
422 handle_ccp(cp, dp, len)
428 struct compressor **comp;
430 if (len < CCP_HDRLEN)
432 clen = CCP_LENGTH(dp);
436 switch (CCP_CODE(dp)) {
438 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
439 if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
440 || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
444 for (comp = compressors; *comp != NULL; ++comp) {
445 if ((*comp)->compress_proto == dp[0]) {
446 if (cp->state != NULL) {
447 (*cp->comp->decomp_free)(cp->state);
451 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
452 cp->flags |= CCP_ISUP;
453 if (cp->state != NULL
454 && (*cp->comp->decomp_init)
455 (cp->state, dp, clen, 0, 0, 8192, 1))
456 cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
464 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
468 if (cp->flags & CCP_ISUP) {
469 if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
470 (*cp->comp->decomp_reset)(cp->state);
471 cp->flags &= ~CCP_ERROR;