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