]> git.ozlabs.org Git - ppp.git/blob - pppdump/pppdump.c
Repaired bad LCP Configure-Nak generated to request EAP instead of PAP.
[ppp.git] / pppdump / pppdump.c
1 /*
2  * pppdump - print out the contents of a record file generated by
3  * pppd in readable form.
4  *
5  * Copyright (c) 1999 Paul Mackerras. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
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
17  *    distribution.
18  *
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.
22  *
23  * 4. Redistributions of any form whatsoever must retain the following
24  *    acknowledgment:
25  *    "This product includes software developed by Paul Mackerras
26  *     <paulus@samba.org>".
27  *
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.
35  */
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <time.h>
39 #include <sys/types.h>
40 #include "ppp_defs.h"
41 #include "ppp-comp.h"
42
43 int hexmode;
44 int pppmode;
45 int reverse;
46 int decompress;
47 int mru = 1500;
48 int abs_times;
49 time_t start_time;
50 int start_time_tenths;
51 int tot_sent, tot_rcvd;
52
53 extern int optind;
54 extern char *optarg;
55
56 main(ac, av)
57     int ac;
58     char **av;
59 {
60     int i;
61     char *p;
62     FILE *f;
63
64     while ((i = getopt(ac, av, "hprdm:a")) != -1) {
65         switch (i) {
66         case 'h':
67             hexmode = 1;
68             break;
69         case 'p':
70             pppmode = 1;
71             break;
72         case 'r':
73             reverse = 1;
74             break;
75         case 'd':
76             decompress = 1;
77             break;
78         case 'm':
79             mru = atoi(optarg);
80             break;
81         case 'a':
82             abs_times = 1;
83             break;
84         default:
85             fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av[0]);
86             exit(1);
87         }
88     }
89     if (optind >= ac)
90         dumplog(stdin);
91     else {
92         for (i = optind; i < ac; ++i) {
93             p = av[i];
94             if ((f = fopen(p, "r")) == NULL) {
95                 perror(p);
96                 exit(1);
97             }
98             if (pppmode)
99                 dumpppp(f);
100             else
101                 dumplog(f);
102             fclose(f);
103         }
104     }
105     exit(0);
106 }
107
108 dumplog(f)
109     FILE *f;
110 {
111     int c, n, k, col;
112     int nb, c2;
113     unsigned char buf[16];
114
115     while ((c = getc(f)) != EOF) {
116         switch (c) {
117         case 1:
118         case 2:
119             if (reverse)
120                 c = 3 - c;
121             printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
122             col = 6;
123             n = getc(f);
124             n = (n << 8) + getc(f);
125             *(c==1? &tot_sent: &tot_rcvd) += n;
126             nb = 0;
127             for (; n > 0; --n) {
128                 c = getc(f);
129                 if (c == EOF) {
130                     printf("\nEOF\n");
131                     exit(0);
132                 }
133                 if (hexmode) {
134                     if (nb >= 16) {
135                         printf("  ");
136                         for (k = 0; k < nb; ++k) {
137                             c2 = buf[k];
138                             putchar((' ' <= c2 && c2 <= '~')? c2: '.');
139                         }
140                         printf("\n      ");
141                         nb = 0;
142                     }
143                     buf[nb++] = c;
144                     printf(" %.2x", c);
145                 } else {
146                     k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
147                     if ((col += k) >= 78) {
148                         printf("\n      ");
149                         col = 6 + k;
150                     }
151                     switch (k) {
152                     case 1:
153                         putchar(c);
154                         break;
155                     case 2:
156                         printf("\\%c", c);
157                         break;
158                     case 3:
159                         printf("\\%.2x", c);
160                         break;
161                     }
162                 }
163             }
164             if (hexmode) {
165                 for (k = nb; k < 16; ++k)
166                     printf("   ");
167                 printf("  ");
168                 for (k = 0; k < nb; ++k) {
169                     c2 = buf[k];
170                     putchar((' ' <= c2 && c2 <= '~')? c2: '.');
171                 }
172             } else
173                 putchar('"');
174             printf("\n");
175             break;
176         case 3:
177         case 4:
178             printf("end %s\n", c==3? "send": "recv");
179             break;
180         case 5:
181         case 6:
182         case 7:
183             show_time(f, c);
184             break;
185         default:
186             printf("?%.2x\n");
187         }
188     }
189 }
190
191 /*
192  * FCS lookup table as calculated by genfcstab.
193  */
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
227 };
228
229 struct pkt {
230     int cnt;
231     int esc;
232     int flags;
233     struct compressor *comp;
234     void *state;
235     unsigned char buf[8192];
236 } spkt, rpkt;
237
238 /* Values for flags */
239 #define CCP_ISUP        1
240 #define CCP_ERROR       2
241 #define CCP_FATALERROR  4
242 #define CCP_ERR         (CCP_ERROR | CCP_FATALERROR)
243 #define CCP_DECOMP_RUN  8
244
245 unsigned char dbuf[8192];
246
247 dumpppp(f)
248     FILE *f;
249 {
250     int c, n, k;
251     int nb, nl, dn, proto, rv;
252     char *dir, *q;
253     unsigned char *p, *r, *endp;
254     unsigned char *d;
255     unsigned short fcs;
256     struct pkt *pkt;
257
258     spkt.cnt = rpkt.cnt = 0;
259     spkt.esc = rpkt.esc = 0;
260     while ((c = getc(f)) != EOF) {
261         switch (c) {
262         case 1:
263         case 2:
264             if (reverse)
265                 c = 3 - c;
266             dir = c==1? "sent": "rcvd";
267             pkt = c==1? &spkt: &rpkt;
268             n = getc(f);
269             n = (n << 8) + getc(f);
270             *(c==1? &tot_sent: &tot_rcvd) += n;
271             for (; n > 0; --n) {
272                 c = getc(f);
273                 switch (c) {
274                 case EOF:
275                     printf("\nEOF\n");
276                     if (spkt.cnt > 0)
277                         printf("[%d bytes in incomplete send packet]\n",
278                                spkt.cnt);
279                     if (rpkt.cnt > 0)
280                         printf("[%d bytes in incomplete recv packet]\n",
281                                rpkt.cnt);
282                     exit(0);
283                 case '~':
284                     if (pkt->cnt > 0) {
285                         q = dir;
286                         if (pkt->esc) {
287                             printf("%s aborted packet:\n     ", dir);
288                             q = "    ";
289                         }
290                         nb = pkt->cnt;
291                         p = pkt->buf;
292                         pkt->cnt = 0;
293                         pkt->esc = 0;
294                         if (nb <= 2) {
295                             printf("%s short packet [%d bytes]:", q, nb);
296                             for (k = 0; k < nb; ++k)
297                                 printf(" %.2x", p[k]);
298                             printf("\n");
299                             break;
300                         }
301                         fcs = PPP_INITFCS;
302                         for (k = 0; k < nb; ++k)
303                             fcs = PPP_FCS(fcs, p[k]);
304                         fcs &= 0xFFFF;
305                         nb -= 2;
306                         endp = p + nb;
307                         r = p;
308                         if (r[0] == 0xff && r[1] == 3)
309                             r += 2;
310                         if ((r[0] & 1) == 0)
311                             ++r;
312                         ++r;
313                         if (endp - r > mru)
314                             printf("     ERROR: length (%d) > MRU (%d)\n",
315                                    endp - r, mru);
316                         if (decompress && fcs == PPP_GOODFCS) {
317                             /* See if this is a CCP or compressed packet */
318                             d = dbuf;
319                             r = p;
320                             if (r[0] == 0xff && r[1] == 3) {
321                                 *d++ = *r++;
322                                 *d++ = *r++;
323                             }
324                             proto = r[0];
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)
332                                     && pkt->state
333                                     && (pkt->flags & CCP_ERR) == 0) {
334                                     rv = pkt->comp->decompress(pkt->state, r,
335                                                         endp - r, d, &dn);
336                                     switch (rv) {
337                                     case DECOMP_OK:
338                                         p = dbuf;
339                                         nb = d + dn - p;
340                                         if ((d[0] & 1) == 0)
341                                             --dn;
342                                         --dn;
343                                         if (dn > mru)
344                                             printf("     ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
345                                         break;
346                                     case DECOMP_ERROR:
347                                         printf("     DECOMPRESSION ERROR\n");
348                                         pkt->flags |= CCP_ERROR;
349                                         break;
350                                     case DECOMP_FATALERROR:
351                                         printf("     FATAL DECOMPRESSION ERROR\n");
352                                         pkt->flags |= CCP_FATALERROR;
353                                         break;
354                                     }
355                                 }
356                             } else if (pkt->state
357                                        && (pkt->flags & CCP_DECOMP_RUN)) {
358                                 pkt->comp->incomp(pkt->state, r, endp - r);
359                             }
360                         }
361                         do {
362                             nl = nb < 16? nb: 16;
363                             printf("%s ", q);
364                             for (k = 0; k < nl; ++k)
365                                 printf(" %.2x", p[k]);
366                             for (; k < 16; ++k)
367                                 printf("   ");
368                             printf("  ");
369                             for (k = 0; k < nl; ++k) {
370                                 c = p[k];
371                                 putchar((' ' <= c && c <= '~')? c: '.');
372                             }
373                             printf("\n");
374                             q = "    ";
375                             p += nl;
376                             nb -= nl;
377                         } while (nb > 0);
378                         if (fcs != PPP_GOODFCS)
379                             printf("     BAD FCS: (residue = %x)\n", fcs);
380                     }
381                     break;
382                 case '}':
383                     if (!pkt->esc) {
384                         pkt->esc = 1;
385                         break;
386                     }
387                     /* else fall through */
388                 default:
389                     if (pkt->esc) {
390                         c ^= 0x20;
391                         pkt->esc = 0;
392                     }
393                     pkt->buf[pkt->cnt++] = c;
394                     break;
395                 }
396             }
397             break;
398         case 3:
399         case 4:
400             if (reverse)
401                 c = 7 - c;
402             dir = c==3? "send": "recv";
403             pkt = c==3? &spkt: &rpkt;
404             printf("end %s", dir);
405             if (pkt->cnt > 0)
406                 printf("  [%d bytes in incomplete packet]", pkt->cnt);
407             printf("\n");
408             break;
409         case 5:
410         case 6:
411         case 7:
412             show_time(f, c);
413             break;
414         default:
415             printf("?%.2x\n");
416         }
417     }
418 }
419
420 extern struct compressor ppp_bsd_compress, ppp_deflate;
421
422 struct compressor *compressors[] = {
423 #if DO_BSD_COMPRESS
424     &ppp_bsd_compress,
425 #endif
426 #if DO_DEFLATE
427     &ppp_deflate,
428 #endif
429     NULL
430 };
431
432 handle_ccp(cp, dp, len)
433     struct pkt *cp;
434     u_char *dp;
435     int len;
436 {
437     int clen;
438     struct compressor **comp;
439
440     if (len < CCP_HDRLEN)
441         return;
442     clen = CCP_LENGTH(dp);
443     if (clen > len)
444         return;
445
446     switch (CCP_CODE(dp)) {
447     case CCP_CONFACK:
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))
451             break;
452         dp += CCP_HDRLEN;
453         clen -= 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);
458                     cp->state = NULL;
459                 }
460                 cp->comp = *comp;
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;
467                 break;
468             }
469         }
470         break;
471
472     case CCP_CONFNAK:
473     case CCP_CONFREJ:
474         cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
475         break;
476
477     case CCP_RESETACK:
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;
482             }
483         }
484         break;
485     }
486 }
487
488 show_time(f, c)
489     FILE *f;
490     int c;
491 {
492     time_t t;
493     int n;
494     struct tm *tm;
495
496     if (c == 7) {
497         t = getc(f);
498         t = (t << 8) + getc(f);
499         t = (t << 8) + getc(f);
500         t = (t << 8) + getc(f);
501         printf("start %s", ctime(&t));
502         start_time = t;
503         start_time_tenths = 0;
504         tot_sent = tot_rcvd = 0;
505     } else {
506         n = getc(f);
507         if (c == 5) {
508             for (c = 3; c > 0; --c)
509                 n = (n << 8) + getc(f);
510         }
511         if (abs_times) {
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);
519         } else
520             printf("time  %.1fs\n", (double) n / 10);
521     }
522 }