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@samba.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>
41 #include <net/ppp_defs.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);
305 printf("%s short packet [%d bytes]:", q, nb);
306 for (k = 0; k < nb; ++k)
307 printf(" %.2x", p[k]);
312 for (k = 0; k < nb; ++k)
313 fcs = PPP_FCS(fcs, p[k]);
318 if (r[0] == 0xff && r[1] == 3)
324 printf(" ERROR: length (%zd) > MRU (%d)\n",
326 if (decompress && fcs == PPP_GOODFCS) {
327 /* See if this is a CCP or compressed packet */
330 if (r[0] == 0xff && r[1] == 3) {
335 if ((proto & 1) == 0)
336 proto = (proto << 8) + r[1];
337 if (proto == PPP_CCP) {
338 handle_ccp(pkt, r + 2, endp - r - 2);
339 } else if (proto == PPP_COMP) {
340 if ((pkt->flags & CCP_ISUP)
341 && (pkt->flags & CCP_DECOMP_RUN)
343 && (pkt->flags & CCP_ERR) == 0) {
344 rv = pkt->comp->decompress(pkt->state, r,
354 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
357 printf(" DECOMPRESSION ERROR\n");
358 pkt->flags |= CCP_ERROR;
360 case DECOMP_FATALERROR:
361 printf(" FATAL DECOMPRESSION ERROR\n");
362 pkt->flags |= CCP_FATALERROR;
366 } else if (pkt->state
367 && (pkt->flags & CCP_DECOMP_RUN)) {
368 pkt->comp->incomp(pkt->state, r, endp - r);
372 nl = nb < 16? nb: 16;
374 for (k = 0; k < nl; ++k)
375 printf(" %.2x", p[k]);
379 for (k = 0; k < nl; ++k) {
381 putchar((' ' <= c && c <= '~')? c: '.');
388 if (fcs != PPP_GOODFCS)
389 printf(" BAD FCS: (residue = %x)\n", fcs);
397 /* else fall through */
403 pkt->buf[pkt->cnt++] = c;
412 dir = c==3? "send": "recv";
413 pkt = c==3? &spkt: &rpkt;
414 printf("end %s", dir);
416 printf(" [%d bytes in incomplete packet]", pkt->cnt);
425 printf("?%.2x\n", c);
430 extern struct compressor ppp_bsd_compress, ppp_deflate;
432 struct compressor *compressors[] = {
443 handle_ccp(cp, dp, len)
449 struct compressor **comp;
451 if (len < CCP_HDRLEN)
453 clen = CCP_LENGTH(dp);
457 switch (CCP_CODE(dp)) {
459 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
460 if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
461 || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
465 for (comp = compressors; *comp != NULL; ++comp) {
466 if ((*comp)->compress_proto == dp[0]) {
467 if (cp->state != NULL) {
468 (*cp->comp->decomp_free)(cp->state);
472 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
473 cp->flags |= CCP_ISUP;
474 if (cp->state != NULL
475 && (*cp->comp->decomp_init)
476 (cp->state, dp, clen, 0, 0, 8192, 1))
477 cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
485 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
489 if (cp->flags & CCP_ISUP) {
490 if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
491 (*cp->comp->decomp_reset)(cp->state);
492 cp->flags &= ~CCP_ERROR;
510 t = (t << 8) + getc(f);
511 t = (t << 8) + getc(f);
512 t = (t << 8) + getc(f);
513 printf("start %s", ctime(&t));
515 start_time_tenths = 0;
516 tot_sent = tot_rcvd = 0;
520 for (c = 3; c > 0; --c)
521 n = (n << 8) + getc(f);
524 n += start_time_tenths;
525 start_time += n / 10;
526 start_time_tenths = n % 10;
527 tm = localtime(&start_time);
528 printf("time %.2d:%.2d:%.2d.%d", tm->tm_hour, tm->tm_min,
529 tm->tm_sec, start_time_tenths);
530 printf(" (sent %d, rcvd %d)\n", tot_sent, tot_rcvd);
532 printf("time %.1fs\n", (double) n / 10);