]> git.ozlabs.org Git - ppp.git/blob - pppdump/pppdump.c
Makefile.am: Add explicit openssl directory to pppd include path
[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 <stdlib.h>
39 #include <time.h>
40 #include <sys/types.h>
41
42 #include "ppp-comp.h"
43
44 int hexmode;
45 int pppmode;
46 int reverse;
47 int decompress;
48 int mru = 1500;
49 int abs_times;
50 time_t start_time;
51 int start_time_tenths;
52 int tot_sent, tot_rcvd;
53
54 extern int optind;
55 extern char *optarg;
56
57 void dumplog();
58 void dumpppp();
59 void show_time();
60 void handle_ccp();
61
62 int
63 main(ac, av)
64     int ac;
65     char **av;
66 {
67     int i;
68     char *p;
69     FILE *f;
70
71     while ((i = getopt(ac, av, "hprdm:a")) != -1) {
72         switch (i) {
73         case 'h':
74             hexmode = 1;
75             break;
76         case 'p':
77             pppmode = 1;
78             break;
79         case 'r':
80             reverse = 1;
81             break;
82         case 'd':
83             decompress = 1;
84             break;
85         case 'm':
86             mru = atoi(optarg);
87             break;
88         case 'a':
89             abs_times = 1;
90             break;
91         default:
92             fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av[0]);
93             exit(1);
94         }
95     }
96     if (optind >= ac)
97         dumplog(stdin);
98     else {
99         for (i = optind; i < ac; ++i) {
100             p = av[i];
101             if ((f = fopen(p, "r")) == NULL) {
102                 perror(p);
103                 exit(1);
104             }
105             if (pppmode)
106                 dumpppp(f);
107             else
108                 dumplog(f);
109             fclose(f);
110         }
111     }
112     exit(0);
113 }
114
115 void
116 dumplog(f)
117     FILE *f;
118 {
119     int c, n, k, col;
120     int nb, c2;
121     unsigned char buf[16];
122
123     while ((c = getc(f)) != EOF) {
124         switch (c) {
125         case 1:
126         case 2:
127             if (reverse)
128                 c = 3 - c;
129             printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
130             col = 6;
131             n = getc(f);
132             n = (n << 8) + getc(f);
133             *(c==1? &tot_sent: &tot_rcvd) += n;
134             nb = 0;
135             for (; n > 0; --n) {
136                 c = getc(f);
137                 if (c == EOF) {
138                     printf("\nEOF\n");
139                     exit(0);
140                 }
141                 if (hexmode) {
142                     if (nb >= 16) {
143                         printf("  ");
144                         for (k = 0; k < nb; ++k) {
145                             c2 = buf[k];
146                             putchar((' ' <= c2 && c2 <= '~')? c2: '.');
147                         }
148                         printf("\n      ");
149                         nb = 0;
150                     }
151                     buf[nb++] = c;
152                     printf(" %.2x", c);
153                 } else {
154                     k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
155                     if ((col += k) >= 78) {
156                         printf("\n      ");
157                         col = 6 + k;
158                     }
159                     switch (k) {
160                     case 1:
161                         putchar(c);
162                         break;
163                     case 2:
164                         printf("\\%c", c);
165                         break;
166                     case 3:
167                         printf("\\%.2x", c);
168                         break;
169                     }
170                 }
171             }
172             if (hexmode) {
173                 for (k = nb; k < 16; ++k)
174                     printf("   ");
175                 printf("  ");
176                 for (k = 0; k < nb; ++k) {
177                     c2 = buf[k];
178                     putchar((' ' <= c2 && c2 <= '~')? c2: '.');
179                 }
180             } else
181                 putchar('"');
182             printf("\n");
183             break;
184         case 3:
185         case 4:
186             printf("end %s\n", c==3? "send": "recv");
187             break;
188         case 5:
189         case 6:
190         case 7:
191             show_time(f, c);
192             break;
193         default:
194             printf("?%.2x\n", c);
195         }
196     }
197 }
198
199 /*
200  * FCS lookup table as calculated by genfcstab.
201  */
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
235 };
236 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
237
238 struct pkt {
239     int cnt;
240     int esc;
241     int flags;
242     struct compressor *comp;
243     void *state;
244     unsigned char buf[8192];
245 } spkt, rpkt;
246
247 /* Values for flags */
248 #define CCP_ISUP        1
249 #define CCP_ERROR       2
250 #define CCP_FATALERROR  4
251 #define CCP_ERR         (CCP_ERROR | CCP_FATALERROR)
252 #define CCP_DECOMP_RUN  8
253
254 unsigned char dbuf[8192];
255
256 void
257 dumpppp(f)
258     FILE *f;
259 {
260     int c, n, k;
261     int nb, nl, dn, proto, rv;
262     char *dir, *q;
263     unsigned char *p, *r, *endp;
264     unsigned char *d;
265     unsigned short fcs;
266     struct pkt *pkt;
267
268     spkt.cnt = rpkt.cnt = 0;
269     spkt.esc = rpkt.esc = 0;
270     while ((c = getc(f)) != EOF) {
271         switch (c) {
272         case 1:
273         case 2:
274             if (reverse)
275                 c = 3 - c;
276             dir = c==1? "sent": "rcvd";
277             pkt = c==1? &spkt: &rpkt;
278             n = getc(f);
279             n = (n << 8) + getc(f);
280             *(c==1? &tot_sent: &tot_rcvd) += n;
281             for (; n > 0; --n) {
282                 c = getc(f);
283                 switch (c) {
284                 case EOF:
285                     printf("\nEOF\n");
286                     if (spkt.cnt > 0)
287                         printf("[%d bytes in incomplete send packet]\n",
288                                spkt.cnt);
289                     if (rpkt.cnt > 0)
290                         printf("[%d bytes in incomplete recv packet]\n",
291                                rpkt.cnt);
292                     exit(0);
293                 case '~':
294                     if (pkt->cnt > 0) {
295                         q = dir;
296                         if (pkt->esc) {
297                             printf("%s aborted packet:\n     ", dir);
298                             q = "    ";
299                         }
300                         if (pkt->cnt >= sizeof(pkt->buf)) {
301                             printf("%s over-long packet truncated:\n     ", dir);
302                             q = "    ";
303                         }
304                         nb = pkt->cnt;
305                         p = pkt->buf;
306                         pkt->cnt = 0;
307                         pkt->esc = 0;
308                         if (nb <= 2) {
309                             printf("%s short packet [%d bytes]:", q, nb);
310                             for (k = 0; k < nb; ++k)
311                                 printf(" %.2x", p[k]);
312                             printf("\n");
313                             break;
314                         }
315                         fcs = PPP_INITFCS;
316                         for (k = 0; k < nb; ++k)
317                             fcs = PPP_FCS(fcs, p[k]);
318                         fcs &= 0xFFFF;
319                         nb -= 2;
320                         endp = p + nb;
321                         r = p;
322                         if (r[0] == 0xff && r[1] == 3)
323                             r += 2;
324                         if ((r[0] & 1) == 0)
325                             ++r;
326                         ++r;
327                         if (endp - r > mru)
328                             printf("     ERROR: length (%zd) > MRU (%d)\n",
329                                    endp - r, mru);
330                         if (decompress && fcs == PPP_GOODFCS) {
331                             /* See if this is a CCP or compressed packet */
332                             d = dbuf;
333                             r = p;
334                             if (r[0] == 0xff && r[1] == 3) {
335                                 *d++ = *r++;
336                                 *d++ = *r++;
337                             }
338                             proto = r[0];
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)
346                                     && pkt->state
347                                     && (pkt->flags & CCP_ERR) == 0) {
348                                     rv = pkt->comp->decompress(pkt->state, r,
349                                                         endp - r, d, &dn);
350                                     switch (rv) {
351                                     case DECOMP_OK:
352                                         p = dbuf;
353                                         nb = d + dn - p;
354                                         if ((d[0] & 1) == 0)
355                                             --dn;
356                                         --dn;
357                                         if (dn > mru)
358                                             printf("     ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
359                                         break;
360                                     case DECOMP_ERROR:
361                                         printf("     DECOMPRESSION ERROR\n");
362                                         pkt->flags |= CCP_ERROR;
363                                         break;
364                                     case DECOMP_FATALERROR:
365                                         printf("     FATAL DECOMPRESSION ERROR\n");
366                                         pkt->flags |= CCP_FATALERROR;
367                                         break;
368                                     }
369                                 }
370                             } else if (pkt->state
371                                        && (pkt->flags & CCP_DECOMP_RUN)) {
372                                 pkt->comp->incomp(pkt->state, r, endp - r);
373                             }
374                         }
375                         do {
376                             nl = nb < 16? nb: 16;
377                             printf("%s ", q);
378                             for (k = 0; k < nl; ++k)
379                                 printf(" %.2x", p[k]);
380                             for (; k < 16; ++k)
381                                 printf("   ");
382                             printf("  ");
383                             for (k = 0; k < nl; ++k) {
384                                 c = p[k];
385                                 putchar((' ' <= c && c <= '~')? c: '.');
386                             }
387                             printf("\n");
388                             q = "    ";
389                             p += nl;
390                             nb -= nl;
391                         } while (nb > 0);
392                         if (fcs != PPP_GOODFCS)
393                             printf("     BAD FCS: (residue = %x)\n", fcs);
394                     }
395                     break;
396                 case '}':
397                     if (!pkt->esc) {
398                         pkt->esc = 1;
399                         break;
400                     }
401                     /* else fall through */
402                 default:
403                     if (pkt->esc) {
404                         c ^= 0x20;
405                         pkt->esc = 0;
406                     }
407                     if (pkt->cnt < sizeof(pkt->buf))
408                         pkt->buf[pkt->cnt++] = c;
409                     break;
410                 }
411             }
412             break;
413         case 3:
414         case 4:
415             if (reverse)
416                 c = 7 - c;
417             dir = c==3? "send": "recv";
418             pkt = c==3? &spkt: &rpkt;
419             printf("end %s", dir);
420             if (pkt->cnt > 0)
421                 printf("  [%d bytes in incomplete packet]", pkt->cnt);
422             printf("\n");
423             break;
424         case 5:
425         case 6:
426         case 7:
427             show_time(f, c);
428             break;
429         default:
430             printf("?%.2x\n", c);
431         }
432     }
433 }
434
435 extern struct compressor ppp_bsd_compress, ppp_deflate;
436
437 struct compressor *compressors[] = {
438 #if DO_BSD_COMPRESS
439     &ppp_bsd_compress,
440 #endif
441 #if DO_DEFLATE
442     &ppp_deflate,
443 #endif
444     NULL
445 };
446
447 void
448 handle_ccp(cp, dp, len)
449     struct pkt *cp;
450     u_char *dp;
451     int len;
452 {
453     int clen;
454     struct compressor **comp;
455
456     if (len < CCP_HDRLEN)
457         return;
458     clen = CCP_LENGTH(dp);
459     if (clen > len)
460         return;
461
462     switch (CCP_CODE(dp)) {
463     case CCP_CONFACK:
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))
467             break;
468         dp += CCP_HDRLEN;
469         clen -= 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);
474                     cp->state = NULL;
475                 }
476                 cp->comp = *comp;
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;
483                 break;
484             }
485         }
486         break;
487
488     case CCP_CONFNAK:
489     case CCP_CONFREJ:
490         cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
491         break;
492
493     case CCP_RESETACK:
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;
498             }
499         }
500         break;
501     }
502 }
503
504 void
505 show_time(f, c)
506     FILE *f;
507     int c;
508 {
509     time_t t;
510     int n;
511     struct tm *tm;
512
513     if (c == 7) {
514         t = getc(f);
515         t = (t << 8) + getc(f);
516         t = (t << 8) + getc(f);
517         t = (t << 8) + getc(f);
518         printf("start %s", ctime(&t));
519         start_time = t;
520         start_time_tenths = 0;
521         tot_sent = tot_rcvd = 0;
522     } else {
523         n = getc(f);
524         if (c == 5) {
525             for (c = 3; c > 0; --c)
526                 n = (n << 8) + getc(f);
527         }
528         if (abs_times) {
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);
536         } else
537             printf("time  %.1fs\n", (double) n / 10);
538     }
539 }