pppdump.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. #include "ppp_defs.h"
  42. #include "ppp-comp.h"
  43. int hexmode;
  44. int pppmode;
  45. int reverse;
  46. int decompress;
  47. int mru = 1500;
  48. int abs_times;
  49. time_t start_time;
  50. int start_time_tenths;
  51. int tot_sent, tot_rcvd;
  52. extern int optind;
  53. extern char *optarg;
  54. void dumplog();
  55. void dumpppp();
  56. void show_time();
  57. void handle_ccp();
  58. int
  59. main(ac, av)
  60. int ac;
  61. char **av;
  62. {
  63. int i;
  64. char *p;
  65. FILE *f;
  66. while ((i = getopt(ac, av, "hprdm:a")) != -1) {
  67. switch (i) {
  68. case 'h':
  69. hexmode = 1;
  70. break;
  71. case 'p':
  72. pppmode = 1;
  73. break;
  74. case 'r':
  75. reverse = 1;
  76. break;
  77. case 'd':
  78. decompress = 1;
  79. break;
  80. case 'm':
  81. mru = atoi(optarg);
  82. break;
  83. case 'a':
  84. abs_times = 1;
  85. break;
  86. default:
  87. fprintf(stderr, "Usage: %s [-h | -p[d]] [-r] [-m mru] [-a] [file ...]\n", av[0]);
  88. exit(1);
  89. }
  90. }
  91. if (optind >= ac)
  92. dumplog(stdin);
  93. else {
  94. for (i = optind; i < ac; ++i) {
  95. p = av[i];
  96. if ((f = fopen(p, "r")) == NULL) {
  97. perror(p);
  98. exit(1);
  99. }
  100. if (pppmode)
  101. dumpppp(f);
  102. else
  103. dumplog(f);
  104. fclose(f);
  105. }
  106. }
  107. exit(0);
  108. }
  109. void
  110. dumplog(f)
  111. FILE *f;
  112. {
  113. int c, n, k, col;
  114. int nb, c2;
  115. unsigned char buf[16];
  116. while ((c = getc(f)) != EOF) {
  117. switch (c) {
  118. case 1:
  119. case 2:
  120. if (reverse)
  121. c = 3 - c;
  122. printf("%s %c", c==1? "sent": "rcvd", hexmode? ' ': '"');
  123. col = 6;
  124. n = getc(f);
  125. n = (n << 8) + getc(f);
  126. *(c==1? &tot_sent: &tot_rcvd) += n;
  127. nb = 0;
  128. for (; n > 0; --n) {
  129. c = getc(f);
  130. if (c == EOF) {
  131. printf("\nEOF\n");
  132. exit(0);
  133. }
  134. if (hexmode) {
  135. if (nb >= 16) {
  136. printf(" ");
  137. for (k = 0; k < nb; ++k) {
  138. c2 = buf[k];
  139. putchar((' ' <= c2 && c2 <= '~')? c2: '.');
  140. }
  141. printf("\n ");
  142. nb = 0;
  143. }
  144. buf[nb++] = c;
  145. printf(" %.2x", c);
  146. } else {
  147. k = (' ' <= c && c <= '~')? (c != '\\' && c != '"')? 1: 2: 3;
  148. if ((col += k) >= 78) {
  149. printf("\n ");
  150. col = 6 + k;
  151. }
  152. switch (k) {
  153. case 1:
  154. putchar(c);
  155. break;
  156. case 2:
  157. printf("\\%c", c);
  158. break;
  159. case 3:
  160. printf("\\%.2x", c);
  161. break;
  162. }
  163. }
  164. }
  165. if (hexmode) {
  166. for (k = nb; k < 16; ++k)
  167. printf(" ");
  168. printf(" ");
  169. for (k = 0; k < nb; ++k) {
  170. c2 = buf[k];
  171. putchar((' ' <= c2 && c2 <= '~')? c2: '.');
  172. }
  173. } else
  174. putchar('"');
  175. printf("\n");
  176. break;
  177. case 3:
  178. case 4:
  179. printf("end %s\n", c==3? "send": "recv");
  180. break;
  181. case 5:
  182. case 6:
  183. case 7:
  184. show_time(f, c);
  185. break;
  186. default:
  187. printf("?%.2x\n", c);
  188. }
  189. }
  190. }
  191. /*
  192. * FCS lookup table as calculated by genfcstab.
  193. */
  194. static u_short fcstab[256] = {
  195. 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
  196. 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
  197. 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
  198. 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
  199. 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
  200. 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
  201. 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
  202. 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
  203. 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
  204. 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
  205. 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
  206. 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
  207. 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
  208. 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
  209. 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
  210. 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
  211. 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
  212. 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
  213. 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
  214. 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
  215. 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
  216. 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
  217. 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
  218. 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
  219. 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
  220. 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
  221. 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
  222. 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
  223. 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
  224. 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
  225. 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
  226. 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
  227. };
  228. struct pkt {
  229. int cnt;
  230. int esc;
  231. int flags;
  232. struct compressor *comp;
  233. void *state;
  234. unsigned char buf[8192];
  235. } spkt, rpkt;
  236. /* Values for flags */
  237. #define CCP_ISUP 1
  238. #define CCP_ERROR 2
  239. #define CCP_FATALERROR 4
  240. #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
  241. #define CCP_DECOMP_RUN 8
  242. unsigned char dbuf[8192];
  243. void
  244. dumpppp(f)
  245. FILE *f;
  246. {
  247. int c, n, k;
  248. int nb, nl, dn, proto, rv;
  249. char *dir, *q;
  250. unsigned char *p, *r, *endp;
  251. unsigned char *d;
  252. unsigned short fcs;
  253. struct pkt *pkt;
  254. spkt.cnt = rpkt.cnt = 0;
  255. spkt.esc = rpkt.esc = 0;
  256. while ((c = getc(f)) != EOF) {
  257. switch (c) {
  258. case 1:
  259. case 2:
  260. if (reverse)
  261. c = 3 - c;
  262. dir = c==1? "sent": "rcvd";
  263. pkt = c==1? &spkt: &rpkt;
  264. n = getc(f);
  265. n = (n << 8) + getc(f);
  266. *(c==1? &tot_sent: &tot_rcvd) += n;
  267. for (; n > 0; --n) {
  268. c = getc(f);
  269. switch (c) {
  270. case EOF:
  271. printf("\nEOF\n");
  272. if (spkt.cnt > 0)
  273. printf("[%d bytes in incomplete send packet]\n",
  274. spkt.cnt);
  275. if (rpkt.cnt > 0)
  276. printf("[%d bytes in incomplete recv packet]\n",
  277. rpkt.cnt);
  278. exit(0);
  279. case '~':
  280. if (pkt->cnt > 0) {
  281. q = dir;
  282. if (pkt->esc) {
  283. printf("%s aborted packet:\n ", dir);
  284. q = " ";
  285. }
  286. nb = pkt->cnt;
  287. p = pkt->buf;
  288. pkt->cnt = 0;
  289. pkt->esc = 0;
  290. if (nb <= 2) {
  291. printf("%s short packet [%d bytes]:", q, nb);
  292. for (k = 0; k < nb; ++k)
  293. printf(" %.2x", p[k]);
  294. printf("\n");
  295. break;
  296. }
  297. fcs = PPP_INITFCS;
  298. for (k = 0; k < nb; ++k)
  299. fcs = PPP_FCS(fcs, p[k]);
  300. fcs &= 0xFFFF;
  301. nb -= 2;
  302. endp = p + nb;
  303. r = p;
  304. if (r[0] == 0xff && r[1] == 3)
  305. r += 2;
  306. if ((r[0] & 1) == 0)
  307. ++r;
  308. ++r;
  309. if (endp - r > mru)
  310. printf(" ERROR: length (%d) > MRU (%d)\n",
  311. endp - r, mru);
  312. if (decompress && fcs == PPP_GOODFCS) {
  313. /* See if this is a CCP or compressed packet */
  314. d = dbuf;
  315. r = p;
  316. if (r[0] == 0xff && r[1] == 3) {
  317. *d++ = *r++;
  318. *d++ = *r++;
  319. }
  320. proto = r[0];
  321. if ((proto & 1) == 0)
  322. proto = (proto << 8) + r[1];
  323. if (proto == PPP_CCP) {
  324. handle_ccp(pkt, r + 2, endp - r - 2);
  325. } else if (proto == PPP_COMP) {
  326. if ((pkt->flags & CCP_ISUP)
  327. && (pkt->flags & CCP_DECOMP_RUN)
  328. && pkt->state
  329. && (pkt->flags & CCP_ERR) == 0) {
  330. rv = pkt->comp->decompress(pkt->state, r,
  331. endp - r, d, &dn);
  332. switch (rv) {
  333. case DECOMP_OK:
  334. p = dbuf;
  335. nb = d + dn - p;
  336. if ((d[0] & 1) == 0)
  337. --dn;
  338. --dn;
  339. if (dn > mru)
  340. printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru);
  341. break;
  342. case DECOMP_ERROR:
  343. printf(" DECOMPRESSION ERROR\n");
  344. pkt->flags |= CCP_ERROR;
  345. break;
  346. case DECOMP_FATALERROR:
  347. printf(" FATAL DECOMPRESSION ERROR\n");
  348. pkt->flags |= CCP_FATALERROR;
  349. break;
  350. }
  351. }
  352. } else if (pkt->state
  353. && (pkt->flags & CCP_DECOMP_RUN)) {
  354. pkt->comp->incomp(pkt->state, r, endp - r);
  355. }
  356. }
  357. do {
  358. nl = nb < 16? nb: 16;
  359. printf("%s ", q);
  360. for (k = 0; k < nl; ++k)
  361. printf(" %.2x", p[k]);
  362. for (; k < 16; ++k)
  363. printf(" ");
  364. printf(" ");
  365. for (k = 0; k < nl; ++k) {
  366. c = p[k];
  367. putchar((' ' <= c && c <= '~')? c: '.');
  368. }
  369. printf("\n");
  370. q = " ";
  371. p += nl;
  372. nb -= nl;
  373. } while (nb > 0);
  374. if (fcs != PPP_GOODFCS)
  375. printf(" BAD FCS: (residue = %x)\n", fcs);
  376. }
  377. break;
  378. case '}':
  379. if (!pkt->esc) {
  380. pkt->esc = 1;
  381. break;
  382. }
  383. /* else fall through */
  384. default:
  385. if (pkt->esc) {
  386. c ^= 0x20;
  387. pkt->esc = 0;
  388. }
  389. pkt->buf[pkt->cnt++] = c;
  390. break;
  391. }
  392. }
  393. break;
  394. case 3:
  395. case 4:
  396. if (reverse)
  397. c = 7 - c;
  398. dir = c==3? "send": "recv";
  399. pkt = c==3? &spkt: &rpkt;
  400. printf("end %s", dir);
  401. if (pkt->cnt > 0)
  402. printf(" [%d bytes in incomplete packet]", pkt->cnt);
  403. printf("\n");
  404. break;
  405. case 5:
  406. case 6:
  407. case 7:
  408. show_time(f, c);
  409. break;
  410. default:
  411. printf("?%.2x\n", c);
  412. }
  413. }
  414. }
  415. extern struct compressor ppp_bsd_compress, ppp_deflate;
  416. struct compressor *compressors[] = {
  417. #if DO_BSD_COMPRESS
  418. &ppp_bsd_compress,
  419. #endif
  420. #if DO_DEFLATE
  421. &ppp_deflate,
  422. #endif
  423. NULL
  424. };
  425. void
  426. handle_ccp(cp, dp, len)
  427. struct pkt *cp;
  428. u_char *dp;
  429. int len;
  430. {
  431. int clen;
  432. struct compressor **comp;
  433. if (len < CCP_HDRLEN)
  434. return;
  435. clen = CCP_LENGTH(dp);
  436. if (clen > len)
  437. return;
  438. switch (CCP_CODE(dp)) {
  439. case CCP_CONFACK:
  440. cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
  441. if (clen < CCP_HDRLEN + CCP_OPT_MINLEN
  442. || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN))
  443. break;
  444. dp += CCP_HDRLEN;
  445. clen -= CCP_HDRLEN;
  446. for (comp = compressors; *comp != NULL; ++comp) {
  447. if ((*comp)->compress_proto == dp[0]) {
  448. if (cp->state != NULL) {
  449. (*cp->comp->decomp_free)(cp->state);
  450. cp->state = NULL;
  451. }
  452. cp->comp = *comp;
  453. cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp));
  454. cp->flags |= CCP_ISUP;
  455. if (cp->state != NULL
  456. && (*cp->comp->decomp_init)
  457. (cp->state, dp, clen, 0, 0, 8192, 1))
  458. cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
  459. break;
  460. }
  461. }
  462. break;
  463. case CCP_CONFNAK:
  464. case CCP_CONFREJ:
  465. cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP);
  466. break;
  467. case CCP_RESETACK:
  468. if (cp->flags & CCP_ISUP) {
  469. if (cp->state && (cp->flags & CCP_DECOMP_RUN)) {
  470. (*cp->comp->decomp_reset)(cp->state);
  471. cp->flags &= ~CCP_ERROR;
  472. }
  473. }
  474. break;
  475. }
  476. }
  477. void
  478. show_time(f, c)
  479. FILE *f;
  480. int c;
  481. {
  482. time_t t;
  483. int n;
  484. struct tm *tm;
  485. if (c == 7) {
  486. t = getc(f);
  487. t = (t << 8) + getc(f);
  488. t = (t << 8) + getc(f);
  489. t = (t << 8) + getc(f);
  490. printf("start %s", ctime(&t));
  491. start_time = t;
  492. start_time_tenths = 0;
  493. tot_sent = tot_rcvd = 0;
  494. } else {
  495. n = getc(f);
  496. if (c == 5) {
  497. for (c = 3; c > 0; --c)
  498. n = (n << 8) + getc(f);
  499. }
  500. if (abs_times) {
  501. n += start_time_tenths;
  502. start_time += n / 10;
  503. start_time_tenths = n % 10;
  504. tm = localtime(&start_time);
  505. printf("time %.2d:%.2d:%.2d.%d", tm->tm_hour, tm->tm_min,
  506. tm->tm_sec, start_time_tenths);
  507. printf(" (sent %d, rcvd %d)\n", tot_sent, tot_rcvd);
  508. } else
  509. printf("time %.1fs\n", (double) n / 10);
  510. }
  511. }