]> git.ozlabs.org Git - ppp.git/blob - pppdump/pppdump.c
__linux__ (already defined by compiler) not _linux_ (manually defined)
[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 are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms.  The name of the author
10  * may not be used to endorse or promote products derived
11  * from this software without specific prior written permission.
12  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  */
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include "ppp_defs.h"
21 #include "ppp-comp.h"
22
23 int hexmode;
24 int pppmode;
25 int reverse;
26 int decompress;
27 int mru = 1500;
28 int abs_times;
29 time_t start_time;
30 int start_time_tenths;
31 int tot_sent, tot_rcvd;
32
33 extern int optind;
34 extern char *optarg;
35
36 main(ac, av)
37     int ac;
38     char **av;
39 {
40     int i;
41     char *p;
42     FILE *f;
43
44     while ((i = getopt(ac, av, "hprdm:a")) != -1) {
45         switch (i) {
46         case 'h':
47             hexmode = 1;
48             break;
49         case 'p':
50             pppmode = 1;
51             break;
52         case 'r':
53             reverse = 1;
54             break;
55         case 'd':
56             decompress = 1;
57             break;
58         case 'm':
59             mru = atoi(optarg);
60             break;
61         case 'a':
62             abs_times = 1;
63             break;
64         default:
65             fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av[0]);
66             exit(1);
67         }
68     }
69     if (optind >= ac)
70         dumplog(stdin);
71     else {
72         for (i = optind; i < ac; ++i) {
73             p = av[i];
74             if ((f = fopen(p, "r")) == NULL) {
75                 perror(p);
76                 exit(1);
77             }
78             if (pppmode)
79                 dumpppp(f);
80             else
81                 dumplog(f);
82             fclose(f);
83         }
84     }
85     exit(0);
86 }
87
88 dumplog(f)
89     FILE *f;
90 {
91     int c, n, k, col;
92     int nb, c2;
93     unsigned char buf[16];
94
95     while ((c = getc(f)) != EOF) {
96         switch (c) {
97         case 1:
98         case 2:
99             if (reverse)
100                 c = 3 - c;
101             printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
102             col = 6;
103             n = getc(f);
104             n = (n << 8) + getc(f);
105             *(c==1? &tot_sent: &tot_rcvd) += n;
106             nb = 0;
107             for (; n > 0; --n) {
108                 c = getc(f);
109                 if (c == EOF) {
110                     printf("\nEOF\n");
111                     exit(0);
112                 }
113                 if (hexmode) {
114                     if (nb >= 16) {
115                         printf("  ");
116                         for (k = 0; k < nb; ++k) {
117                             c2 = buf[k];
118                             putchar((' ' <= c2 && c2 <= '~')? c2: '.');
119                         }
120                         printf("\n      ");
121                         nb = 0;
122                     }
123                     buf[nb++] = c;
124                     printf(" %.2x", c);
125                 } else {
126                     k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
127                     if ((col += k) >= 78) {
128                         printf("\n      ");
129                         col = 6 + k;
130                     }
131                     switch (k) {
132                     case 1:
133                         putchar(c);
134                         break;
135                     case 2:
136                         printf("\\%c", c);
137                         break;
138                     case 3:
139                         printf("\\%.2x", c);
140                         break;
141                     }
142                 }
143             }
144             if (hexmode) {
145                 for (k = nb; k < 16; ++k)
146                     printf("   ");
147                 printf("  ");
148                 for (k = 0; k < nb; ++k) {
149                     c2 = buf[k];
150                     putchar((' ' <= c2 && c2 <= '~')? c2: '.');
151                 }
152             } else
153                 putchar('"');
154             printf("\n");
155             break;
156         case 3:
157         case 4:
158             printf("end %s\n", c==3? "send": "recv");
159             break;
160         case 5:
161         case 6:
162         case 7:
163             show_time(f, c);
164             break;
165         default:
166             printf("?%.2x\n");
167         }
168     }
169 }
170
171 /*
172  * FCS lookup table as calculated by genfcstab.
173  */
174 static u_short fcstab[256] = {
175         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
176         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
177         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
178         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
179         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
180         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
181         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
182         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
183         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
184         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
185         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
186         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
187         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
188         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
189         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
190         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
191         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
192         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
193         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
194         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
195         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
196         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
197         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
198         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
199         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
200         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
201         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
202         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
203         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
204         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
205         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
206         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
207 };
208
209 struct pkt {
210     int cnt;
211     int esc;
212     int flags;
213     struct compressor *comp;
214     void *state;
215     unsigned char buf[8192];
216 } spkt, rpkt;
217
218 /* Values for flags */
219 #define CCP_ISUP        1
220 #define CCP_ERROR       2
221 #define CCP_FATALERROR  4
222 #define CCP_ERR         (CCP_ERROR | CCP_FATALERROR)
223 #define CCP_DECOMP_RUN  8
224
225 unsigned char dbuf[8192];
226
227 dumpppp(f)
228     FILE *f;
229 {
230     int c, n, k;
231     int nb, nl, dn, proto, rv;
232     char *dir, *q;
233     unsigned char *p, *r, *endp;
234     unsigned char *d;
235     unsigned short fcs;
236     struct pkt *pkt;
237
238     spkt.cnt = rpkt.cnt = 0;
239     spkt.esc = rpkt.esc = 0;
240     while ((c = getc(f)) != EOF) {
241         switch (c) {
242         case 1:
243         case 2:
244             if (reverse)
245                 c = 3 - c;
246             dir = c==1? "sent": "rcvd";
247             pkt = c==1? &spkt: &rpkt;
248             n = getc(f);
249             n = (n << 8) + getc(f);
250             *(c==1? &tot_sent: &tot_rcvd) += n;
251             for (; n > 0; --n) {
252                 c = getc(f);
253                 switch (c) {
254                 case EOF:
255                     printf("\nEOF\n");
256                     if (spkt.cnt > 0)
257                         printf("[%d bytes in incomplete send packet]\n",
258                                spkt.cnt);
259                     if (rpkt.cnt > 0)
260                         printf("[%d bytes in incomplete recv packet]\n",
261                                rpkt.cnt);
262                     exit(0);
263                 case '~':
264                     if (pkt->cnt > 0) {
265                         q = dir;
266                         if (pkt->esc) {
267                             printf("%s aborted packet:\n     ", dir);
268                             q = "    ";
269                         }
270                         nb = pkt->cnt;
271                         p = pkt->buf;
272                         pkt->cnt = 0;
273                         pkt->esc = 0;
274                         if (nb <= 2) {
275                             printf("%s short packet [%d bytes]:", q, nb);
276                             for (k = 0; k < nb; ++k)
277                                 printf(" %.2x", p[k]);
278                             printf("\n");
279                             break;
280                         }
281                         fcs = PPP_INITFCS;
282                         for (k = 0; k < nb; ++k)
283                             fcs = PPP_FCS(fcs, p[k]);
284                         fcs &= 0xFFFF;
285                         nb -= 2;
286                         endp = p + nb;
287                         r = p;
288                         if (r[0] == 0xff && r[1] == 3)
289                             r += 2;
290                         if ((r[0] & 1) == 0)
291                             ++r;
292                         ++r;
293                         if (endp - r > mru)
294                             printf("     ERROR: length (%d) > MRU (%d)\n",
295                                    endp - r, mru);
296                         if (decompress && fcs == PPP_GOODFCS) {
297                             /* See if this is a CCP or compressed packet */
298                             d = dbuf;
299                             r = p;
300                             if (r[0] == 0xff && r[1] == 3) {
301                                 *d++ = *r++;
302                                 *d++ = *r++;
303                             }
304                             proto = r[0];
305                             if ((proto & 1) == 0)
306                                 proto = (proto << 8) + r[1];
307                             if (proto == PPP_CCP) {
308                                 handle_ccp(pkt, r + 2, endp - r - 2);
309                             } else if (proto == PPP_COMP) {
310                                 if ((pkt->flags & CCP_ISUP)
311                                     && (pkt->flags & CCP_DECOMP_RUN)
312                                     && pkt->state
313                                     && (pkt->flags & CCP_ERR) == 0) {
314                                     rv = pkt->comp->decompress(pkt->state, r,
315                                                         endp - r, d, &dn);
316                                     switch (rv) {
317                                     case DECOMP_OK:
318                                         p = dbuf;
319                                         nb = d + dn - p;
320                                         if ((d[0] & 1) == 0)
321                                             --dn;
322                                         --dn;
323                                         if (dn > mru)
324                                             printf("     ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
325                                         break;
326                                     case DECOMP_ERROR:
327                                         printf("     DECOMPRESSION ERROR\n");
328                                         pkt->flags |= CCP_ERROR;
329                                         break;
330                                     case DECOMP_FATALERROR:
331                                         printf("     FATAL DECOMPRESSION ERROR\n");
332                                         pkt->flags |= CCP_FATALERROR;
333                                         break;
334                                     }
335                                 }
336                             } else if (pkt->state
337                                        && (pkt->flags & CCP_DECOMP_RUN)) {
338                                 pkt->comp->incomp(pkt->state, r, endp - r);
339                             }
340                         }
341                         do {
342                             nl = nb < 16? nb: 16;
343                             printf("%s ", q);
344                             for (k = 0; k < nl; ++k)
345                                 printf(" %.2x", p[k]);
346                             for (; k < 16; ++k)
347                                 printf("   ");
348                             printf("  ");
349                             for (k = 0; k < nl; ++k) {
350                                 c = p[k];
351                                 putchar((' ' <= c && c <= '~')? c: '.');
352                             }
353                             printf("\n");
354                             q = "    ";
355                             p += nl;
356                             nb -= nl;
357                         } while (nb > 0);
358                         if (fcs != PPP_GOODFCS)
359                             printf("     BAD FCS: (residue = %x)\n", fcs);
360                     }
361                     break;
362                 case '}':
363                     if (!pkt->esc) {
364                         pkt->esc = 1;
365                         break;
366                     }
367                     /* else fall through */
368                 default:
369                     if (pkt->esc) {
370                         c ^= 0x20;
371                         pkt->esc = 0;
372                     }
373                     pkt->buf[pkt->cnt++] = c;
374                     break;
375                 }
376             }
377             break;
378         case 3:
379         case 4:
380             if (reverse)
381                 c = 7 - c;
382             dir = c==3? "send": "recv";
383             pkt = c==3? &spkt: &rpkt;
384             printf("end %s", dir);
385             if (pkt->cnt > 0)
386                 printf("  [%d bytes in incomplete packet]", pkt->cnt);
387             printf("\n");
388             break;
389         case 5:
390         case 6:
391         case 7:
392             show_time(f, c);
393             break;
394         default:
395             printf("?%.2x\n");
396         }
397     }
398 }
399
400 extern struct compressor ppp_bsd_compress, ppp_deflate;
401
402 struct compressor *compressors[] = {
403 #if DO_BSD_COMPRESS
404     &ppp_bsd_compress,
405 #endif
406 #if DO_DEFLATE
407     &ppp_deflate,
408 #endif
409     NULL
410 };
411
412 handle_ccp(cp, dp, len)
413     struct pkt *cp;
414     u_char *dp;
415     int len;
416 {
417     int clen;
418     struct compressor **comp;
419
420     if (len < CCP_HDRLEN)
421         return;
422     clen = CCP_LENGTH(dp);
423     if (clen > len)
424         return;
425
426     switch (CCP_CODE(dp)) {
427     case CCP_CONFACK:
428         cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
429         if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
430             || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
431             break;
432         dp += CCP_HDRLEN;
433         clen -= CCP_HDRLEN;
434         for (comp = compressors; *comp != NULL; ++comp) {
435             if ((*comp)->compress_proto == dp[0]) {
436                 if (cp->state != NULL) {
437                     (*cp->comp->decomp_free)(cp->state);
438                     cp->state = NULL;
439                 }
440                 cp->comp = *comp;
441                 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
442                 cp->flags |= CCP_ISUP;
443                 if (cp->state != NULL
444                     && (*cp->comp->decomp_init)
445                         (cp->state, dp, clen, 0, 0, 8192, 1))
446                     cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
447                 break;
448             }
449         }
450         break;
451
452     case CCP_CONFNAK:
453     case CCP_CONFREJ:
454         cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
455         break;
456
457     case CCP_RESETACK:
458         if (cp->flags & CCP_ISUP) {
459             if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
460                 (*cp->comp->decomp_reset)(cp->state);
461                 cp->flags &= ~CCP_ERROR;
462             }
463         }
464         break;
465     }
466 }
467
468 show_time(f, c)
469     FILE *f;
470     int c;
471 {
472     time_t t;
473     int n;
474     struct tm *tm;
475
476     if (c == 7) {
477         t = getc(f);
478         t = (t << 8) + getc(f);
479         t = (t << 8) + getc(f);
480         t = (t << 8) + getc(f);
481         printf("start %s", ctime(&t));
482         start_time = t;
483         start_time_tenths = 0;
484         tot_sent = tot_rcvd = 0;
485     } else {
486         n = getc(f);
487         if (c == 5) {
488             for (c = 3; c > 0; --c)
489                 n = (n << 8) + getc(f);
490         }
491         if (abs_times) {
492             n += start_time_tenths;
493             start_time += n / 10;
494             start_time_tenths = n % 10;
495             tm = localtime(&start_time);
496             printf("time  %.2d:%.2d:%.2d.%d", tm->tm_hour, tm->tm_min,
497                    tm->tm_sec, start_time_tenths);
498             printf("  (sent %d, rcvd %d)\n", tot_sent, tot_rcvd);
499         } else
500             printf("time  %.1fs\n", (double) n / 10);
501     }
502 }