make it compile under sunos
[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  *  This program is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU General Public License
9  *  as published by the Free Software Foundation; either version
10  *  2 of the License, or (at your option) any later version.
11  */
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include "ppp_defs.h"
16 #include "ppp-comp.h"
17
18 int hexmode;
19 int pppmode;
20 int reverse;
21 int decompress;
22 int mru = 1500;
23
24 extern int optind;
25 extern char *optarg;
26
27 main(ac, av)
28     int ac;
29     char **av;
30 {
31     int i;
32     char *p;
33     FILE *f;
34
35     while ((i = getopt(ac, av, "hprdm:")) != -1) {
36         switch (i) {
37         case 'h':
38             hexmode = 1;
39             break;
40         case 'p':
41             pppmode = 1;
42             break;
43         case 'r':
44             reverse = 1;
45             break;
46         case 'd':
47             decompress = 1;
48             break;
49         case 'm':
50             mru = atoi(optarg);
51             break;
52         default:
53             fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [file ...]\n", av[0]);
54             exit(1);
55         }
56     }
57     if (optind >= ac)
58         dumplog(stdin);
59     else {
60         for (i = optind; i < ac; ++i) {
61             p = av[i];
62             if ((f = fopen(p, "r")) == NULL) {
63                 perror(p);
64                 exit(1);
65             }
66             if (pppmode)
67                 dumpppp(f);
68             else
69                 dumplog(f);
70             fclose(f);
71         }
72     }
73     exit(0);
74 }
75
76
77 dumplog(f)
78     FILE *f;
79 {
80     int c, n, k, col;
81     int nb, c2;
82     unsigned char buf[16];
83     time_t t;
84
85     while ((c = getc(f)) != EOF) {
86         switch (c) {
87         case 1:
88         case 2:
89             if (reverse)
90                 c = 3 - c;
91             printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
92             col = 6;
93             n = getc(f);
94             n = (n << 8) + getc(f);
95             nb = 0;
96             for (; n > 0; --n) {
97                 c = getc(f);
98                 if (c == EOF) {
99                     printf("\nEOF\n");
100                     exit(0);
101                 }
102                 if (hexmode) {
103                     if (nb >= 16) {
104                         printf("  ");
105                         for (k = 0; k < nb; ++k) {
106                             c2 = buf[k];
107                             putchar((' ' <= c2 && c2 <= '~')? c2: '.');
108                         }
109                         printf("\n      ");
110                         nb = 0;
111                     }
112                     buf[nb++] = c;
113                     printf(" %.2x", c);
114                 } else {
115                     k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
116                     if ((col += k) >= 78) {
117                         printf("\n      ");
118                         col = 6 + k;
119                     }
120                     switch (k) {
121                     case 1:
122                         putchar(c);
123                         break;
124                     case 2:
125                         printf("\\%c", c);
126                         break;
127                     case 3:
128                         printf("\\%.2x", c);
129                         break;
130                     }
131                 }
132             }
133             if (hexmode) {
134                 for (k = nb; k < 16; ++k)
135                     printf("   ");
136                 printf("  ");
137                 for (k = 0; k < nb; ++k) {
138                     c2 = buf[k];
139                     putchar((' ' <= c2 && c2 <= '~')? c2: '.');
140                 }
141             } else
142                 putchar('"');
143             printf("\n");
144             break;
145         case 3:
146         case 4:
147             printf("end %s\n", c==3? "send": "recv");
148             break;
149         case 5:
150         case 6:
151             n = getc(f);
152             if (c == 5) {
153                 for (c = 3; c > 0; --c)
154                     n = (n << 8) + getc(f);
155             }
156             printf("time %.1fs\n", (double) n / 10);
157             break;
158         case 7:
159             t = getc(f);
160             t = (t << 8) + getc(f);
161             t = (t << 8) + getc(f);
162             t = (t << 8) + getc(f);
163             printf("start %s", ctime(&t));
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     time_t t;
238
239     spkt.cnt = rpkt.cnt = 0;
240     spkt.esc = rpkt.esc = 0;
241     while ((c = getc(f)) != EOF) {
242         switch (c) {
243         case 1:
244         case 2:
245             if (reverse)
246                 c = 3 - c;
247             dir = c==1? "sent": "rcvd";
248             pkt = c==1? &spkt: &rpkt;
249             n = getc(f);
250             n = (n << 8) + getc(f);
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             n = getc(f);
392             if (c == 5) {
393                 for (c = 3; c > 0; --c)
394                     n = (n << 8) + getc(f);
395             }
396             printf("time %.1fs\n", (double) n / 10);
397             break;
398         case 7:
399             t = getc(f);
400             t = (t << 8) + getc(f);
401             t = (t << 8) + getc(f);
402             t = (t << 8) + getc(f);
403             printf("start %s", ctime(&t));
404             break;
405         default:
406             printf("?%.2x\n");
407         }
408     }
409 }
410
411 extern struct compressor ppp_bsd_compress, ppp_deflate;
412
413 struct compressor *compressors[] = {
414 #if DO_BSD_COMPRESS
415     &ppp_bsd_compress,
416 #endif
417 #if DO_DEFLATE
418     &ppp_deflate,
419 #endif
420     NULL
421 };
422
423 handle_ccp(cp, dp, len)
424     struct pkt *cp;
425     u_char *dp;
426     int len;
427 {
428     int clen;
429     struct compressor **comp;
430
431     if (len < CCP_HDRLEN)
432         return;
433     clen = CCP_LENGTH(dp);
434     if (clen > len)
435         return;
436
437     switch (CCP_CODE(dp)) {
438     case CCP_CONFACK:
439         cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
440         if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
441             || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
442             break;
443         dp += CCP_HDRLEN;
444         clen -= CCP_HDRLEN;
445         for (comp = compressors; *comp != NULL; ++comp) {
446             if ((*comp)->compress_proto == dp[0]) {
447                 if (cp->state != NULL) {
448                     (*cp->comp->decomp_free)(cp->state);
449                     cp->state = NULL;
450                 }
451                 cp->comp = *comp;
452                 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
453                 cp->flags |= CCP_ISUP;
454                 if (cp->state != NULL
455                     && (*cp->comp->decomp_init)
456                         (cp->state, dp, clen, 0, 0, 8192, 1))
457                     cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
458                 break;
459             }
460         }
461         break;
462
463     case CCP_CONFNAK:
464     case CCP_CONFREJ:
465         cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
466         break;
467
468     case CCP_RESETACK:
469         if (cp->flags & CCP_ISUP) {
470             if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
471                 (*cp->comp->decomp_reset)(cp->state);
472                 cp->flags &= ~CCP_ERROR;
473             }
474         }
475         break;
476     }
477 }