]> The Tcpdump Group git mirrors - tcpdump/blob - print-ppp.c
s/u_short/u_int16_t/ for KAME-origin source codes
[tcpdump] / print-ppp.c
1 /*
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.36 2000-04-28 11:14:48 itojun Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34 #include <sys/file.h>
35 #include <sys/ioctl.h>
36
37 #if __STDC__
38 struct mbuf;
39 struct rtentry;
40 #endif
41 #include <net/if.h>
42
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/if_ether.h>
47
48 #include <ctype.h>
49 #include <netdb.h>
50 #include <pcap.h>
51 #include <stdio.h>
52 #ifdef __bsdi__
53 #include <net/slcompress.h>
54 #include <net/if_ppp.h>
55 #endif
56
57 #include "interface.h"
58 #include "extract.h"
59 #include "addrtoname.h"
60 #include "ppp.h"
61
62 /* XXX This goes somewhere else. */
63 #define PPP_HDRLEN 4
64
65 /* LCP */
66
67 #define LCP_CONF_REQ 1
68 #define LCP_CONF_ACK 2
69 #define LCP_CONF_NAK 3
70 #define LCP_CONF_REJ 4
71 #define LCP_TERM_REQ 5
72 #define LCP_TERM_ACK 6
73 #define LCP_CODE_REJ 7
74 #define LCP_PROT_REJ 8
75 #define LCP_ECHO_REQ 9
76 #define LCP_ECHO_RPL 10
77 #define LCP_DISC_REQ 11
78
79 #define LCP_MIN LCP_CONF_REQ
80 #define LCP_MAX LCP_DISC_REQ
81
82 static char *lcpcodes[] = {
83 /*
84 * LCP code values (RFC1661, pp26)
85 */
86 "Configure-Request",
87 "Configure-Ack",
88 "Configure-Nak",
89 "Configure-Reject",
90 "Terminate-Request",
91 "Terminate-Ack",
92 "Code-Reject",
93 "Protocol-Reject",
94 "Echo-Request",
95 "Echo-Reply",
96 "Discard-Request",
97 };
98
99 #define LCPOPT_VEXT 0
100 #define LCPOPT_MRU 1
101 #define LCPOPT_ACCM 2
102 #define LCPOPT_AP 3
103 #define LCPOPT_QP 4
104 #define LCPOPT_MN 5
105 #define LCPOPT_PFC 7
106 #define LCPOPT_ACFC 8
107
108 #define LCPOPT_MIN 0
109 #define LCPOPT_MAX 24
110
111 static char *lcpconfopts[] = {
112 "Vendor-Ext",
113 "Max-Rx-Unit",
114 "Async-Ctrl-Char-Map",
115 "Auth-Prot",
116 "Quality-Prot",
117 "Magic-Number",
118 "unassigned (6)",
119 "Prot-Field-Compr",
120 "Add-Ctrl-Field-Compr",
121 "FCS-Alternatives",
122 "Self-Describing-Pad",
123 "Numbered-Mode",
124 "Multi-Link-Procedure",
125 "Call-Back",
126 "Connect-Time",
127 "Compund-Frames",
128 "Nominal-Data-Encap",
129 "Multilink-MRRU",
130 "Multilink-SSNHF",
131 "Multilink-ED",
132 "Proprietary",
133 "DCE-Identifier",
134 "Multilink-Plus-Proc",
135 "Link-Discriminator",
136 "LCP-Auth-Option",
137 };
138
139 /* CHAP */
140
141 #define CHAP_CHAL 1
142 #define CHAP_RESP 2
143 #define CHAP_SUCC 3
144 #define CHAP_FAIL 4
145
146 #define CHAP_CODEMIN 1
147 #define CHAP_CODEMAX 4
148
149 static char *chapcode[] = {
150 "Challenge",
151 "Response",
152 "Success",
153 "Failure",
154 };
155
156 /* PAP */
157
158 #define PAP_AREQ 1
159 #define PAP_AACK 2
160 #define PAP_ANAK 3
161
162 #define PAP_CODEMIN 1
163 #define PAP_CODEMAX 3
164
165 static char *papcode[] = {
166 "Authenticate-Request",
167 "Authenticate-Ack",
168 "Authenticate-Nak",
169 };
170
171 /* IPCP */
172
173 #define IPCP_2ADDR 1
174 #define IPCP_CP 2
175 #define IPCP_ADDR 3
176
177 static const char *ppp_protoname __P((int proto));
178 static void handle_lcp __P((const u_char *p, int length));
179 static int print_lcp_config_options __P((const u_char *p));
180 static void handle_chap __P((const u_char *p, int length));
181 static void handle_ipcp __P((const u_char *p, int length));
182 static void handle_pap __P((const u_char *p, int length));
183
184 static const char *
185 ppp_protoname(int proto)
186 {
187 static char buf[20];
188
189 switch (proto) {
190 case PPP_IP: return "IP";
191 #ifdef PPP_XNS
192 case PPP_XNS: return "XNS";
193 #endif
194 #ifdef PPP_IPX
195 case PPP_IPX: return "IPX";
196 #endif
197 #ifdef PPP_COMP
198 case PPP_COMP: return "COMP";
199 #endif
200 #ifdef PPP_IPCP
201 case PPP_IPCP: return "IPCP";
202 #endif
203 #ifdef PPP_IPV6CP
204 case PPP_IPV6CP: return "IPV6CP";
205 #endif
206 #ifdef PPP_IPXCP
207 case PPP_IPXCP: return "IPXCP";
208 #endif
209 #ifdef PPP_CCP
210 case PPP_CCP: return "CCP";
211 #endif
212 #ifdef PPP_LCP
213 case PPP_LCP: return "LCP";
214 #endif
215 #ifdef PPP_PAP
216 case PPP_PAP: return "PAP";
217 #endif
218 #ifdef PPP_LQR
219 case PPP_LQR: return "LQR";
220 #endif
221 #ifdef PPP_CHAP
222 case PPP_CHAP: return "CHAP";
223 #endif
224 default:
225 snprintf(buf, sizeof(buf), "unknown-0x%04x\n", proto);
226 return buf;
227 }
228 }
229
230 /* print LCP frame */
231 static void
232 handle_lcp(const u_char *p, int length)
233 {
234 int x, j;
235 const u_char *ptr;
236
237 x = p[4];
238
239 if ((x >= LCP_MIN) && (x <= LCP_MAX))
240 printf("%s", lcpcodes[x - 1]);
241 else {
242 printf("0x%02x", x);
243 return;
244 }
245
246 length -= 4;
247
248 switch (x) {
249 case LCP_CONF_REQ:
250 case LCP_CONF_ACK:
251 case LCP_CONF_NAK:
252 case LCP_CONF_REJ:
253 x = length;
254 ptr = p + 8;
255 do {
256 if ((j = print_lcp_config_options(ptr)) == 0)
257 break;
258 x -= j;
259 ptr += j;
260 } while (x > 0);
261 break;
262
263 case LCP_ECHO_REQ:
264 case LCP_ECHO_RPL:
265 printf(", Magic-Number=%u",
266 EXTRACT_32BITS(p+8));
267 break;
268 case LCP_TERM_REQ:
269 case LCP_TERM_ACK:
270 case LCP_CODE_REJ:
271 case LCP_PROT_REJ:
272 case LCP_DISC_REQ:
273 default:
274 break;
275 }
276 }
277
278 /* LCP config options */
279 static int
280 print_lcp_config_options(const u_char *p)
281 {
282 int len = p[1];
283 int opt = p[0];
284
285 if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
286 printf(", %s", lcpconfopts[opt]);
287
288 switch (opt) {
289 case LCPOPT_MRU:
290 if (len == 4)
291 printf("=%d", (*(p+2) << 8) + *(p+3));
292 break;
293 case LCPOPT_AP:
294 if (len >= 4) {
295 if (p[2] == 0xc0 && p[3] == 0x23)
296 printf(" PAP");
297 else if (p[2] == 0xc2 && p[3] == 0x23) {
298 printf(" CHAP/");
299 switch (p[4]) {
300 default:
301 printf("unknown-algorithm-%u", p[4]);
302 break;
303 case 5:
304 printf("MD5");
305 break;
306 case 0x80:
307 printf("Microsoft");
308 break;
309 }
310 }
311 else if (p[2] == 0xc2 && p[3] == 0x27)
312 printf(" EAP");
313 else if (p[2] == 0xc0 && p[3] == 0x27)
314 printf(" SPAP");
315 else if (p[2] == 0xc1 && p[3] == 0x23)
316 printf(" Old-SPAP");
317 else
318 printf("unknown");
319 }
320 break;
321 case LCPOPT_QP:
322 if (len >= 4) {
323 if (p[2] == 0xc0 && p[3] == 0x25)
324 printf(" LQR");
325 else
326 printf(" unknown");
327 }
328 break;
329 case LCPOPT_MN:
330 if (len == 6)
331 printf("=%u", EXTRACT_32BITS(p+2));
332 break;
333 case LCPOPT_PFC:
334 printf(" PFC");
335 break;
336 case LCPOPT_ACFC:
337 printf(" ACFC");
338 break;
339 }
340 return len;
341 }
342
343 /* CHAP */
344 static void
345 handle_chap(const u_char *p, int length)
346 {
347 int x;
348 const u_char *ptr;
349
350 x = p[4];
351
352 if ((x >= CHAP_CODEMIN) && (x <= CHAP_CODEMAX))
353 printf("%s", chapcode[x - 1]);
354 else {
355 printf("0x%02x", x);
356 return;
357 }
358
359 length -= 4;
360
361 switch (p[4]) {
362 case CHAP_CHAL:
363 case CHAP_RESP:
364 printf(", Value=");
365 x = p[8]; /* value size */
366 ptr = p + 9;
367 while (--x >= 0)
368 printf("%02x", *ptr++);
369 x = length - p[8] - 1;
370 printf(", Name=");
371 while (--x >= 0) {
372 if (isprint(*ptr))
373 printf("%c", *ptr);
374 else
375 printf("\\%03o", *ptr);
376 ptr++;
377 }
378 break;
379 }
380 }
381
382 /* PAP */
383 static void
384 handle_pap(const u_char *p, int length)
385 {
386 int x;
387 const u_char *ptr;
388
389 x = p[4];
390
391 if ((x >= PAP_CODEMIN) && (x <= PAP_CODEMAX))
392 printf("%s", papcode[x - 1]);
393 else {
394 printf("0x%02x", x);
395 return;
396 }
397
398 length -= 4;
399
400 switch (x) {
401 case PAP_AREQ:
402 printf(", Peer-Id=");
403 x = p[8]; /* peerid size */
404 ptr = p + 9;
405 while (--x >= 0) {
406 if (isprint(*ptr))
407 printf("%c", *ptr);
408 else
409 printf("\\%03o", *ptr);
410 ptr++;
411 }
412 x = *ptr++;
413 printf(", Passwd=");
414 while (--x >= 0) {
415 if (isprint(*ptr))
416 printf("%c", *ptr);
417 else
418 printf("\\%03o", *ptr);
419 ptr++;
420 }
421 break;
422 case PAP_AACK:
423 case PAP_ANAK:
424 break;
425 }
426 }
427
428 /* IPCP */
429 static void
430 handle_ipcp(const u_char *p, int length)
431 {
432 length -= 4;
433
434 switch (p[8]) {
435 case IPCP_2ADDR:
436 printf("IP-Addresses");
437 printf(", src=%s", ipaddr_string(p + 10));
438 printf(", drc=%s", ipaddr_string(p + 14));
439 break;
440
441 case IPCP_CP:
442 printf("IP-Compression-Protocol");
443 break;
444
445 case IPCP_ADDR:
446 printf("IP-Address=%s", ipaddr_string(p + 10));
447 break;
448 }
449 }
450
451 /* Standard PPP printer */
452 void
453 ppp_if_print(u_char *user, const struct pcap_pkthdr *h,
454 register const u_char *p)
455 {
456 register u_int length = h->len;
457 register u_int caplen = h->caplen;
458 const struct ip *ip;
459 u_int proto;
460
461 ts_print(&h->ts);
462
463 if (caplen < PPP_HDRLEN) {
464 printf("[|ppp]");
465 goto out;
466 }
467
468 /*
469 * Some printers want to get back at the link level addresses,
470 * and/or check that they're not walking off the end of the packet.
471 * Rather than pass them all the way down, we set these globals.
472 */
473 proto = ntohs(*(u_int16_t *)&p[2]);
474 packetp = p;
475 snapend = p + caplen;
476
477 if (eflag)
478 printf("%c %4d %02x %s: ", p[0] ? 'O' : 'I', length,
479 p[1], ppp_protoname(proto));
480
481 length -= PPP_HDRLEN;
482 ip = (struct ip *)(p + PPP_HDRLEN);
483 switch (proto) {
484 case PPP_LCP:
485 handle_lcp(p, length);
486 break;
487 case PPP_CHAP:
488 handle_chap(p, length);
489 break;
490 case PPP_PAP:
491 handle_pap(p, length);
492 break;
493 case PPP_IPCP:
494 handle_ipcp(p, length);
495 break;
496 case ETHERTYPE_IP: /*XXX*/
497 case PPP_IP:
498 ip_print((const u_char *)ip, length);
499 break;
500 #ifdef INET6
501 case ETHERTYPE_IPV6: /*XXX*/
502 #ifdef PPP_IPV6
503 case PPP_IPV6:
504 #endif
505 ip6_print((const u_char *)ip, length);
506 break;
507 #endif
508 }
509 if (xflag)
510 default_print((const u_char *)ip, caplen - PPP_HDRLEN);
511 out:
512 putchar('\n');
513 }
514
515 struct tok ppptype2str[] = {
516 { PPP_IP, "IP" },
517 { PPP_OSI, "OSI" },
518 { PPP_NS, "NS" },
519 { PPP_DECNET, "DECNET" },
520 { PPP_APPLE, "APPLE" },
521 { PPP_IPX, "IPX" },
522 { PPP_VJC, "VJC" },
523 { PPP_VJNC, "VJNC" },
524 { PPP_BRPDU, "BRPDU" },
525 { PPP_STII, "STII" },
526 { PPP_VINES, "VINES" },
527
528 { PPP_HELLO, "HELLO" },
529 { PPP_LUXCOM, "LUXCOM" },
530 { PPP_SNS, "SNS" },
531 { PPP_IPCP, "IPCP" },
532 { PPP_OSICP, "OSICP" },
533 { PPP_NSCP, "NSCP" },
534 { PPP_DECNETCP, "DECNETCP" },
535 { PPP_APPLECP, "APPLECP" },
536 { PPP_IPXCP, "IPXCP" },
537 { PPP_STIICP, "STIICP" },
538 { PPP_VINESCP, "VINESCP" },
539
540 { PPP_LCP, "LCP" },
541 { PPP_PAP, "PAP" },
542 { PPP_LQM, "LQM" },
543 { PPP_CHAP, "CHAP" },
544 { 0, NULL }
545 };
546
547 #define PPP_BSDI_HDRLEN 24
548
549 /* BSD/OS specific PPP printer */
550 void
551 ppp_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h,
552 register const u_char *p)
553 {
554 #ifdef __bsdi__
555 register u_int length = h->len;
556 register u_int caplen = h->caplen;
557 register int hdrlength;
558 u_int16_t ptype;
559 const u_char *q;
560 int i;
561
562 ts_print(&h->ts);
563
564 if (caplen < PPP_BSDI_HDRLEN) {
565 printf("[|ppp]");
566 goto out;
567 }
568
569 /*
570 * Some printers want to get back at the link level addresses,
571 * and/or check that they're not walking off the end of the packet.
572 * Rather than pass them all the way down, we set these globals.
573 */
574 packetp = p;
575 snapend = p + caplen;
576 hdrlength = 0;
577
578 #if 0
579 if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
580 if (eflag)
581 printf("%02x %02x ", p[0], p[1]);
582 p += 2;
583 hdrlength = 2;
584 }
585
586 if (eflag)
587 printf("%d ", length);
588 /* Retrieve the protocol type */
589 if (*p & 01) {
590 /* Compressed protocol field */
591 ptype = *p;
592 if (eflag)
593 printf("%02x ", ptype);
594 p++;
595 hdrlength += 1;
596 } else {
597 /* Un-compressed protocol field */
598 ptype = ntohs(*(u_int16_t *)p);
599 if (eflag)
600 printf("%04x ", ptype);
601 p += 2;
602 hdrlength += 2;
603 }
604 #else
605 ptype = 0; /*XXX*/
606 if (eflag)
607 printf("%c ", p[SLC_DIR] ? 'O' : 'I');
608 if (p[SLC_LLHL]) {
609 /* link level header */
610 struct ppp_header *ph;
611
612 q = p + SLC_BPFHDRLEN;
613 ph = (struct ppp_header *)q;
614 if (ph->phdr_addr == PPP_ADDRESS
615 && ph->phdr_ctl == PPP_CONTROL) {
616 if (eflag)
617 printf("%02x %02x ", q[0], q[1]);
618 ptype = ntohs(ph->phdr_type);
619 if (eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
620 printf("%s ", tok2str(ppptype2str,
621 "proto-#%d", ptype));
622 }
623 } else {
624 if (eflag) {
625 printf("LLH=[");
626 for (i = 0; i < p[SLC_LLHL]; i++)
627 printf("%02x", q[i]);
628 printf("] ");
629 }
630 }
631 if (eflag)
632 printf("%d ", length);
633 }
634 if (p[SLC_CHL]) {
635 q = p + SLC_BPFHDRLEN + p[SLC_LLHL];
636
637 switch (ptype) {
638 case PPP_VJC:
639 ptype = vjc_print(q, length - (q - p), ptype);
640 hdrlength = PPP_BSDI_HDRLEN;
641 p += hdrlength;
642 if (ptype == PPP_IP)
643 ip_print(p, length);
644 goto printx;
645 case PPP_VJNC:
646 ptype = vjc_print(q, length - (q - p), ptype);
647 hdrlength = PPP_BSDI_HDRLEN;
648 p += hdrlength;
649 if (ptype == PPP_IP)
650 ip_print(p, length);
651 goto printx;
652 default:
653 if (eflag) {
654 printf("CH=[");
655 for (i = 0; i < p[SLC_LLHL]; i++)
656 printf("%02x", q[i]);
657 printf("] ");
658 }
659 break;
660 }
661 }
662
663 hdrlength = PPP_BSDI_HDRLEN;
664 #endif
665
666 length -= hdrlength;
667 p += hdrlength;
668
669 if (ptype == PPP_IP)
670 ip_print(p, length);
671 else
672 printf("%s ", tok2str(ppptype2str, "proto-#%d", ptype));
673
674 printx:
675 if (xflag)
676 default_print((const u_char *)p, caplen - hdrlength);
677 out:
678 putchar('\n');
679 #endif /* __bsdi__ */
680 }