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 * 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.
17 #include <sys/types.h>
18 #ifdef PPP_DEFS_IN_NET
19 #include <net/ppp_defs.h>
32 int start_time_tenths
;
33 int tot_sent
, tot_rcvd
;
52 while ((i
= getopt(ac
, av
, "hprdm:a")) != -1) {
73 fprintf(stderr
, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av
[0]);
80 for (i
= optind
; i
< ac
; ++i
) {
82 if ((f
= fopen(p
, "r")) == NULL
) {
102 unsigned char buf
[16];
104 while ((c
= getc(f
)) != EOF
) {
106 case RECMARK_STARTSEND
:
107 case RECMARK_STARTRECV
:
109 c
= c
==RECMARK_STARTSEND
? RECMARK_STARTRECV
:
111 printf("%s %c", c
==RECMARK_STARTSEND
? "sent": "rcvd",
115 n
= (n
<< 8) + getc(f
);
116 *(c
==1? &tot_sent
: &tot_rcvd
) += n
;
127 for (k
= 0; k
< nb
; ++k
) {
129 putchar((' ' <= c2
&& c2
<= '~')? c2
: '.');
137 k
= (' ' <= c
&& c
<= '~')? (c
!= '\\' && c
!= '"')? 1: 2: 3;
138 if ((col
+= k
) >= 78) {
156 for (k
= nb
; k
< 16; ++k
)
159 for (k
= 0; k
< nb
; ++k
) {
161 putchar((' ' <= c2
&& c2
<= '~')? c2
: '.');
167 case RECMARK_ENDSEND
:
168 case RECMARK_ENDRECV
:
170 c
= c
==RECMARK_ENDSEND
? RECMARK_ENDRECV
: RECMARK_ENDSEND
;
171 printf("end %s\n", c
==RECMARK_ENDSEND
? "send": "recv");
173 case RECMARK_TIMEDELTA32
:
174 case RECMARK_TIMEDELTA8
:
175 case RECMARK_TIMESTART
:
185 * FCS lookup table as calculated by genfcstab.
187 static u_short fcstab
[256] = {
188 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
189 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
190 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
191 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
192 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
193 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
194 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
195 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
196 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
197 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
198 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
199 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
200 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
201 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
202 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
203 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
204 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
205 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
206 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
207 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
208 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
209 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
210 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
211 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
212 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
213 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
214 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
215 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
216 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
217 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
218 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
219 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
226 struct compressor
*comp
;
228 unsigned char buf
[8192];
231 /* Values for flags */
234 #define CCP_FATALERROR 4
235 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
236 #define CCP_DECOMP_RUN 8
238 unsigned char dbuf
[8192];
245 int nb
, nl
, dn
, proto
, rv
;
247 unsigned char *p
, *r
, *endp
;
252 spkt
.cnt
= rpkt
.cnt
= 0;
253 spkt
.esc
= rpkt
.esc
= 0;
254 while ((c
= getc(f
)) != EOF
) {
256 case RECMARK_STARTSEND
:
257 case RECMARK_STARTRECV
:
259 c
= c
==RECMARK_STARTSEND
? RECMARK_STARTRECV
:
261 dir
= c
==RECMARK_STARTSEND
? "sent": "rcvd";
262 pkt
= c
==RECMARK_STARTSEND
? &spkt
: &rpkt
;
264 n
= (n
<< 8) + getc(f
);
265 *(c
==1? &tot_sent
: &tot_rcvd
) += n
;
272 printf("[%d bytes in incomplete send packet]\n",
275 printf("[%d bytes in incomplete recv packet]\n",
282 printf("%s aborted packet:\n ", dir
);
290 printf("%s short packet [%d bytes]:", q
, nb
);
291 for (k
= 0; k
< nb
; ++k
)
292 printf(" %.2x", p
[k
]);
297 for (k
= 0; k
< nb
; ++k
)
298 fcs
= PPP_FCS(fcs
, p
[k
]);
303 if (r
[0] == 0xff && r
[1] == 3)
309 printf(" ERROR: length (%d) > MRU (%d)\n",
311 if (decompress
&& fcs
== PPP_GOODFCS
) {
312 /* See if this is a CCP or compressed packet */
315 if (r
[0] == 0xff && r
[1] == 3) {
320 if ((proto
& 1) == 0)
321 proto
= (proto
<< 8) + r
[1];
322 if (proto
== PPP_CCP
) {
323 handle_ccp(pkt
, r
+ 2, endp
- r
- 2);
324 } else if (proto
== PPP_COMP
) {
325 if ((pkt
->flags
& CCP_ISUP
)
326 && (pkt
->flags
& CCP_DECOMP_RUN
)
328 && (pkt
->flags
& CCP_ERR
) == 0) {
329 rv
= pkt
->comp
->decompress(pkt
->state
, r
,
339 printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn
, mru
);
342 printf(" DECOMPRESSION ERROR\n");
343 pkt
->flags
|= CCP_ERROR
;
345 case DECOMP_FATALERROR
:
346 printf(" FATAL DECOMPRESSION ERROR\n");
347 pkt
->flags
|= CCP_FATALERROR
;
351 } else if (pkt
->state
352 && (pkt
->flags
& CCP_DECOMP_RUN
)) {
353 pkt
->comp
->incomp(pkt
->state
, r
, endp
- r
);
357 nl
= nb
< 16? nb
: 16;
359 for (k
= 0; k
< nl
; ++k
)
360 printf(" %.2x", p
[k
]);
364 for (k
= 0; k
< nl
; ++k
) {
366 putchar((' ' <= c
&& c
<= '~')? c
: '.');
373 if (fcs
!= PPP_GOODFCS
)
374 printf(" BAD FCS: (residue = %x)\n", fcs
);
382 /* else fall through */
388 pkt
->buf
[pkt
->cnt
++] = c
;
393 case RECMARK_ENDSEND
:
394 case RECMARK_ENDRECV
:
396 c
= c
==RECMARK_ENDSEND
? RECMARK_ENDRECV
: RECMARK_ENDSEND
;
397 dir
= c
==RECMARK_ENDSEND
? "send": "recv";
398 pkt
= c
==RECMARK_ENDSEND
? &spkt
: &rpkt
;
399 printf("end %s", dir
);
401 printf(" [%d bytes in incomplete packet]", pkt
->cnt
);
404 case RECMARK_TIMEDELTA32
:
405 case RECMARK_TIMEDELTA8
:
406 case RECMARK_TIMESTART
:
415 extern struct compressor ppp_bsd_compress
, ppp_deflate
;
417 struct compressor
*compressors
[] = {
428 handle_ccp(cp
, dp
, len
)
434 struct compressor
**comp
;
436 if (len
< CCP_HDRLEN
)
438 clen
= CCP_LENGTH(dp
);
442 switch (CCP_CODE(dp
)) {
444 cp
->flags
&= ~(CCP_DECOMP_RUN
| CCP_ISUP
);
445 if (clen
< CCP_HDRLEN
+ CCP_OPT_MINLEN
446 || clen
< CCP_HDRLEN
+ CCP_OPT_LENGTH(dp
+ CCP_HDRLEN
))
450 for (comp
= compressors
; *comp
!= NULL
; ++comp
) {
451 if ((*comp
)->compress_proto
== dp
[0]) {
452 if (cp
->state
!= NULL
) {
453 (*cp
->comp
->decomp_free
)(cp
->state
);
457 cp
->state
= (*comp
)->decomp_alloc(dp
, CCP_OPT_LENGTH(dp
));
458 cp
->flags
|= CCP_ISUP
;
459 if (cp
->state
!= NULL
460 && (*cp
->comp
->decomp_init
)
461 (cp
->state
, dp
, clen
, 0, 0, 8192, 1))
462 cp
->flags
= (cp
->flags
& ~CCP_ERR
) | CCP_DECOMP_RUN
;
470 cp
->flags
&= ~(CCP_DECOMP_RUN
| CCP_ISUP
);
474 if (cp
->flags
& CCP_ISUP
) {
475 if (cp
->state
&& (cp
->flags
& CCP_DECOMP_RUN
)) {
476 (*cp
->comp
->decomp_reset
)(cp
->state
);
477 cp
->flags
&= ~CCP_ERROR
;
493 if (c
== RECMARK_TIMESTART
) {
495 t
= (t
<< 8) + getc(f
);
496 t
= (t
<< 8) + getc(f
);
497 t
= (t
<< 8) + getc(f
);
498 printf("start %s", ctime(&t
));
500 start_time_tenths
= 0;
501 tot_sent
= tot_rcvd
= 0;
504 if (c
== RECMARK_TIMEDELTA32
) {
505 for (c
= 3; c
> 0; --c
)
506 n
= (n
<< 8) + getc(f
);
509 n
+= start_time_tenths
;
510 start_time
+= n
/ 10;
511 start_time_tenths
= n
% 10;
512 tm
= localtime(&start_time
);
513 printf("time %.2d:%.2d:%.2d.%d", tm
->tm_hour
, tm
->tm_min
,
514 tm
->tm_sec
, start_time_tenths
);
515 printf(" (sent %d, rcvd %d)\n", tot_sent
, tot_rcvd
);
517 printf("time %.1fs\n", (double) n
/ 10);