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