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 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The name(s) of the authors of this software must not be used to
20 * endorse or promote products derived from this software without
21 * prior written permission.
23 * 4. Redistributions of any form whatsoever must retain the following
25 * "This product includes software developed by Paul Mackerras
26 * <paulus@ozlabs.org>".
28 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
29 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
30 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
31 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
32 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
33 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
34 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40 #include <sys/types.h>
51 int start_time_tenths;
52 int tot_sent, tot_rcvd;
71 while ((i = getopt(ac, av, "hprdm:a")) != -1) {
92 fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av[0]);
99 for (i = optind; i < ac; ++i) {
101 if ((f = fopen(p, "r")) == NULL) {
121 unsigned char buf[16];
123 while ((c = getc(f)) != EOF) {
129 printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
132 n = (n << 8) + getc(f);
133 *(c==1? &tot_sent: &tot_rcvd) += n;
144 for (k = 0; k < nb; ++k) {
146 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
154 k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
155 if ((col += k) >= 78) {
173 for (k = nb; k < 16; ++k)
176 for (k = 0; k < nb; ++k) {
178 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
186 printf("end %s\n", c==3? "send": "recv");
194 printf("?%.2x\n", c);
200 * FCS lookup table as calculated by genfcstab.
202 static u_short fcstab[256] = {
203 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
204 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
205 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
206 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
207 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
208 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
209 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
210 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
211 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
212 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
213 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
214 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
215 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
216 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
217 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
218 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
219 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
220 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
221 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
222 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
223 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
224 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
225 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
226 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
227 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
228 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
229 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
230 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
231 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
232 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
233 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
234 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
236 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
242 struct compressor *comp;
244 unsigned char buf[8192];
247 /* Values for flags */
250 #define CCP_FATALERROR 4
251 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
252 #define CCP_DECOMP_RUN 8
254 unsigned char dbuf[8192];
261 int nb, nl, dn, proto, rv;
263 unsigned char *p, *r, *endp;
268 spkt.cnt = rpkt.cnt = 0;
269 spkt.esc = rpkt.esc = 0;
270 while ((c = getc(f)) != EOF) {
276 dir = c==1? "sent": "rcvd";
277 pkt = c==1? &spkt: &rpkt;
279 n = (n << 8) + getc(f);
280 *(c==1? &tot_sent: &tot_rcvd) += n;
287 printf("[%d bytes in incomplete send packet]\n",
290 printf("[%d bytes in incomplete recv packet]\n",
297 printf("%s aborted packet:\n ", dir);
300 if (pkt->cnt >= sizeof(pkt->buf)) {
301 printf("%s over-long packet truncated:\n ", dir);
309 printf("%s short packet [%d bytes]:", q, nb);
310 for (k = 0; k < nb; ++k)
311 printf(" %.2x", p[k]);
316 for (k = 0; k < nb; ++k)
317 fcs = PPP_FCS(fcs, p[k]);
322 if (r[0] == 0xff && r[1] == 3)
328 printf(" ERROR: length (%zd) > MRU (%d)\n",
330 if (decompress && fcs == PPP_GOODFCS) {
331 /* See if this is a CCP or compressed packet */
334 if (r[0] == 0xff && r[1] == 3) {
339 if ((proto & 1) == 0)
340 proto = (proto << 8) + r[1];
341 if (proto == PPP_CCP) {
342 handle_ccp(pkt, r + 2, endp - r - 2);
343 } else if (proto == PPP_COMP) {
344 if ((pkt->flags & CCP_ISUP)
345 && (pkt->flags & CCP_DECOMP_RUN)
347 && (pkt->flags & CCP_ERR) == 0) {
348 rv = pkt->comp->decompress(pkt->state, r,
358 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
361 printf(" DECOMPRESSION ERROR\n");
362 pkt->flags |= CCP_ERROR;
364 case DECOMP_FATALERROR:
365 printf(" FATAL DECOMPRESSION ERROR\n");
366 pkt->flags |= CCP_FATALERROR;
370 } else if (pkt->state
371 && (pkt->flags & CCP_DECOMP_RUN)) {
372 pkt->comp->incomp(pkt->state, r, endp - r);
376 nl = nb < 16? nb: 16;
378 for (k = 0; k < nl; ++k)
379 printf(" %.2x", p[k]);
383 for (k = 0; k < nl; ++k) {
385 putchar((' ' <= c && c <= '~')? c: '.');
392 if (fcs != PPP_GOODFCS)
393 printf(" BAD FCS: (residue = %x)\n", fcs);
401 /* else fall through */
407 if (pkt->cnt < sizeof(pkt->buf))
408 pkt->buf[pkt->cnt++] = c;
417 dir = c==3? "send": "recv";
418 pkt = c==3? &spkt: &rpkt;
419 printf("end %s", dir);
421 printf(" [%d bytes in incomplete packet]", pkt->cnt);
430 printf("?%.2x\n", c);
435 extern struct compressor ppp_bsd_compress, ppp_deflate;
437 struct compressor *compressors[] = {
448 handle_ccp(cp, dp, len)
454 struct compressor **comp;
456 if (len < CCP_HDRLEN)
458 clen = CCP_LENGTH(dp);
462 switch (CCP_CODE(dp)) {
464 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
465 if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
466 || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
470 for (comp = compressors; *comp != NULL; ++comp) {
471 if ((*comp)->compress_proto == dp[0]) {
472 if (cp->state != NULL) {
473 (*cp->comp->decomp_free)(cp->state);
477 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
478 cp->flags |= CCP_ISUP;
479 if (cp->state != NULL
480 && (*cp->comp->decomp_init)
481 (cp->state, dp, clen, 0, 0, 8192, 1))
482 cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
490 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
494 if (cp->flags & CCP_ISUP) {
495 if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
496 (*cp->comp->decomp_reset)(cp->state);
497 cp->flags &= ~CCP_ERROR;
515 t = (t << 8) + getc(f);
516 t = (t << 8) + getc(f);
517 t = (t << 8) + getc(f);
518 printf("start %s", ctime(&t));
520 start_time_tenths = 0;
521 tot_sent = tot_rcvd = 0;
525 for (c = 3; c > 0; --c)
526 n = (n << 8) + getc(f);
529 n += start_time_tenths;
530 start_time += n / 10;
531 start_time_tenths = n % 10;
532 tm = localtime(&start_time);
533 printf("time %.2d:%.2d:%.2d.%d", tm->tm_hour, tm->tm_min,
534 tm->tm_sec, start_time_tenths);
535 printf(" (sent %d, rcvd %d)\n", tot_sent, tot_rcvd);
537 printf("time %.1fs\n", (double) n / 10);