rp_pppoe: Copy acName and pppd_pppoe_service after option parsing
[mpls-ppp.git] / pppdump / pppdump.c
blob95e692c8774af4513747d7f7ae0f22810b5db6fe
1 /*
2 * pppdump - print out the contents of a record file generated by
3 * pppd in readable form.
5 * Copyright (c) 1999 Paul Mackerras. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
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.
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.
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>".
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.
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <time.h>
40 #include <sys/types.h>
41 #include "ppp_defs.h"
42 #include "ppp-comp.h"
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;
54 extern int optind;
55 extern char *optarg;
57 void dumplog();
58 void dumpppp();
59 void show_time();
60 void handle_ccp();
62 int
63 main(ac, av)
64 int ac;
65 char **av;
67 int i;
68 char *p;
69 FILE *f;
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);
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);
105 if (pppmode)
106 dumpppp(f);
107 else
108 dumplog(f);
109 fclose(f);
112 exit(0);
115 void
116 dumplog(f)
117 FILE *f;
119 int c, n, k, col;
120 int nb, c2;
121 unsigned char buf[16];
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);
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: '.');
148 printf("\n ");
149 nb = 0;
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;
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;
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: '.');
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");
200 * FCS lookup table as calculated by genfcstab.
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
237 struct pkt {
238 int cnt;
239 int esc;
240 int flags;
241 struct compressor *comp;
242 void *state;
243 unsigned char buf[8192];
244 } spkt, rpkt;
246 /* Values for flags */
247 #define CCP_ISUP 1
248 #define CCP_ERROR 2
249 #define CCP_FATALERROR 4
250 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
251 #define CCP_DECOMP_RUN 8
253 unsigned char dbuf[8192];
255 void
256 dumpppp(f)
257 FILE *f;
259 int c, n, k;
260 int nb, nl, dn, proto, rv;
261 char *dir, *q;
262 unsigned char *p, *r, *endp;
263 unsigned char *d;
264 unsigned short fcs;
265 struct pkt *pkt;
267 spkt.cnt = rpkt.cnt = 0;
268 spkt.esc = rpkt.esc = 0;
269 while ((c = getc(f)) != EOF) {
270 switch (c) {
271 case 1:
272 case 2:
273 if (reverse)
274 c = 3 - c;
275 dir = c==1? "sent": "rcvd";
276 pkt = c==1? &spkt: &rpkt;
277 n = getc(f);
278 n = (n << 8) + getc(f);
279 *(c==1? &tot_sent: &tot_rcvd) += n;
280 for (; n > 0; --n) {
281 c = getc(f);
282 switch (c) {
283 case EOF:
284 printf("\nEOF\n");
285 if (spkt.cnt > 0)
286 printf("[%d bytes in incomplete send packet]\n",
287 spkt.cnt);
288 if (rpkt.cnt > 0)
289 printf("[%d bytes in incomplete recv packet]\n",
290 rpkt.cnt);
291 exit(0);
292 case '~':
293 if (pkt->cnt > 0) {
294 q = dir;
295 if (pkt->esc) {
296 printf("%s aborted packet:\n ", dir);
297 q = " ";
299 nb = pkt->cnt;
300 p = pkt->buf;
301 pkt->cnt = 0;
302 pkt->esc = 0;
303 if (nb <= 2) {
304 printf("%s short packet [%d bytes]:", q, nb);
305 for (k = 0; k < nb; ++k)
306 printf(" %.2x", p[k]);
307 printf("\n");
308 break;
310 fcs = PPP_INITFCS;
311 for (k = 0; k < nb; ++k)
312 fcs = PPP_FCS(fcs, p[k]);
313 fcs &= 0xFFFF;
314 nb -= 2;
315 endp = p + nb;
316 r = p;
317 if (r[0] == 0xff && r[1] == 3)
318 r += 2;
319 if ((r[0] & 1) == 0)
320 ++r;
321 ++r;
322 if (endp - r > mru)
323 printf(" ERROR: length (%d) > MRU (%d)\n",
324 endp - r, mru);
325 if (decompress && fcs == PPP_GOODFCS) {
326 /* See if this is a CCP or compressed packet */
327 d = dbuf;
328 r = p;
329 if (r[0] == 0xff && r[1] == 3) {
330 *d++ = *r++;
331 *d++ = *r++;
333 proto = r[0];
334 if ((proto & 1) == 0)
335 proto = (proto << 8) + r[1];
336 if (proto == PPP_CCP) {
337 handle_ccp(pkt, r + 2, endp - r - 2);
338 } else if (proto == PPP_COMP) {
339 if ((pkt->flags & CCP_ISUP)
340 && (pkt->flags & CCP_DECOMP_RUN)
341 && pkt->state
342 && (pkt->flags & CCP_ERR) == 0) {
343 rv = pkt->comp->decompress(pkt->state, r,
344 endp - r, d, &dn);
345 switch (rv) {
346 case DECOMP_OK:
347 p = dbuf;
348 nb = d + dn - p;
349 if ((d[0] & 1) == 0)
350 --dn;
351 --dn;
352 if (dn > mru)
353 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
354 break;
355 case DECOMP_ERROR:
356 printf(" DECOMPRESSION ERROR\n");
357 pkt->flags |= CCP_ERROR;
358 break;
359 case DECOMP_FATALERROR:
360 printf(" FATAL DECOMPRESSION ERROR\n");
361 pkt->flags |= CCP_FATALERROR;
362 break;
365 } else if (pkt->state
366 && (pkt->flags & CCP_DECOMP_RUN)) {
367 pkt->comp->incomp(pkt->state, r, endp - r);
370 do {
371 nl = nb < 16? nb: 16;
372 printf("%s ", q);
373 for (k = 0; k < nl; ++k)
374 printf(" %.2x", p[k]);
375 for (; k < 16; ++k)
376 printf(" ");
377 printf(" ");
378 for (k = 0; k < nl; ++k) {
379 c = p[k];
380 putchar((' ' <= c && c <= '~')? c: '.');
382 printf("\n");
383 q = " ";
384 p += nl;
385 nb -= nl;
386 } while (nb > 0);
387 if (fcs != PPP_GOODFCS)
388 printf(" BAD FCS: (residue = %x)\n", fcs);
390 break;
391 case '}':
392 if (!pkt->esc) {
393 pkt->esc = 1;
394 break;
396 /* else fall through */
397 default:
398 if (pkt->esc) {
399 c ^= 0x20;
400 pkt->esc = 0;
402 pkt->buf[pkt->cnt++] = c;
403 break;
406 break;
407 case 3:
408 case 4:
409 if (reverse)
410 c = 7 - c;
411 dir = c==3? "send": "recv";
412 pkt = c==3? &spkt: &rpkt;
413 printf("end %s", dir);
414 if (pkt->cnt > 0)
415 printf(" [%d bytes in incomplete packet]", pkt->cnt);
416 printf("\n");
417 break;
418 case 5:
419 case 6:
420 case 7:
421 show_time(f, c);
422 break;
423 default:
424 printf("?%.2x\n");
429 extern struct compressor ppp_bsd_compress, ppp_deflate;
431 struct compressor *compressors[] = {
432 #if DO_BSD_COMPRESS
433 &ppp_bsd_compress,
434 #endif
435 #if DO_DEFLATE
436 &ppp_deflate,
437 #endif
438 NULL
441 void
442 handle_ccp(cp, dp, len)
443 struct pkt *cp;
444 u_char *dp;
445 int len;
447 int clen;
448 struct compressor **comp;
450 if (len < CCP_HDRLEN)
451 return;
452 clen = CCP_LENGTH(dp);
453 if (clen > len)
454 return;
456 switch (CCP_CODE(dp)) {
457 case CCP_CONFACK:
458 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
459 if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
460 || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
461 break;
462 dp += CCP_HDRLEN;
463 clen -= CCP_HDRLEN;
464 for (comp = compressors; *comp != NULL; ++comp) {
465 if ((*comp)->compress_proto == dp[0]) {
466 if (cp->state != NULL) {
467 (*cp->comp->decomp_free)(cp->state);
468 cp->state = NULL;
470 cp->comp = *comp;
471 cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
472 cp->flags |= CCP_ISUP;
473 if (cp->state != NULL
474 && (*cp->comp->decomp_init)
475 (cp->state, dp, clen, 0, 0, 8192, 1))
476 cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
477 break;
480 break;
482 case CCP_CONFNAK:
483 case CCP_CONFREJ:
484 cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
485 break;
487 case CCP_RESETACK:
488 if (cp->flags & CCP_ISUP) {
489 if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
490 (*cp->comp->decomp_reset)(cp->state);
491 cp->flags &= ~CCP_ERROR;
494 break;
498 void
499 show_time(f, c)
500 FILE *f;
501 int c;
503 time_t t;
504 int n;
505 struct tm *tm;
507 if (c == 7) {
508 t = getc(f);
509 t = (t << 8) + getc(f);
510 t = (t << 8) + getc(f);
511 t = (t << 8) + getc(f);
512 printf("start %s", ctime(&t));
513 start_time = t;
514 start_time_tenths = 0;
515 tot_sent = tot_rcvd = 0;
516 } else {
517 n = getc(f);
518 if (c == 5) {
519 for (c = 3; c > 0; --c)
520 n = (n << 8) + getc(f);
522 if (abs_times) {
523 n += start_time_tenths;
524 start_time += n / 10;
525 start_time_tenths = n % 10;
526 tm = localtime(&start_time);
527 printf("time %.2d:%.2d:%.2d.%d", tm->tm_hour, tm->tm_min,
528 tm->tm_sec, start_time_tenths);
529 printf(" (sent %d, rcvd %d)\n", tot_sent, tot_rcvd);
530 } else
531 printf("time %.1fs\n", (double) n / 10);