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.
39 #include <sys/types.h>
50 int start_time_tenths;
51 int tot_sent, tot_rcvd;
64 while ((i = getopt(ac, av, "hprdm:a")) != -1) {
85 fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av[0]);
92 for (i = optind; i < ac; ++i) {
94 if ((f = fopen(p, "r")) == NULL) {
113 unsigned char buf[16];
115 while ((c = getc(f)) != EOF) {
121 printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
124 n = (n << 8) + getc(f);
125 *(c==1? &tot_sent: &tot_rcvd) += n;
136 for (k = 0; k < nb; ++k) {
138 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
146 k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
147 if ((col += k) >= 78) {
165 for (k = nb; k < 16; ++k)
168 for (k = 0; k < nb; ++k) {
170 putchar((' ' <= c2 && c2 <= '~')? c2: '.');
178 printf("end %s\n", c==3? "send": "recv");
192 * FCS lookup table as calculated by genfcstab.
194 static u_short fcstab[256] = {
195 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
196 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
197 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
198 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
199 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
200 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
201 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
202 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
203 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
204 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
205 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
206 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
207 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
208 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
209 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
210 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
211 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
212 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
213 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
214 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
215 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
216 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
217 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
218 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
219 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
220 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
221 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
222 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
223 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
224 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
225 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
226 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
233 struct compressor *comp;
235 unsigned char buf[8192];
238 /* Values for flags */
241 #define CCP_FATALERROR 4
242 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
243 #define CCP_DECOMP_RUN 8
245 unsigned char dbuf[8192];
251 int nb, nl, dn, proto, rv;
253 unsigned char *p, *r, *endp;
258 spkt.cnt = rpkt.cnt = 0;
259 spkt.esc = rpkt.esc = 0;
260 while ((c = getc(f)) != EOF) {
266 dir = c==1? "sent": "rcvd";
267 pkt = c==1? &spkt: &rpkt;
269 n = (n << 8) + getc(f);
270 *(c==1? &tot_sent: &tot_rcvd) += n;
277 printf("[%d bytes in incomplete send packet]\n",
280 printf("[%d bytes in incomplete recv packet]\n",
287 printf("%s aborted packet:\n ", dir);
295 printf("%s short packet [%d bytes]:", q, nb);
296 for (k = 0; k < nb; ++k)
297 printf(" %.2x", p[k]);
302 for (k = 0; k < nb; ++k)
303 fcs = PPP_FCS(fcs, p[k]);
308 if (r[0] == 0xff && r[1] == 3)
314 printf(" ERROR: length (%d) > MRU (%d)\n",
316 if (decompress && fcs == PPP_GOODFCS) {
317 /* See if this is a CCP or compressed packet */
320 if (r[0] == 0xff && r[1] == 3) {
325 if ((proto & 1) == 0)
326 proto = (proto << 8) + r[1];
327 if (proto == PPP_CCP) {
328 handle_ccp(pkt, r + 2, endp - r - 2);
329 } else if (proto == PPP_COMP) {
330 if ((pkt->flags & CCP_ISUP)
331 && (pkt->flags & CCP_DECOMP_RUN)
333 && (pkt->flags & CCP_ERR) == 0) {
334 rv = pkt->comp->decompress(pkt->state, r,
344 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
347 printf(" DECOMPRESSION ERROR\n");
348 pkt->flags |= CCP_ERROR;
350 case DECOMP_FATALERROR:
351 printf(" FATAL DECOMPRESSION ERROR\n");
352 pkt->flags |= CCP_FATALERROR;
356 } else if (pkt->state
357 && (pkt->flags & CCP_DECOMP_RUN)) {
358 pkt->comp->incomp(pkt->state, r, endp - r);
362 nl = nb < 16? nb: 16;
364 for (k = 0; k < nl; ++k)
365 printf(" %.2x", p[k]);
369 for (k = 0; k < nl; ++k) {
371 putchar((' ' <= c && c <= '~')? c: '.');
378 if (fcs != PPP_GOODFCS)
379 printf(" BAD FCS: (residue = %x)\n", fcs);
387 /* else fall through */
393 pkt->buf[pkt->cnt++] = c;
402 dir = c==3? "send": "recv";
403 pkt = c==3? &spkt: &rpkt;
404 printf("end %s", dir);
406 printf(" [%d bytes in incomplete packet]", pkt->cnt);
420 extern struct compressor ppp_bsd_compress, ppp_deflate;
422 struct compressor *compressors[] = {
432 handle_ccp(cp, dp, len)
438 struct compressor **comp;
440 if (len < CCP_HDRLEN)
442 clen = CCP_LENGTH(dp);
446 switch (CCP_CODE(dp)) {
448 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
449 if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
450 || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
454 for (comp = compressors; *comp != NULL; ++comp) {
455 if ((*comp)->compress_proto == dp[0]) {
456 if (cp->state != NULL) {
457 (*cp->comp->decomp_free)(cp->state);
461 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
462 cp->flags |= CCP_ISUP;
463 if (cp->state != NULL
464 && (*cp->comp->decomp_init)
465 (cp->state, dp, clen, 0, 0, 8192, 1))
466 cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
474 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
478 if (cp->flags & CCP_ISUP) {
479 if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
480 (*cp->comp->decomp_reset)(cp->state);
481 cp->flags &= ~CCP_ERROR;
498 t = (t << 8) + getc(f);
499 t = (t << 8) + getc(f);
500 t = (t << 8) + getc(f);
501 printf("start %s", ctime(&t));
503 start_time_tenths = 0;
504 tot_sent = tot_rcvd = 0;
508 for (c = 3; c > 0; --c)
509 n = (n << 8) + getc(f);
512 n += start_time_tenths;
513 start_time += n / 10;
514 start_time_tenths = n % 10;
515 tm = localtime(&start_time);
516 printf("time %.2d:%.2d:%.2d.%d", tm->tm_hour, tm->tm_min,
517 tm->tm_sec, start_time_tenths);
518 printf(" (sent %d, rcvd %d)\n", tot_sent, tot_rcvd);
520 printf("time %.1fs\n", (double) n / 10);