xref: /openbsd-src/usr.sbin/tcpdump/print-ppp.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: print-ppp.c,v 1.20 2008/10/10 15:24:24 claudio Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Id: print-ppp.c,v 1.20 2008/10/10 15:24:24 claudio Exp $ (LBL)";
27 #endif
28 
29 #ifdef PPP
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/socket.h>
33 #include <sys/file.h>
34 #include <sys/ioctl.h>
35 
36 struct mbuf;
37 struct rtentry;
38 #include <net/if.h>
39 
40 #include <netinet/in.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/ip.h>
43 
44 #include <ctype.h>
45 #include <netdb.h>
46 #include <pcap.h>
47 #include <signal.h>
48 #include <stdio.h>
49 
50 #include <netinet/if_ether.h>
51 #include "ethertype.h"
52 
53 #include <net/ppp_defs.h>
54 #include "interface.h"
55 #include "addrtoname.h"
56 #include "extract.h"
57 
58 struct protonames {
59 	u_short protocol;
60 	char *name;
61 };
62 
63 static struct protonames protonames[] = {
64 	/*
65 	 * Protocol field values.
66 	 */
67 	{ PPP_IP,	"IP" },		/* Internet Protocol */
68 	{ PPP_XNS,	"XNS" },	/* Xerox NS */
69 	{ PPP_IPX,	"IPX" },	/* IPX Datagram (RFC1552) */
70 	{ PPP_VJC_COMP,	"VJC_UNCOMP" },	/* VJ compressed TCP */
71 	{ PPP_VJC_UNCOMP,"VJC_UNCOMP" },/* VJ uncompressed TCP */
72 	{ PPP_COMP,	"COMP" },	/* compressed packet */
73 	{ PPP_IPCP,	"IPCP" },	/* IP Control Protocol */
74 	{ PPP_IPXCP,	"IPXCP" },	/* IPX Control Protocol (RFC1552) */
75 	{ PPP_CCP,	"CCP" },	/* Compression Control Protocol */
76 	{ PPP_LCP,	"LCP" },	/* Link Control Protocol */
77 	{ PPP_PAP,	"PAP" },	/* Password Authentication Protocol */
78 	{ PPP_LQR,	"LQR" },	/* Link Quality Report protocol */
79 	{ PPP_CHAP,	"CHAP" },	/* Cryptographic Handshake Auth. Proto */
80 	{ PPP_IPV6,	"IPV6" },	/* Internet Protocol v6 */
81 };
82 
83 /* LCP */
84 
85 #define LCP_CONF_REQ	1
86 #define LCP_CONF_ACK	2
87 #define LCP_CONF_NAK	3
88 #define LCP_CONF_REJ	4
89 #define LCP_TERM_REQ	5
90 #define LCP_TERM_ACK	6
91 #define LCP_CODE_REJ	7
92 #define LCP_PROT_REJ	8
93 #define LCP_ECHO_REQ	9
94 #define LCP_ECHO_RPL	10
95 #define LCP_DISC_REQ	11
96 
97 #define LCP_MIN	LCP_CONF_REQ
98 #define LCP_MAX LCP_DISC_REQ
99 
100 static char *lcpcodes[] = {
101 	/*
102 	 * LCP code values (RFC1661, pp26)
103 	 */
104 	"Configure-Request",
105 	"Configure-Ack",
106 	"Configure-Nak",
107 	"Configure-Reject",
108 	"Terminate-Request",
109 	"Terminate-Ack",
110  	"Code-Reject",
111 	"Protocol-Reject",
112 	"Echo-Request",
113 	"Echo-Reply",
114 	"Discard-Request",
115 };
116 
117 #define LCPOPT_VEXT	0
118 #define LCPOPT_MRU	1
119 #define LCPOPT_ACCM	2
120 #define LCPOPT_AP	3
121 #define LCPOPT_QP	4
122 #define LCPOPT_MN	5
123 #define LCPOPT_PFC	7
124 #define LCPOPT_ACFC	8
125 
126 #define LCPOPT_MIN 0
127 #define LCPOPT_MAX 24
128 
129 static char *lcpconfopts[] = {
130 	"Vendor-Ext",
131 	"Max-Rx-Unit",
132 	"Async-Ctrl-Char-Map",
133 	"Auth-Prot",
134 	"Quality-Prot",
135 	"Magic-Number",
136 	"unassigned (6)",
137 	"Prot-Field-Compr",
138 	"Add-Ctrl-Field-Compr",
139 	"FCS-Alternatives",
140 	"Self-Describing-Pad",
141 	"Numbered-Mode",
142 	"Multi-Link-Procedure",
143 	"Call-Back",
144 	"Connect-Time"
145 	"Compund-Frames",
146 	"Nominal-Data-Encap",
147 	"Multilink-MRRU",
148 	"Multilink-SSNHF",
149 	"Multilink-ED",
150 	"Proprietary",
151 	"DCE-Identifier",
152 	"Multilink-Plus-Proc",
153 	"Link-Discriminator",
154 	"LCP-Auth-Option",
155 };
156 
157 /* CHAP */
158 
159 #define CHAP_CHAL	1
160 #define CHAP_RESP	2
161 #define CHAP_SUCC	3
162 #define CHAP_FAIL	4
163 
164 #define CHAP_CODEMIN 1
165 #define CHAP_CODEMAX 4
166 
167 static char *chapcode[] = {
168 	"Challenge",
169 	"Response",
170 	"Success",
171 	"Failure",
172 };
173 
174 /* PAP */
175 
176 #define PAP_AREQ	1
177 #define PAP_AACK	2
178 #define PAP_ANAK	3
179 
180 #define PAP_CODEMIN	1
181 #define PAP_CODEMAX	3
182 
183 static char *papcode[] = {
184 	"Authenticate-Request",
185 	"Authenticate-Ack",
186 	"Authenticate-Nak",
187 };
188 
189 /* IPCP */
190 
191 #define IPCP_CODE_CFG_REQ	1
192 #define IPCP_CODE_CFG_ACK	2
193 #define IPCP_CODE_CFG_NAK	3
194 #define IPCP_CODE_CFG_REJ	4
195 #define IPCP_CODE_TRM_REQ	5
196 #define IPCP_CODE_TRM_ACK	6
197 #define IPCP_CODE_COD_REJ	7
198 
199 #define IPCP_CODE_MIN IPCP_CODE_CFG_REQ
200 #define IPCP_CODE_MAX IPCP_CODE_COD_REJ
201 
202 #define IPCP_2ADDR	1
203 #define IPCP_CP		2
204 #define IPCP_ADDR	3
205 
206 static int print_lcp_config_options(u_char *p);
207 static void handle_lcp(const u_char *p, int length);
208 static void handle_chap(const u_char *p, int length);
209 static void handle_ipcp(const u_char *p, int length);
210 static void handle_pap(const u_char *p, int length);
211 
212 struct pppoe_header {
213 	u_int8_t vertype;	/* PPPoE version/type */
214 	u_int8_t code;		/* PPPoE code (packet type) */
215 	u_int16_t sessionid;	/* PPPoE session id */
216 	u_int16_t len;		/* PPPoE payload length */
217 };
218 #define	PPPOE_CODE_SESSION	0x00	/* Session */
219 #define	PPPOE_CODE_PADO		0x07	/* Active Discovery Offer */
220 #define	PPPOE_CODE_PADI		0x09	/* Active Discovery Initiation */
221 #define	PPPOE_CODE_PADR		0x19	/* Active Discovery Request */
222 #define	PPPOE_CODE_PADS		0x65	/* Active Discovery Session-Confirm */
223 #define	PPPOE_CODE_PADT		0xa7	/* Active Discovery Terminate */
224 #define	PPPOE_TAG_END_OF_LIST		0x0000	/* End Of List */
225 #define	PPPOE_TAG_SERVICE_NAME		0x0101	/* Service Name */
226 #define	PPPOE_TAG_AC_NAME		0x0102	/* Access Concentrator Name */
227 #define	PPPOE_TAG_HOST_UNIQ		0x0103	/* Host Uniq */
228 #define	PPPOE_TAG_AC_COOKIE		0x0104	/* Access Concentratr Cookie */
229 #define	PPPOE_TAG_VENDOR_SPEC		0x0105	/* Vendor Specific */
230 #define	PPPOE_TAG_RELAY_SESSION		0x0110	/* Relay Session Id */
231 #define	PPPOE_TAG_SERVICE_NAME_ERROR	0x0201	/* Service Name Error */
232 #define	PPPOE_TAG_AC_SYSTEM_ERROR	0x0202	/* Acc. Concentrator Error */
233 #define	PPPOE_TAG_GENERIC_ERROR		0x0203	/* Generic Error */
234 
235 void
236 ppp_hdlc_print(p, length)
237 	const u_char *p;
238 	int length;
239 {
240 	int proto = PPP_PROTOCOL(p);
241 	int i;
242 
243 	printf("ID-%03d ", *(p+5));
244 
245 	for (i = sizeof(protonames) / sizeof(protonames[0]) - 1; i >= 0; i--) {
246 		if (proto == protonames[i].protocol) {
247 			printf("%s: ", protonames[i].name);
248 
249 			switch(proto) {
250 
251 			case PPP_LCP:
252 				handle_lcp(p, length);
253 				break;
254 			case PPP_CHAP:
255 				handle_chap(p, length);
256 				break;
257 			case PPP_PAP:
258 				handle_pap(p, length);
259 				break;
260 			case PPP_IPCP:
261 				handle_ipcp(p, length);
262 				break;
263 			}
264 			break;
265 		}
266 	}
267 	if (i < 0)
268 		printf("%04x: ", proto);
269 }
270 
271 /* print LCP frame */
272 
273 static void
274 handle_lcp(p, length)
275 	const u_char *p;
276 	int length;
277 {
278 	int x, j;
279 	u_char *ptr;
280 
281 	x = *(p + 4);
282 
283 	if ((x >= LCP_MIN) && (x <= LCP_MAX))
284 		printf("%s", lcpcodes[x-1]);
285 	else {
286 		printf("0x%02x", x);
287 		return;
288 	}
289 
290 	length -= 4;
291 
292 	switch(x) {
293 
294 	case LCP_CONF_REQ:
295 	case LCP_CONF_ACK:
296 	case LCP_CONF_NAK:
297 	case LCP_CONF_REJ:
298 		x = length;
299 		ptr = (u_char *)p+8;
300 		do {
301 			if((j = print_lcp_config_options(ptr)) == 0)
302 				break;
303 			x -= j;
304 			ptr += j;
305 		}
306 		while(x > 0);
307 		break;
308 
309 	case LCP_ECHO_REQ:
310 	case LCP_ECHO_RPL:
311 		printf(", Magic-Number=%d", ((*(p+ 8) << 24) + (*(p+9) << 16) +
312 					     (*(p+10) <<  8) + (*(p+11))));
313 		break;
314 	case LCP_TERM_REQ:
315 	case LCP_TERM_ACK:
316 	case LCP_CODE_REJ:
317 	case LCP_PROT_REJ:
318 	case LCP_DISC_REQ:
319 	default:
320 		break;
321 	}
322 }
323 
324 /* LCP config options */
325 
326 static int
327 print_lcp_config_options(p)
328 	u_char *p;
329 {
330 	int len	= *(p+1);
331 	int opt = *p;
332 
333 	if((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
334 		printf(", %s", lcpconfopts[opt]);
335 
336 	switch(opt) {
337 	case LCPOPT_MRU:
338 		if(len == 4)
339 			printf("=%d", (*(p+2) << 8) + *(p+3));
340 		break;
341 	case LCPOPT_AP:
342 		if(len >= 4) {
343 			if(*(p+2) == 0xc0 && *(p+3) == 0x23)
344 				printf(" PAP");
345 			else if(*(p+2) == 0xc2 && *(p+3) == 0x23) {
346 				printf(" CHAP/");
347 				switch(*(p+4)) {
348 				default:
349 					printf("unknown-algorithm-%d", *(p+4));
350 					break;
351 				case 5:
352 					printf("MD5");
353 					break;
354 				case 0x80:
355 					printf("Microsoft");
356 					break;
357 				}
358 			} else if(*(p+2) == 0xc2 && *(p+3) == 0x27)
359 					printf(" EAP");
360 			else if(*(p+2) == 0xc0 && *(p+3) == 0x27)
361 				printf(" SPAP");
362 			else if(*(p+2) == 0xc1 && *(p+3) == 0x23)
363 				printf(" Old-SPAP");
364 			else
365 				printf("unknown");
366 		}
367 		break;
368 	case LCPOPT_QP:
369 		if(len >= 4) {
370 			if(*(p+2) == 0xc0 && *(p+3) == 0x25)
371 				printf(" LQR");
372 			else
373 				printf(" unknown");
374 		}
375 		break;
376 	case LCPOPT_MN:
377 		if(len == 6)
378 			printf("=%d", ((*(p+2) << 24) + (*(p+3) << 16) +
379 				       (*(p+4) <<  8) + (*(p+5))));
380 		break;
381 	case LCPOPT_PFC:
382 		printf(" PFC");
383 		break;
384 	case LCPOPT_ACFC:
385 		printf(" ACFC");
386 		break;
387 	}
388 	return(len);
389 }
390 
391 /* CHAP */
392 
393 static void
394 handle_chap(p, length)
395 	const u_char *p;
396 	int length;
397 {
398 	int x;
399 	u_char *ptr;
400 
401 	x = *(p+4);
402 
403 	if((x >= CHAP_CODEMIN) && (x <= CHAP_CODEMAX))
404 		printf("%s", chapcode[x-1]);
405 	else {
406 		printf("0x%02x", x);
407 		return;
408 	}
409 
410 	length -= 4;
411 
412 	switch(x) {
413 	case CHAP_CHAL:
414 	case CHAP_RESP:
415 		printf(", Value=");
416 		x = *(p+8);	/* value size */
417 		ptr = (u_char *)p+9;
418 		while(--x >= 0)
419 			printf("%02x", *ptr++);
420 		x = length - *(p+8) - 1;
421 		printf(", Name=");
422 		while(--x >= 0)
423 			printf("%c", *ptr++);
424 		break;
425 	}
426 }
427 
428 /* PAP */
429 
430 static void
431 handle_pap(p, length)
432 	const u_char *p;
433 	int length;
434 {
435 	int x;
436 	u_char *ptr;
437 
438 	x = *(p+4);
439 
440 	if((x >= PAP_CODEMIN) && (x <= PAP_CODEMAX))
441 		printf("%s", papcode[x-1]);
442 	else {
443 		printf("0x%02x", x);
444 		return;
445 	}
446 
447 	length -= 4;
448 
449 	switch(x) {
450 	case PAP_AREQ:
451 		printf(", Peer-Id=");
452 		x = *(p+8);	/* peerid size */
453 		ptr = (u_char *)p+9;
454 		while(--x >= 0)
455 			printf("%c", *ptr++);
456 		x = *ptr++;
457 		printf(", Passwd=");
458 		while(--x >= 0)
459 			printf("%c", *ptr++);
460 		break;
461 	case PAP_AACK:
462 	case PAP_ANAK:
463 		break;
464 	}
465 }
466 
467 /* IPCP */
468 
469 static void
470 handle_ipcp(p, length)
471 	const u_char *p;
472 	int length;
473 {
474 	int x;
475 
476 	x = *(p+4);
477 
478 	if((x >= IPCP_CODE_MIN) && (x <= IPCP_CODE_MAX))
479 		printf("%s", lcpcodes[x-1]);	/* share table with LCP */
480 	else {
481 		printf("0x%02x", x);
482 		return;
483 	}
484 
485 	length -= 4;
486 
487 	switch(*(p+8)) {
488 	case IPCP_2ADDR:
489 		printf(", IP-Addresses");
490 		printf(", Src=%d.%d.%d.%d",
491 		       *(p+10), *(p+11), *(p+12), *(p+13));
492 		printf(", Dst=%d.%d.%d.%d",
493 		       *(p+14), *(p+15), *(p+16), *(p+17));
494 		break;
495 
496 	case IPCP_CP:
497 		printf(", IP-Compression-Protocol");
498 		break;
499 
500 	case IPCP_ADDR:
501 		printf(", IP-Address=%d.%d.%d.%d",
502 		       *(p+10), *(p+11), *(p+12), *(p+13));
503 		break;
504 	default:
505 		printf(", Unknown IPCP code 0x%x", *(p+8));
506 		break;
507 	}
508 }
509 
510 void
511 ppp_if_print(user, h, p)
512 	u_char *user;
513 	const struct pcap_pkthdr *h;
514 	register const u_char *p;
515 {
516 	register u_int length = h->len;
517 	register u_int caplen = h->caplen;
518 
519 	ts_print(&h->ts);
520 
521 	if (caplen < PPP_HDRLEN) {
522 		printf("[|ppp]");
523 		goto out;
524 	}
525 
526 	/*
527 	 * Some printers want to get back at the link level addresses,
528 	 * and/or check that they're not walking off the end of the packet.
529 	 * Rather than pass them all the way down, we set these globals.
530 	 */
531 	packetp = p;
532 	snapend = p + caplen;
533 
534 	if (eflag)
535 		ppp_hdlc_print(p, length);
536 
537 	length -= PPP_HDRLEN;
538 
539 	switch(PPP_PROTOCOL(p)) {
540 	case PPP_IP:
541 	case ETHERTYPE_IP:
542 		ip_print((const u_char *)(p + PPP_HDRLEN), length);
543 		break;
544 	case PPP_IPV6:
545 	case ETHERTYPE_IPV6:
546 		ip6_print((const u_char *)(p + PPP_HDRLEN), length);
547 		break;
548 	case PPP_IPX:
549 	case ETHERTYPE_IPX:
550 		ipx_print((const u_char *)(p + PPP_HDRLEN), length);
551 		break;
552 
553 #ifndef	PPP_MPLS
554 #define	PPP_MPLS	0x0281
555 #endif
556 	case PPP_MPLS:
557 		mpls_print((const u_char *)(p + PPP_HDRLEN), length);
558 		break;
559 
560 	default:
561 		if(!eflag)
562 			ppp_hdlc_print(p, length);
563 		if(!xflag)
564 			default_print((const u_char *)(p + PPP_HDRLEN),
565 				      caplen - PPP_HDRLEN);
566 	}
567 
568 	if (xflag)
569 		default_print((const u_char *)(p + PPP_HDRLEN),
570 			      caplen - PPP_HDRLEN);
571 out:
572 	putchar('\n');
573 }
574 
575 void
576 ppp_ether_if_print(user, h, p)
577 	u_char *user;
578 	const struct pcap_pkthdr *h;
579 	register const u_char *p;
580 {
581 	u_int16_t pppoe_sid, pppoe_len;
582 	u_int caplen = h->caplen;
583 	u_int16_t length = h->len;
584 	u_int16_t proto;
585 	int i;
586 
587 	ts_print(&h->ts);
588 
589 	packetp = p;
590 	snapend = p + caplen;
591 
592 	if (eflag)
593 		printf("PPPoE ");
594 
595 	if (caplen < sizeof(struct pppoe_header)) {
596 		printf("[|pppoe]");
597 		return;
598 	}
599 
600 	if(eflag)
601 	{
602 		printf("\n\tcode ");
603 		switch (p[1]) {
604 		case PPPOE_CODE_PADI:
605 			printf("Initiation");
606 			break;
607 		case PPPOE_CODE_PADO:
608 			printf("Offer");
609 			break;
610 		case PPPOE_CODE_PADR:
611 			printf("Request");
612 			break;
613 		case PPPOE_CODE_PADS:
614 			printf("Confirm");
615 			break;
616 		case PPPOE_CODE_PADT:
617 			printf("Terminate");
618 			break;
619 		case PPPOE_CODE_SESSION:
620 			printf("Session");
621 			break;
622 		default:
623 			printf("Unknown(0x%02x)", p[1]);
624 			break;
625 		}
626 	}
627 
628 	pppoe_sid = EXTRACT_16BITS(p + 2);
629 	pppoe_len = EXTRACT_16BITS(p + 4);
630 
631 	if(eflag)
632 	    printf(", version %d, type %d, id 0x%04x, length %d",
633 		    (p[0] & 0xf), (p[0] & 0xf0) >> 4, pppoe_sid, pppoe_len);
634 
635 	length -= sizeof(struct pppoe_header);
636 	caplen -= sizeof(struct pppoe_header);
637 	p += sizeof(struct pppoe_header);
638 
639 	if (pppoe_len > caplen)
640 		pppoe_len = caplen;
641 
642 	if (pppoe_len < 2) {
643 		printf("[|pppoe]");
644 		return;
645 	}
646 	proto = EXTRACT_16BITS(p);
647 
648 	for (i = sizeof(protonames)/sizeof(protonames[0]) - 1; i >= 0; i--) {
649 		if (proto == protonames[i].protocol) {
650 			if (eflag)
651 				printf("\n\t%s: ", protonames[i].name);
652 			switch (proto) {
653 			case PPP_LCP:
654 				handle_lcp(p - 2, length + 2);
655 				break;
656 			case PPP_CHAP:
657 				handle_chap(p - 2, length + 2);
658 				break;
659 			case PPP_PAP:
660 				handle_pap(p - 2, length + 2);
661 				break;
662 			case PPP_IPCP:
663 				handle_ipcp(p - 2, length + 2);
664 				break;
665 			case PPP_IP:
666 				ip_print(p + 2, length - 2);
667 				break;
668 			case PPP_IPV6:
669 				ip6_print(p + 2, length - 2);
670 				break;
671 			case PPP_IPX:
672 				ipx_print(p + 2, length - 2);
673 			}
674 			break;
675 		}
676 	}
677 	if (i < 0)
678 		printf("\n\t%04x: ", proto);
679 
680 	if (xflag)
681 	    default_print(p + 2, caplen - 2);
682 	putchar('\n');
683 }
684 
685 int
686 pppoe_if_print(ethertype, p, length, caplen)
687 	u_short ethertype;
688 	const u_char *p;
689 	u_int length, caplen;
690 {
691 	u_int16_t pppoe_sid, pppoe_len;
692 
693 	if (ethertype == ETHERTYPE_PPPOEDISC)
694 		printf("PPPoE-Discovery");
695 	else
696 		printf("PPPoE-Session");
697 
698 	if (caplen < sizeof(struct pppoe_header)) {
699 		printf("[|pppoe]");
700 		return (1);
701 	}
702 
703 	printf("\n\tcode ");
704 	switch (p[1]) {
705 	case PPPOE_CODE_PADI:
706 		printf("Initiation");
707 		break;
708 	case PPPOE_CODE_PADO:
709 		printf("Offer");
710 		break;
711 	case PPPOE_CODE_PADR:
712 		printf("Request");
713 		break;
714 	case PPPOE_CODE_PADS:
715 		printf("Confirm");
716 		break;
717 	case PPPOE_CODE_PADT:
718 		printf("Terminate");
719 		break;
720 	case PPPOE_CODE_SESSION:
721 		printf("Session");
722 		break;
723 	default:
724 		printf("Unknown(0x%02x)", p[1]);
725 		break;
726 	}
727 
728 	pppoe_sid = EXTRACT_16BITS(p + 2);
729 	pppoe_len = EXTRACT_16BITS(p + 4);
730 	printf(", version %d, type %d, id 0x%04x, length %d",
731 	    (p[0] & 0xf), (p[0] & 0xf0) >> 4, pppoe_sid, pppoe_len);
732 
733 	length -= sizeof(struct pppoe_header);
734 	caplen -= sizeof(struct pppoe_header);
735 	p += sizeof(struct pppoe_header);
736 
737 	if (pppoe_len > caplen)
738 		pppoe_len = caplen;
739 
740 	if (ethertype == ETHERTYPE_PPPOEDISC) {
741 		while (pppoe_len > 0) {
742 			u_int16_t t_type, t_len;
743 
744 			if (pppoe_len < 4) {
745 				printf("\n\t[|pppoe]");
746 				break;
747 			}
748 			t_type = EXTRACT_16BITS(p);
749 			t_len = EXTRACT_16BITS(p + 2);
750 
751 			pppoe_len -= 4;
752 			p += 4;
753 
754 			if (pppoe_len < t_len) {
755 				printf("\n\t[|pppoe]");
756 				break;
757 			}
758 
759 			printf("\n\ttag ");
760 			switch (t_type) {
761 			case PPPOE_TAG_END_OF_LIST:
762 				printf("End-Of-List");
763 				break;
764 			case PPPOE_TAG_SERVICE_NAME:
765 				printf("Service-Name");
766 				break;
767 			case PPPOE_TAG_AC_NAME:
768 				printf("AC-Name");
769 				break;
770 			case PPPOE_TAG_HOST_UNIQ:
771 				printf("Host-Uniq");
772 				break;
773 			case PPPOE_TAG_AC_COOKIE:
774 				printf("AC-Cookie");
775 				break;
776 			case PPPOE_TAG_VENDOR_SPEC:
777 				printf("Vendor-Specific");
778 				break;
779 			case PPPOE_TAG_RELAY_SESSION:
780 				printf("Relay-Session");
781 				break;
782 			case PPPOE_TAG_SERVICE_NAME_ERROR:
783 				printf("Service-Name-Error");
784 				break;
785 			case PPPOE_TAG_AC_SYSTEM_ERROR:
786 				printf("AC-System-Error");
787 				break;
788 			case PPPOE_TAG_GENERIC_ERROR:
789 				printf("Generic-Error");
790 				break;
791 			default:
792 				printf("Unknown(0x%04x)", t_type);
793 			}
794 			printf(", length %u%s", t_len, t_len ? " " : "");
795 
796 			if (t_len) {
797 				for (t_type = 0; t_type < t_len; t_type++) {
798 					if (isprint(p[t_type]))
799 						printf("%c", p[t_type]);
800 					else
801 						printf("\\%03o", p[t_type]);
802 				}
803 			}
804 			pppoe_len -= t_len;
805 			p += t_len;
806 		}
807 	}
808 	else if (ethertype == ETHERTYPE_PPPOE) {
809 		u_int16_t proto;
810 		int i;
811 
812 		if (pppoe_len < 2) {
813 			printf("[|pppoe]");
814 			return (1);
815 		}
816 		proto = EXTRACT_16BITS(p);
817 
818 		for (i = sizeof(protonames)/sizeof(protonames[0]) - 1; i >= 0;
819 		     i--) {
820 			if (proto == protonames[i].protocol) {
821 				printf("\n\t%s: ", protonames[i].name);
822 				switch (proto) {
823 				case PPP_LCP:
824 					handle_lcp(p - 2, length + 2);
825 					break;
826 				case PPP_CHAP:
827 					handle_chap(p - 2, length + 2);
828 					break;
829 				case PPP_PAP:
830 					handle_pap(p - 2, length + 2);
831 					break;
832 				case PPP_IPCP:
833 					handle_ipcp(p - 2, length + 2);
834 					break;
835 				case PPP_IP:
836 					ip_print(p + 2, length - 2);
837 					break;
838 				case PPP_IPV6:
839 					ip6_print(p + 2, length - 2);
840 					break;
841 				case PPP_IPX:
842 					ipx_print(p + 2, length - 2);
843 				}
844 				break;
845 			}
846 		}
847 		if (i < 0)
848 			printf("\n\t%04x: ", proto);
849 	}
850 
851 	return (1);
852 }
853 
854 #else
855 
856 #include <sys/types.h>
857 #include <sys/time.h>
858 
859 #include <stdio.h>
860 
861 #include "interface.h"
862 void
863 ppp_if_print(user, h, p)
864 	u_char *user;
865 	const struct pcap_pkthdr *h;
866 	const u_char *p;
867 {
868 	error("not configured for ppp");
869 	/* NOTREACHED */
870 }
871 #endif
872