xref: /minix/external/bsd/tcpdump/dist/print-ppp.c (revision b636d99d)
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  * Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more
22  * complete PPP support.
23  */
24 
25 /*
26  * TODO:
27  * o resolve XXX as much as possible
28  * o MP support
29  * o BAP support
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: print-ppp.c,v 1.6 2015/03/31 21:59:35 christos Exp $");
35 #endif
36 
37 #define NETDISSECT_REWORKED
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 
42 #include <tcpdump-stdinc.h>
43 
44 #ifdef __bsdi__
45 #include <net/slcompress.h>
46 #include <net/if_ppp.h>
47 #endif
48 
49 #include <stdlib.h>
50 
51 #include "interface.h"
52 #include "extract.h"
53 #include "addrtoname.h"
54 #include "ppp.h"
55 #include "chdlc.h"
56 #include "ethertype.h"
57 #include "oui.h"
58 
59 /*
60  * The following constatns are defined by IANA. Please refer to
61  *    http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
62  * for the up-to-date information.
63  */
64 
65 /* Protocol Codes defined in ppp.h */
66 
67 static const struct tok ppptype2str[] = {
68         { PPP_IP,	  "IP" },
69         { PPP_OSI,	  "OSI" },
70         { PPP_NS,	  "NS" },
71         { PPP_DECNET,	  "DECNET" },
72         { PPP_APPLE,	  "APPLE" },
73 	{ PPP_IPX,	  "IPX" },
74 	{ PPP_VJC,	  "VJC IP" },
75 	{ PPP_VJNC,	  "VJNC IP" },
76 	{ PPP_BRPDU,	  "BRPDU" },
77 	{ PPP_STII,	  "STII" },
78 	{ PPP_VINES,	  "VINES" },
79 	{ PPP_MPLS_UCAST, "MPLS" },
80 	{ PPP_MPLS_MCAST, "MPLS" },
81         { PPP_COMP,       "Compressed"},
82         { PPP_ML,         "MLPPP"},
83         { PPP_IPV6,       "IP6"},
84 
85 	{ PPP_HELLO,	  "HELLO" },
86 	{ PPP_LUXCOM,	  "LUXCOM" },
87 	{ PPP_SNS,	  "SNS" },
88 	{ PPP_IPCP,	  "IPCP" },
89 	{ PPP_OSICP,	  "OSICP" },
90 	{ PPP_NSCP,	  "NSCP" },
91 	{ PPP_DECNETCP,   "DECNETCP" },
92 	{ PPP_APPLECP,	  "APPLECP" },
93 	{ PPP_IPXCP,	  "IPXCP" },
94 	{ PPP_STIICP,	  "STIICP" },
95 	{ PPP_VINESCP,	  "VINESCP" },
96         { PPP_IPV6CP,     "IP6CP" },
97 	{ PPP_MPLSCP,	  "MPLSCP" },
98 
99 	{ PPP_LCP,	  "LCP" },
100 	{ PPP_PAP,	  "PAP" },
101 	{ PPP_LQM,	  "LQM" },
102 	{ PPP_CHAP,	  "CHAP" },
103 	{ PPP_EAP,	  "EAP" },
104 	{ PPP_SPAP,	  "SPAP" },
105 	{ PPP_SPAP_OLD,	  "Old-SPAP" },
106 	{ PPP_BACP,	  "BACP" },
107 	{ PPP_BAP,	  "BAP" },
108 	{ PPP_MPCP,	  "MLPPP-CP" },
109 	{ PPP_CCP,	  "CCP" },
110 	{ 0,		  NULL }
111 };
112 
113 /* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */
114 
115 #define CPCODES_VEXT		0	/* Vendor-Specific (RFC2153) */
116 #define CPCODES_CONF_REQ	1	/* Configure-Request */
117 #define CPCODES_CONF_ACK	2	/* Configure-Ack */
118 #define CPCODES_CONF_NAK	3	/* Configure-Nak */
119 #define CPCODES_CONF_REJ	4	/* Configure-Reject */
120 #define CPCODES_TERM_REQ	5	/* Terminate-Request */
121 #define CPCODES_TERM_ACK	6	/* Terminate-Ack */
122 #define CPCODES_CODE_REJ	7	/* Code-Reject */
123 #define CPCODES_PROT_REJ	8	/* Protocol-Reject (LCP only) */
124 #define CPCODES_ECHO_REQ	9	/* Echo-Request (LCP only) */
125 #define CPCODES_ECHO_RPL	10	/* Echo-Reply (LCP only) */
126 #define CPCODES_DISC_REQ	11	/* Discard-Request (LCP only) */
127 #define CPCODES_ID		12	/* Identification (LCP only) RFC1570 */
128 #define CPCODES_TIME_REM	13	/* Time-Remaining (LCP only) RFC1570 */
129 #define CPCODES_RESET_REQ	14	/* Reset-Request (CCP only) RFC1962 */
130 #define CPCODES_RESET_REP	15	/* Reset-Reply (CCP only) */
131 
132 static const struct tok cpcodes[] = {
133 	{CPCODES_VEXT,      "Vendor-Extension"}, /* RFC2153 */
134 	{CPCODES_CONF_REQ,  "Conf-Request"},
135         {CPCODES_CONF_ACK,  "Conf-Ack"},
136 	{CPCODES_CONF_NAK,  "Conf-Nack"},
137 	{CPCODES_CONF_REJ,  "Conf-Reject"},
138 	{CPCODES_TERM_REQ,  "Term-Request"},
139 	{CPCODES_TERM_ACK,  "Term-Ack"},
140 	{CPCODES_CODE_REJ,  "Code-Reject"},
141 	{CPCODES_PROT_REJ,  "Prot-Reject"},
142 	{CPCODES_ECHO_REQ,  "Echo-Request"},
143 	{CPCODES_ECHO_RPL,  "Echo-Reply"},
144 	{CPCODES_DISC_REQ,  "Disc-Req"},
145 	{CPCODES_ID,        "Ident"},            /* RFC1570 */
146 	{CPCODES_TIME_REM,  "Time-Rem"},         /* RFC1570 */
147 	{CPCODES_RESET_REQ, "Reset-Req"},        /* RFC1962 */
148 	{CPCODES_RESET_REP, "Reset-Ack"},        /* RFC1962 */
149         {0,                 NULL}
150 };
151 
152 /* LCP Config Options */
153 
154 #define LCPOPT_VEXT	0
155 #define LCPOPT_MRU	1
156 #define LCPOPT_ACCM	2
157 #define LCPOPT_AP	3
158 #define LCPOPT_QP	4
159 #define LCPOPT_MN	5
160 #define LCPOPT_DEP6	6
161 #define LCPOPT_PFC	7
162 #define LCPOPT_ACFC	8
163 #define LCPOPT_FCSALT	9
164 #define LCPOPT_SDP	10
165 #define LCPOPT_NUMMODE	11
166 #define LCPOPT_DEP12	12
167 #define LCPOPT_CBACK	13
168 #define LCPOPT_DEP14	14
169 #define LCPOPT_DEP15	15
170 #define LCPOPT_DEP16	16
171 #define LCPOPT_MLMRRU	17
172 #define LCPOPT_MLSSNHF	18
173 #define LCPOPT_MLED	19
174 #define LCPOPT_PROP	20
175 #define LCPOPT_DCEID	21
176 #define LCPOPT_MPP	22
177 #define LCPOPT_LD	23
178 #define LCPOPT_LCPAOPT	24
179 #define LCPOPT_COBS	25
180 #define LCPOPT_PE	26
181 #define LCPOPT_MLHF	27
182 #define LCPOPT_I18N	28
183 #define LCPOPT_SDLOS	29
184 #define LCPOPT_PPPMUX	30
185 
186 #define LCPOPT_MIN LCPOPT_VEXT
187 #define LCPOPT_MAX LCPOPT_PPPMUX
188 
189 static const char *lcpconfopts[] = {
190 	"Vend-Ext",		/* (0) */
191 	"MRU",			/* (1) */
192 	"ACCM",			/* (2) */
193 	"Auth-Prot",		/* (3) */
194 	"Qual-Prot",		/* (4) */
195 	"Magic-Num",		/* (5) */
196 	"deprecated(6)",	/* used to be a Quality Protocol */
197 	"PFC",			/* (7) */
198 	"ACFC",			/* (8) */
199 	"FCS-Alt",		/* (9) */
200 	"SDP",			/* (10) */
201 	"Num-Mode",		/* (11) */
202 	"deprecated(12)",	/* used to be a Multi-Link-Procedure*/
203 	"Call-Back",		/* (13) */
204 	"deprecated(14)",	/* used to be a Connect-Time */
205 	"deprecated(15)",	/* used to be a Compund-Frames */
206 	"deprecated(16)",	/* used to be a Nominal-Data-Encap */
207 	"MRRU",			/* (17) */
208 	"12-Bit seq #",		/* (18) */
209 	"End-Disc",		/* (19) */
210 	"Proprietary",		/* (20) */
211 	"DCE-Id",		/* (21) */
212 	"MP+",			/* (22) */
213 	"Link-Disc",		/* (23) */
214 	"LCP-Auth-Opt",		/* (24) */
215 	"COBS",			/* (25) */
216 	"Prefix-elision",	/* (26) */
217 	"Multilink-header-Form",/* (27) */
218 	"I18N",			/* (28) */
219 	"SDL-over-SONET/SDH",	/* (29) */
220 	"PPP-Muxing",		/* (30) */
221 };
222 
223 /* ECP - to be supported */
224 
225 /* CCP Config Options */
226 
227 #define CCPOPT_OUI	0	/* RFC1962 */
228 #define CCPOPT_PRED1	1	/* RFC1962 */
229 #define CCPOPT_PRED2	2	/* RFC1962 */
230 #define CCPOPT_PJUMP	3	/* RFC1962 */
231 /* 4-15 unassigned */
232 #define CCPOPT_HPPPC	16	/* RFC1962 */
233 #define CCPOPT_STACLZS	17	/* RFC1974 */
234 #define CCPOPT_MPPC	18	/* RFC2118 */
235 #define CCPOPT_GFZA	19	/* RFC1962 */
236 #define CCPOPT_V42BIS	20	/* RFC1962 */
237 #define CCPOPT_BSDCOMP	21	/* RFC1977 */
238 /* 22 unassigned */
239 #define CCPOPT_LZSDCP	23	/* RFC1967 */
240 #define CCPOPT_MVRCA	24	/* RFC1975 */
241 #define CCPOPT_DEC	25	/* RFC1976 */
242 #define CCPOPT_DEFLATE	26	/* RFC1979 */
243 /* 27-254 unassigned */
244 #define CCPOPT_RESV	255	/* RFC1962 */
245 
246 static const struct tok ccpconfopts_values[] = {
247         { CCPOPT_OUI, "OUI" },
248         { CCPOPT_PRED1, "Pred-1" },
249         { CCPOPT_PRED2, "Pred-2" },
250         { CCPOPT_PJUMP, "Puddle" },
251         { CCPOPT_HPPPC, "HP-PPC" },
252         { CCPOPT_STACLZS, "Stac-LZS" },
253         { CCPOPT_MPPC, "MPPC" },
254         { CCPOPT_GFZA, "Gand-FZA" },
255         { CCPOPT_V42BIS, "V.42bis" },
256         { CCPOPT_BSDCOMP, "BSD-Comp" },
257         { CCPOPT_LZSDCP, "LZS-DCP" },
258         { CCPOPT_MVRCA, "MVRCA" },
259         { CCPOPT_DEC, "DEC" },
260         { CCPOPT_DEFLATE, "Deflate" },
261         { CCPOPT_RESV, "Reserved"},
262         {0,                 NULL}
263 };
264 
265 /* BACP Config Options */
266 
267 #define BACPOPT_FPEER	1	/* RFC2125 */
268 
269 static const struct tok bacconfopts_values[] = {
270         { BACPOPT_FPEER, "Favored-Peer" },
271         {0,                 NULL}
272 };
273 
274 
275 /* SDCP - to be supported */
276 
277 /* IPCP Config Options */
278 #define IPCPOPT_2ADDR	1	/* RFC1172, RFC1332 (deprecated) */
279 #define IPCPOPT_IPCOMP	2	/* RFC1332 */
280 #define IPCPOPT_ADDR	3	/* RFC1332 */
281 #define IPCPOPT_MOBILE4	4	/* RFC2290 */
282 #define IPCPOPT_PRIDNS	129	/* RFC1877 */
283 #define IPCPOPT_PRINBNS	130	/* RFC1877 */
284 #define IPCPOPT_SECDNS	131	/* RFC1877 */
285 #define IPCPOPT_SECNBNS	132	/* RFC1877 */
286 
287 static const struct tok ipcpopt_values[] = {
288         { IPCPOPT_2ADDR, "IP-Addrs" },
289         { IPCPOPT_IPCOMP, "IP-Comp" },
290         { IPCPOPT_ADDR, "IP-Addr" },
291         { IPCPOPT_MOBILE4, "Home-Addr" },
292         { IPCPOPT_PRIDNS, "Pri-DNS" },
293         { IPCPOPT_PRINBNS, "Pri-NBNS" },
294         { IPCPOPT_SECDNS, "Sec-DNS" },
295         { IPCPOPT_SECNBNS, "Sec-NBNS" },
296 	{ 0,		  NULL }
297 };
298 
299 #define IPCPOPT_IPCOMP_HDRCOMP 0x61  /* rfc3544 */
300 #define IPCPOPT_IPCOMP_MINLEN    14
301 
302 static const struct tok ipcpopt_compproto_values[] = {
303         { PPP_VJC, "VJ-Comp" },
304         { IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" },
305 	{ 0,		  NULL }
306 };
307 
308 static const struct tok ipcpopt_compproto_subopt_values[] = {
309         { 1, "RTP-Compression" },
310         { 2, "Enhanced RTP-Compression" },
311 	{ 0,		  NULL }
312 };
313 
314 /* IP6CP Config Options */
315 #define IP6CP_IFID      1
316 
317 static const struct tok ip6cpopt_values[] = {
318         { IP6CP_IFID, "Interface-ID" },
319 	{ 0,		  NULL }
320 };
321 
322 /* ATCP - to be supported */
323 /* OSINLCP - to be supported */
324 /* BVCP - to be supported */
325 /* BCP - to be supported */
326 /* IPXCP - to be supported */
327 /* MPLSCP - to be supported */
328 
329 /* Auth Algorithms */
330 
331 /* 0-4 Reserved (RFC1994) */
332 #define AUTHALG_CHAPMD5	5	/* RFC1994 */
333 #define AUTHALG_MSCHAP1	128	/* RFC2433 */
334 #define AUTHALG_MSCHAP2	129	/* RFC2795 */
335 
336 static const struct tok authalg_values[] = {
337         { AUTHALG_CHAPMD5, "MD5" },
338         { AUTHALG_MSCHAP1, "MS-CHAPv1" },
339         { AUTHALG_MSCHAP2, "MS-CHAPv2" },
340 	{ 0,		  NULL }
341 };
342 
343 /* FCS Alternatives - to be supported */
344 
345 /* Multilink Endpoint Discriminator (RFC1717) */
346 #define MEDCLASS_NULL	0	/* Null Class */
347 #define MEDCLASS_LOCAL	1	/* Locally Assigned */
348 #define MEDCLASS_IPV4	2	/* Internet Protocol (IPv4) */
349 #define MEDCLASS_MAC	3	/* IEEE 802.1 global MAC address */
350 #define MEDCLASS_MNB	4	/* PPP Magic Number Block */
351 #define MEDCLASS_PSNDN	5	/* Public Switched Network Director Number */
352 
353 /* PPP LCP Callback */
354 #define CALLBACK_AUTH	0	/* Location determined by user auth */
355 #define CALLBACK_DSTR	1	/* Dialing string */
356 #define CALLBACK_LID	2	/* Location identifier */
357 #define CALLBACK_E164	3	/* E.164 number */
358 #define CALLBACK_X500	4	/* X.500 distinguished name */
359 #define CALLBACK_CBCP	6	/* Location is determined during CBCP nego */
360 
361 static const struct tok ppp_callback_values[] = {
362         { CALLBACK_AUTH, "UserAuth" },
363         { CALLBACK_DSTR, "DialString" },
364         { CALLBACK_LID, "LocalID" },
365         { CALLBACK_E164, "E.164" },
366         { CALLBACK_X500, "X.500" },
367         { CALLBACK_CBCP, "CBCP" },
368 	{ 0,		  NULL }
369 };
370 
371 /* CHAP */
372 
373 #define CHAP_CHAL	1
374 #define CHAP_RESP	2
375 #define CHAP_SUCC	3
376 #define CHAP_FAIL	4
377 
378 static const struct tok chapcode_values[] = {
379 	{ CHAP_CHAL, "Challenge" },
380 	{ CHAP_RESP, "Response" },
381 	{ CHAP_SUCC, "Success" },
382 	{ CHAP_FAIL, "Fail" },
383         { 0, NULL}
384 };
385 
386 /* PAP */
387 
388 #define PAP_AREQ	1
389 #define PAP_AACK	2
390 #define PAP_ANAK	3
391 
392 static const struct tok papcode_values[] = {
393         { PAP_AREQ, "Auth-Req" },
394         { PAP_AACK, "Auth-ACK" },
395         { PAP_ANAK, "Auth-NACK" },
396         { 0, NULL }
397 };
398 
399 /* BAP */
400 #define BAP_CALLREQ	1
401 #define BAP_CALLRES	2
402 #define BAP_CBREQ	3
403 #define BAP_CBRES	4
404 #define BAP_LDQREQ	5
405 #define BAP_LDQRES	6
406 #define BAP_CSIND	7
407 #define BAP_CSRES	8
408 
409 static int print_lcp_config_options(netdissect_options *, const u_char *p, int);
410 static int print_ipcp_config_options(netdissect_options *, const u_char *p, int);
411 static int print_ip6cp_config_options(netdissect_options *, const u_char *p, int);
412 static int print_ccp_config_options(netdissect_options *, const u_char *p, int);
413 static int print_bacp_config_options(netdissect_options *, const u_char *p, int);
414 static void handle_ppp(netdissect_options *, u_int proto, const u_char *p, int length);
415 
416 /* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
417 static void
handle_ctrl_proto(netdissect_options * ndo,u_int proto,const u_char * pptr,int length)418 handle_ctrl_proto(netdissect_options *ndo,
419                   u_int proto, const u_char *pptr, int length)
420 {
421 	const char *typestr;
422 	u_int code, len;
423 	int (*pfunc)(netdissect_options *, const u_char *, int);
424 	int x, j;
425         const u_char *tptr;
426 
427         tptr=pptr;
428 
429         typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto);
430 	ND_PRINT((ndo, "%s, ", typestr));
431 
432 	if (length < 4) /* FIXME weak boundary checking */
433 		goto trunc;
434 	ND_TCHECK2(*tptr, 2);
435 
436 	code = *tptr++;
437 
438 	ND_PRINT((ndo, "%s (0x%02x), id %u, length %u",
439 	          tok2str(cpcodes, "Unknown Opcode",code),
440 	          code,
441 	          *tptr++, /* ID */
442 	          length + 2));
443 
444 	if (!ndo->ndo_vflag)
445 		return;
446 
447 	if (length <= 4)
448 		return;    /* there may be a NULL confreq etc. */
449 
450 	ND_TCHECK2(*tptr, 2);
451 	len = EXTRACT_16BITS(tptr);
452 	tptr += 2;
453 
454 	ND_PRINT((ndo, "\n\tencoded length %u (=Option(s) length %u)", len, len - 4));
455 
456 	if (ndo->ndo_vflag > 1)
457 		print_unknown_data(ndo, pptr - 2, "\n\t", 6);
458 
459 
460 	switch (code) {
461 	case CPCODES_VEXT:
462 		if (length < 11)
463 			break;
464 		ND_TCHECK2(*tptr, 4);
465 		ND_PRINT((ndo, "\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr)));
466 		tptr += 4;
467 		ND_TCHECK2(*tptr, 3);
468 		ND_PRINT((ndo, " Vendor: %s (%u)",
469                        tok2str(oui_values,"Unknown",EXTRACT_24BITS(tptr)),
470                        EXTRACT_24BITS(tptr)));
471 		/* XXX: need to decode Kind and Value(s)? */
472 		break;
473 	case CPCODES_CONF_REQ:
474 	case CPCODES_CONF_ACK:
475 	case CPCODES_CONF_NAK:
476 	case CPCODES_CONF_REJ:
477 		x = len - 4;	/* Code(1), Identifier(1) and Length(2) */
478 		do {
479 			switch (proto) {
480 			case PPP_LCP:
481 				pfunc = print_lcp_config_options;
482 				break;
483 			case PPP_IPCP:
484 				pfunc = print_ipcp_config_options;
485 				break;
486 			case PPP_IPV6CP:
487 				pfunc = print_ip6cp_config_options;
488 				break;
489 			case PPP_CCP:
490 				pfunc = print_ccp_config_options;
491 				break;
492 			case PPP_BACP:
493 				pfunc = print_bacp_config_options;
494 				break;
495 			default:
496 				/*
497 				 * No print routine for the options for
498 				 * this protocol.
499 				 */
500 				pfunc = NULL;
501 				break;
502 			}
503 
504 			if (pfunc == NULL) /* catch the above null pointer if unknown CP */
505 				break;
506 
507 			if ((j = (*pfunc)(ndo, tptr, len)) == 0)
508 				break;
509 			x -= j;
510 			tptr += j;
511 		} while (x > 0);
512 		break;
513 
514 	case CPCODES_TERM_REQ:
515 	case CPCODES_TERM_ACK:
516 		/* XXX: need to decode Data? */
517 		break;
518 	case CPCODES_CODE_REJ:
519 		/* XXX: need to decode Rejected-Packet? */
520 		break;
521 	case CPCODES_PROT_REJ:
522 		if (length < 6)
523 			break;
524 		ND_TCHECK2(*tptr, 2);
525 		ND_PRINT((ndo, "\n\t  Rejected %s Protocol (0x%04x)",
526 		       tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)),
527 		       EXTRACT_16BITS(tptr)));
528 		/* XXX: need to decode Rejected-Information? - hexdump for now */
529 		if (len > 6) {
530 			ND_PRINT((ndo, "\n\t  Rejected Packet"));
531 			print_unknown_data(ndo, tptr + 2, "\n\t    ", len - 2);
532 		}
533 		break;
534 	case CPCODES_ECHO_REQ:
535 	case CPCODES_ECHO_RPL:
536 	case CPCODES_DISC_REQ:
537 		if (length < 8)
538 			break;
539 		ND_TCHECK2(*tptr, 4);
540 		ND_PRINT((ndo, "\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr)));
541 		/* XXX: need to decode Data? - hexdump for now */
542 		if (len > 8) {
543 			ND_PRINT((ndo, "\n\t  -----trailing data-----"));
544 			ND_TCHECK2(tptr[4], len - 8);
545 			print_unknown_data(ndo, tptr + 4, "\n\t  ", len - 8);
546 		}
547 		break;
548 	case CPCODES_ID:
549 		if (length < 8)
550 			break;
551 		ND_TCHECK2(*tptr, 4);
552 		ND_PRINT((ndo, "\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr)));
553 		/* RFC 1661 says this is intended to be human readable */
554 		if (len > 8) {
555 			ND_PRINT((ndo, "\n\t  Message\n\t    "));
556 			if (fn_printn(ndo, tptr + 4, len - 4, ndo->ndo_snapend))
557 				goto trunc;
558 		}
559 		break;
560 	case CPCODES_TIME_REM:
561 		if (length < 12)
562 			break;
563 		ND_TCHECK2(*tptr, 4);
564 		ND_PRINT((ndo, "\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr)));
565 		ND_TCHECK2(*(tptr + 4), 4);
566 		ND_PRINT((ndo, ", Seconds-Remaining %us", EXTRACT_32BITS(tptr + 4)));
567 		/* XXX: need to decode Message? */
568 		break;
569 	default:
570 		/* XXX this is dirty but we do not get the
571 		 * original pointer passed to the begin
572 		 * the PPP packet */
573 		if (ndo->ndo_vflag <= 1)
574 			print_unknown_data(ndo, pptr - 2, "\n\t  ", length + 2);
575 		break;
576 	}
577 	return;
578 
579 trunc:
580 	ND_PRINT((ndo, "[|%s]", typestr));
581 }
582 
583 /* LCP config options */
584 static int
print_lcp_config_options(netdissect_options * ndo,const u_char * p,int length)585 print_lcp_config_options(netdissect_options *ndo,
586                          const u_char *p, int length)
587 {
588 	int len, opt;
589 
590 	if (length < 2)
591 		return 0;
592 	ND_TCHECK2(*p, 2);
593 	len = p[1];
594 	opt = p[0];
595 	if (length < len)
596 		return 0;
597 	if (len < 2) {
598 		if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
599 			ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
600 			          lcpconfopts[opt], opt, len));
601 		else
602 			ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt));
603 		return 0;
604 	}
605 	if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
606 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u", lcpconfopts[opt], opt, len));
607 	else {
608 		ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt));
609 		return len;
610 	}
611 
612 	switch (opt) {
613 	case LCPOPT_VEXT:
614 		if (len < 6) {
615 			ND_PRINT((ndo, " (length bogus, should be >= 6)"));
616 			return len;
617 		}
618 		ND_TCHECK2(*(p + 2), 3);
619 		ND_PRINT((ndo, ": Vendor: %s (%u)",
620 			tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)),
621 			EXTRACT_24BITS(p + 2)));
622 #if 0
623 		ND_TCHECK(p[5]);
624 		ND_PRINT((ndo, ", kind: 0x%02x", p[5]));
625 		ND_PRINT((ndo, ", Value: 0x"));
626 		for (i = 0; i < len - 6; i++) {
627 			ND_TCHECK(p[6 + i]);
628 			ND_PRINT((ndo, "%02x", p[6 + i]));
629 		}
630 #endif
631 		break;
632 	case LCPOPT_MRU:
633 		if (len != 4) {
634 			ND_PRINT((ndo, " (length bogus, should be = 4)"));
635 			return len;
636 		}
637 		ND_TCHECK2(*(p + 2), 2);
638 		ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2)));
639 		break;
640 	case LCPOPT_ACCM:
641 		if (len != 6) {
642 			ND_PRINT((ndo, " (length bogus, should be = 6)"));
643 			return len;
644 		}
645 		ND_TCHECK2(*(p + 2), 4);
646 		ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2)));
647 		break;
648 	case LCPOPT_AP:
649 		if (len < 4) {
650 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
651 			return len;
652 		}
653 		ND_TCHECK2(*(p + 2), 2);
654 		ND_PRINT((ndo, ": %s", tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", EXTRACT_16BITS(p + 2))));
655 
656 		switch (EXTRACT_16BITS(p+2)) {
657 		case PPP_CHAP:
658 			ND_TCHECK(p[4]);
659 			ND_PRINT((ndo, ", %s", tok2str(authalg_values, "Unknown Auth Alg %u", p[4])));
660 			break;
661 		case PPP_PAP: /* fall through */
662 		case PPP_EAP:
663 		case PPP_SPAP:
664 		case PPP_SPAP_OLD:
665                         break;
666 		default:
667 			print_unknown_data(ndo, p, "\n\t", len);
668 		}
669 		break;
670 	case LCPOPT_QP:
671 		if (len < 4) {
672 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
673 			return 0;
674 		}
675 		ND_TCHECK2(*(p + 2), 2);
676 		if (EXTRACT_16BITS(p+2) == PPP_LQM)
677 			ND_PRINT((ndo, ": LQR"));
678 		else
679 			ND_PRINT((ndo, ": unknown"));
680 		break;
681 	case LCPOPT_MN:
682 		if (len != 6) {
683 			ND_PRINT((ndo, " (length bogus, should be = 6)"));
684 			return 0;
685 		}
686 		ND_TCHECK2(*(p + 2), 4);
687 		ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2)));
688 		break;
689 	case LCPOPT_PFC:
690 		break;
691 	case LCPOPT_ACFC:
692 		break;
693 	case LCPOPT_LD:
694 		if (len != 4) {
695 			ND_PRINT((ndo, " (length bogus, should be = 4)"));
696 			return 0;
697 		}
698 		ND_TCHECK2(*(p + 2), 2);
699 		ND_PRINT((ndo, ": 0x%04x", EXTRACT_16BITS(p + 2)));
700 		break;
701 	case LCPOPT_CBACK:
702 		if (len < 3) {
703 			ND_PRINT((ndo, " (length bogus, should be >= 3)"));
704 			return 0;
705 		}
706 		ND_PRINT((ndo, ": "));
707 		ND_TCHECK(p[2]);
708 		ND_PRINT((ndo, ": Callback Operation %s (%u)",
709                        tok2str(ppp_callback_values, "Unknown", p[2]),
710                        p[2]));
711 		break;
712 	case LCPOPT_MLMRRU:
713 		if (len != 4) {
714 			ND_PRINT((ndo, " (length bogus, should be = 4)"));
715 			return 0;
716 		}
717 		ND_TCHECK2(*(p + 2), 2);
718 		ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2)));
719 		break;
720 	case LCPOPT_MLED:
721 		if (len < 3) {
722 			ND_PRINT((ndo, " (length bogus, should be >= 3)"));
723 			return 0;
724 		}
725 		ND_TCHECK(p[2]);
726 		switch (p[2]) {		/* class */
727 		case MEDCLASS_NULL:
728 			ND_PRINT((ndo, ": Null"));
729 			break;
730 		case MEDCLASS_LOCAL:
731 			ND_PRINT((ndo, ": Local")); /* XXX */
732 			break;
733 		case MEDCLASS_IPV4:
734 			if (len != 7) {
735 				ND_PRINT((ndo, " (length bogus, should be = 7)"));
736 				return 0;
737 			}
738 			ND_TCHECK2(*(p + 3), 4);
739 			ND_PRINT((ndo, ": IPv4 %s", ipaddr_string(ndo, p + 3)));
740 			break;
741 		case MEDCLASS_MAC:
742 			if (len != 9) {
743 				ND_PRINT((ndo, " (length bogus, should be = 9)"));
744 				return 0;
745 			}
746 			ND_TCHECK2(*(p + 3), 6);
747 			ND_PRINT((ndo, ": MAC %s", etheraddr_string(ndo, p + 3)));
748 			break;
749 		case MEDCLASS_MNB:
750 			ND_PRINT((ndo, ": Magic-Num-Block")); /* XXX */
751 			break;
752 		case MEDCLASS_PSNDN:
753 			ND_PRINT((ndo, ": PSNDN")); /* XXX */
754 			break;
755 		default:
756 			ND_PRINT((ndo, ": Unknown class %u", p[2]));
757 			break;
758 		}
759 		break;
760 
761 /* XXX: to be supported */
762 #if 0
763 	case LCPOPT_DEP6:
764 	case LCPOPT_FCSALT:
765 	case LCPOPT_SDP:
766 	case LCPOPT_NUMMODE:
767 	case LCPOPT_DEP12:
768 	case LCPOPT_DEP14:
769 	case LCPOPT_DEP15:
770 	case LCPOPT_DEP16:
771         case LCPOPT_MLSSNHF:
772 	case LCPOPT_PROP:
773 	case LCPOPT_DCEID:
774 	case LCPOPT_MPP:
775 	case LCPOPT_LCPAOPT:
776 	case LCPOPT_COBS:
777 	case LCPOPT_PE:
778 	case LCPOPT_MLHF:
779 	case LCPOPT_I18N:
780 	case LCPOPT_SDLOS:
781 	case LCPOPT_PPPMUX:
782 		break;
783 #endif
784 	default:
785 		/*
786 		 * Unknown option; dump it as raw bytes now if we're
787 		 * not going to do so below.
788 		 */
789 		if (ndo->ndo_vflag < 2)
790 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
791 		break;
792 	}
793 
794 	if (ndo->ndo_vflag > 1)
795 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
796 
797 	return len;
798 
799 trunc:
800 	ND_PRINT((ndo, "[|lcp]"));
801 	return 0;
802 }
803 
804 /* ML-PPP*/
805 static const struct tok ppp_ml_flag_values[] = {
806     { 0x80, "begin" },
807     { 0x40, "end" },
808     { 0, NULL }
809 };
810 
811 static void
handle_mlppp(netdissect_options * ndo,const u_char * p,int length)812 handle_mlppp(netdissect_options *ndo,
813              const u_char *p, int length)
814 {
815     if (!ndo->ndo_eflag)
816         ND_PRINT((ndo, "MLPPP, "));
817 
818     ND_PRINT((ndo, "seq 0x%03x, Flags [%s], length %u",
819            (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */
820            bittok2str(ppp_ml_flag_values, "none", *p & 0xc0),
821            length));
822 }
823 
824 /* CHAP */
825 static void
handle_chap(netdissect_options * ndo,const u_char * p,int length)826 handle_chap(netdissect_options *ndo,
827             const u_char *p, int length)
828 {
829 	u_int code, len;
830 	int val_size, name_size, msg_size;
831 	const u_char *p0;
832 	int i;
833 
834 	p0 = p;
835 	if (length < 1) {
836 		ND_PRINT((ndo, "[|chap]"));
837 		return;
838 	} else if (length < 4) {
839 		ND_TCHECK(*p);
840 		ND_PRINT((ndo, "[|chap 0x%02x]", *p));
841 		return;
842 	}
843 
844 	ND_TCHECK(*p);
845 	code = *p;
846 	ND_PRINT((ndo, "CHAP, %s (0x%02x)",
847                tok2str(chapcode_values,"unknown",code),
848                code));
849 	p++;
850 
851 	ND_TCHECK(*p);
852 	ND_PRINT((ndo, ", id %u", *p));		/* ID */
853 	p++;
854 
855 	ND_TCHECK2(*p, 2);
856 	len = EXTRACT_16BITS(p);
857 	p += 2;
858 
859 	/*
860 	 * Note that this is a generic CHAP decoding routine. Since we
861 	 * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
862 	 * MS-CHAPv2) is used at this point, we can't decode packet
863 	 * specifically to each algorithms. Instead, we simply decode
864 	 * the GCD (Gratest Common Denominator) for all algorithms.
865 	 */
866 	switch (code) {
867 	case CHAP_CHAL:
868 	case CHAP_RESP:
869 		if (length - (p - p0) < 1)
870 			return;
871 		ND_TCHECK(*p);
872 		val_size = *p;		/* value size */
873 		p++;
874 		if (length - (p - p0) < val_size)
875 			return;
876 		ND_PRINT((ndo, ", Value "));
877 		for (i = 0; i < val_size; i++) {
878 			ND_TCHECK(*p);
879 			ND_PRINT((ndo, "%02x", *p++));
880 		}
881 		name_size = len - (p - p0);
882 		ND_PRINT((ndo, ", Name "));
883 		for (i = 0; i < name_size; i++) {
884 			ND_TCHECK(*p);
885 			safeputchar(ndo, *p++);
886 		}
887 		break;
888 	case CHAP_SUCC:
889 	case CHAP_FAIL:
890 		msg_size = len - (p - p0);
891 		ND_PRINT((ndo, ", Msg "));
892 		for (i = 0; i< msg_size; i++) {
893 			ND_TCHECK(*p);
894 			safeputchar(ndo, *p++);
895 		}
896 		break;
897 	}
898 	return;
899 
900 trunc:
901 	ND_PRINT((ndo, "[|chap]"));
902 }
903 
904 /* PAP (see RFC 1334) */
905 static void
handle_pap(netdissect_options * ndo,const u_char * p,int length)906 handle_pap(netdissect_options *ndo,
907            const u_char *p, int length)
908 {
909 	u_int code, len;
910 	int peerid_len, passwd_len, msg_len;
911 	const u_char *p0;
912 	int i;
913 
914 	p0 = p;
915 	if (length < 1) {
916 		ND_PRINT((ndo, "[|pap]"));
917 		return;
918 	} else if (length < 4) {
919 		ND_TCHECK(*p);
920 		ND_PRINT((ndo, "[|pap 0x%02x]", *p));
921 		return;
922 	}
923 
924 	ND_TCHECK(*p);
925 	code = *p;
926 	ND_PRINT((ndo, "PAP, %s (0x%02x)",
927 	          tok2str(papcode_values, "unknown", code),
928 	          code));
929 	p++;
930 
931 	ND_TCHECK(*p);
932 	ND_PRINT((ndo, ", id %u", *p));		/* ID */
933 	p++;
934 
935 	ND_TCHECK2(*p, 2);
936 	len = EXTRACT_16BITS(p);
937 	p += 2;
938 
939 	if ((int)len > length) {
940 		ND_PRINT((ndo, ", length %u > packet size", len));
941 		return;
942 	}
943 	length = len;
944 	if (length < (p - p0)) {
945 		ND_PRINT((ndo, ", length %u < PAP header length", length));
946 		return;
947 	}
948 
949 	switch (code) {
950 	case PAP_AREQ:
951 		if (length - (p - p0) < 1)
952 			return;
953 		ND_TCHECK(*p);
954 		peerid_len = *p;	/* Peer-ID Length */
955 		p++;
956 		if (length - (p - p0) < peerid_len)
957 			return;
958 		ND_PRINT((ndo, ", Peer "));
959 		for (i = 0; i < peerid_len; i++) {
960 			ND_TCHECK(*p);
961 			safeputchar(ndo, *p++);
962 		}
963 
964 		if (length - (p - p0) < 1)
965 			return;
966 		ND_TCHECK(*p);
967 		passwd_len = *p;	/* Password Length */
968 		p++;
969 		if (length - (p - p0) < passwd_len)
970 			return;
971 		ND_PRINT((ndo, ", Name "));
972 		for (i = 0; i < passwd_len; i++) {
973 			ND_TCHECK(*p);
974 			safeputchar(ndo, *p++);
975 		}
976 		break;
977 	case PAP_AACK:
978 	case PAP_ANAK:
979 		if (length - (p - p0) < 1)
980 			return;
981 		ND_TCHECK(*p);
982 		msg_len = *p;		/* Msg-Length */
983 		p++;
984 		if (length - (p - p0) < msg_len)
985 			return;
986 		ND_PRINT((ndo, ", Msg "));
987 		for (i = 0; i< msg_len; i++) {
988 			ND_TCHECK(*p);
989 			safeputchar(ndo, *p++);
990 		}
991 		break;
992 	}
993 	return;
994 
995 trunc:
996 	ND_PRINT((ndo, "[|pap]"));
997 }
998 
999 /* BAP */
1000 static void
handle_bap(netdissect_options * ndo _U_,const u_char * p _U_,int length _U_)1001 handle_bap(netdissect_options *ndo _U_,
1002            const u_char *p _U_, int length _U_)
1003 {
1004 	/* XXX: to be supported!! */
1005 }
1006 
1007 
1008 /* IPCP config options */
1009 static int
print_ipcp_config_options(netdissect_options * ndo,const u_char * p,int length)1010 print_ipcp_config_options(netdissect_options *ndo,
1011                           const u_char *p, int length)
1012 {
1013 	int len, opt;
1014         u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen;
1015 
1016 	if (length < 2)
1017 		return 0;
1018 	ND_TCHECK2(*p, 2);
1019 	len = p[1];
1020 	opt = p[0];
1021 	if (length < len)
1022 		return 0;
1023 	if (len < 2) {
1024 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
1025 		       tok2str(ipcpopt_values,"unknown",opt),
1026 		       opt,
1027 		       len));
1028 		return 0;
1029 	}
1030 
1031 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
1032 	       tok2str(ipcpopt_values,"unknown",opt),
1033 	       opt,
1034 	       len));
1035 
1036 	switch (opt) {
1037 	case IPCPOPT_2ADDR:		/* deprecated */
1038 		if (len != 10) {
1039 			ND_PRINT((ndo, " (length bogus, should be = 10)"));
1040 			return len;
1041 		}
1042 		ND_TCHECK2(*(p + 6), 4);
1043 		ND_PRINT((ndo, ": src %s, dst %s",
1044 		       ipaddr_string(ndo, p + 2),
1045 		       ipaddr_string(ndo, p + 6)));
1046 		break;
1047 	case IPCPOPT_IPCOMP:
1048 		if (len < 4) {
1049 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
1050 			return 0;
1051 		}
1052 		ND_TCHECK2(*(p + 2), 2);
1053 		compproto = EXTRACT_16BITS(p+2);
1054 
1055 		ND_PRINT((ndo, ": %s (0x%02x):",
1056 		          tok2str(ipcpopt_compproto_values, "Unknown", compproto),
1057 		          compproto));
1058 
1059 		switch (compproto) {
1060                 case PPP_VJC:
1061 			/* XXX: VJ-Comp parameters should be decoded */
1062                         break;
1063                 case IPCPOPT_IPCOMP_HDRCOMP:
1064                         if (len < IPCPOPT_IPCOMP_MINLEN) {
1065                         	ND_PRINT((ndo, " (length bogus, should be >= %u)",
1066                         		IPCPOPT_IPCOMP_MINLEN));
1067                         	return 0;
1068                         }
1069 
1070                         ND_TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN);
1071                         ND_PRINT((ndo, "\n\t    TCP Space %u, non-TCP Space %u" \
1072                                ", maxPeriod %u, maxTime %u, maxHdr %u",
1073                                EXTRACT_16BITS(p+4),
1074                                EXTRACT_16BITS(p+6),
1075                                EXTRACT_16BITS(p+8),
1076                                EXTRACT_16BITS(p+10),
1077                                EXTRACT_16BITS(p+12)));
1078 
1079                         /* suboptions present ? */
1080                         if (len > IPCPOPT_IPCOMP_MINLEN) {
1081                                 ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN;
1082                                 p += IPCPOPT_IPCOMP_MINLEN;
1083 
1084                                 ND_PRINT((ndo, "\n\t      Suboptions, length %u", ipcomp_subopttotallen));
1085 
1086                                 while (ipcomp_subopttotallen >= 2) {
1087                                         ND_TCHECK2(*p, 2);
1088                                         ipcomp_subopt = *p;
1089                                         ipcomp_suboptlen = *(p+1);
1090 
1091                                         /* sanity check */
1092                                         if (ipcomp_subopt == 0 ||
1093                                             ipcomp_suboptlen == 0 )
1094                                                 break;
1095 
1096                                         /* XXX: just display the suboptions for now */
1097                                         ND_PRINT((ndo, "\n\t\t%s Suboption #%u, length %u",
1098                                                tok2str(ipcpopt_compproto_subopt_values,
1099                                                        "Unknown",
1100                                                        ipcomp_subopt),
1101                                                ipcomp_subopt,
1102                                                ipcomp_suboptlen));
1103 
1104                                         ipcomp_subopttotallen -= ipcomp_suboptlen;
1105                                         p += ipcomp_suboptlen;
1106                                 }
1107                         }
1108                         break;
1109                 default:
1110                         break;
1111 		}
1112 		break;
1113 
1114 	case IPCPOPT_ADDR:     /* those options share the same format - fall through */
1115 	case IPCPOPT_MOBILE4:
1116 	case IPCPOPT_PRIDNS:
1117 	case IPCPOPT_PRINBNS:
1118 	case IPCPOPT_SECDNS:
1119 	case IPCPOPT_SECNBNS:
1120 		if (len != 6) {
1121 			ND_PRINT((ndo, " (length bogus, should be = 6)"));
1122 			return 0;
1123 		}
1124 		ND_TCHECK2(*(p + 2), 4);
1125 		ND_PRINT((ndo, ": %s", ipaddr_string(ndo, p + 2)));
1126 		break;
1127 	default:
1128 		/*
1129 		 * Unknown option; dump it as raw bytes now if we're
1130 		 * not going to do so below.
1131 		 */
1132 		if (ndo->ndo_vflag < 2)
1133 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
1134 		break;
1135 	}
1136 	if (ndo->ndo_vflag > 1)
1137 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
1138 	return len;
1139 
1140 trunc:
1141 	ND_PRINT((ndo, "[|ipcp]"));
1142 	return 0;
1143 }
1144 
1145 /* IP6CP config options */
1146 static int
print_ip6cp_config_options(netdissect_options * ndo,const u_char * p,int length)1147 print_ip6cp_config_options(netdissect_options *ndo,
1148                            const u_char *p, int length)
1149 {
1150 	int len, opt;
1151 
1152 	if (length < 2)
1153 		return 0;
1154 	ND_TCHECK2(*p, 2);
1155 	len = p[1];
1156 	opt = p[0];
1157 	if (length < len)
1158 		return 0;
1159 	if (len < 2) {
1160 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
1161 		       tok2str(ip6cpopt_values,"unknown",opt),
1162 		       opt,
1163 		       len));
1164 		return 0;
1165 	}
1166 
1167 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
1168 	       tok2str(ip6cpopt_values,"unknown",opt),
1169 	       opt,
1170 	       len));
1171 
1172 	switch (opt) {
1173 	case IP6CP_IFID:
1174 		if (len != 10) {
1175 			ND_PRINT((ndo, " (length bogus, should be = 10)"));
1176 			return len;
1177 		}
1178 		ND_TCHECK2(*(p + 2), 8);
1179 		ND_PRINT((ndo, ": %04x:%04x:%04x:%04x",
1180 		       EXTRACT_16BITS(p + 2),
1181 		       EXTRACT_16BITS(p + 4),
1182 		       EXTRACT_16BITS(p + 6),
1183 		       EXTRACT_16BITS(p + 8)));
1184 		break;
1185 	default:
1186 		/*
1187 		 * Unknown option; dump it as raw bytes now if we're
1188 		 * not going to do so below.
1189 		 */
1190 		if (ndo->ndo_vflag < 2)
1191 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
1192 		break;
1193 	}
1194 	if (ndo->ndo_vflag > 1)
1195 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
1196 
1197 	return len;
1198 
1199 trunc:
1200 	ND_PRINT((ndo, "[|ip6cp]"));
1201 	return 0;
1202 }
1203 
1204 
1205 /* CCP config options */
1206 static int
print_ccp_config_options(netdissect_options * ndo,const u_char * p,int length)1207 print_ccp_config_options(netdissect_options *ndo,
1208                          const u_char *p, int length)
1209 {
1210 	int len, opt;
1211 
1212 	if (length < 2)
1213 		return 0;
1214 	ND_TCHECK2(*p, 2);
1215 	len = p[1];
1216 	opt = p[0];
1217 	if (length < len)
1218 		return 0;
1219 	if (len < 2) {
1220 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
1221 		          tok2str(ccpconfopts_values, "Unknown", opt),
1222 		          opt,
1223 		          len));
1224 		return 0;
1225 	}
1226 
1227 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
1228 	          tok2str(ccpconfopts_values, "Unknown", opt),
1229 	          opt,
1230 	          len));
1231 
1232 	switch (opt) {
1233 	case CCPOPT_BSDCOMP:
1234 		if (len < 3) {
1235 			ND_PRINT((ndo, " (length bogus, should be >= 3)"));
1236 			return len;
1237 		}
1238 		ND_TCHECK2(*(p + 2), 1);
1239 		ND_PRINT((ndo, ": Version: %u, Dictionary Bits: %u",
1240 			p[2] >> 5, p[2] & 0x1f));
1241 		break;
1242 	case CCPOPT_MVRCA:
1243 		if (len < 4) {
1244 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
1245 			return len;
1246 		}
1247 		ND_TCHECK2(*(p + 2), 1);
1248 		ND_PRINT((ndo, ": Features: %u, PxP: %s, History: %u, #CTX-ID: %u",
1249 				(p[2] & 0xc0) >> 6,
1250 				(p[2] & 0x20) ? "Enabled" : "Disabled",
1251 				p[2] & 0x1f, p[3]));
1252 		break;
1253 	case CCPOPT_DEFLATE:
1254 		if (len < 4) {
1255 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
1256 			return len;
1257 		}
1258 		ND_TCHECK2(*(p + 2), 1);
1259 		ND_PRINT((ndo, ": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u",
1260 			(p[2] & 0xf0) >> 4,
1261 			((p[2] & 0x0f) == 8) ? "zlib" : "unkown",
1262 			p[2] & 0x0f, (p[3] & 0xfc) >> 2, p[3] & 0x03));
1263 		break;
1264 
1265 /* XXX: to be supported */
1266 #if 0
1267 	case CCPOPT_OUI:
1268 	case CCPOPT_PRED1:
1269 	case CCPOPT_PRED2:
1270 	case CCPOPT_PJUMP:
1271 	case CCPOPT_HPPPC:
1272 	case CCPOPT_STACLZS:
1273 	case CCPOPT_MPPC:
1274 	case CCPOPT_GFZA:
1275 	case CCPOPT_V42BIS:
1276 	case CCPOPT_LZSDCP:
1277 	case CCPOPT_DEC:
1278 	case CCPOPT_RESV:
1279 		break;
1280 #endif
1281 	default:
1282 		/*
1283 		 * Unknown option; dump it as raw bytes now if we're
1284 		 * not going to do so below.
1285 		 */
1286 		if (ndo->ndo_vflag < 2)
1287 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
1288 		break;
1289 	}
1290 	if (ndo->ndo_vflag > 1)
1291 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
1292 
1293 	return len;
1294 
1295 trunc:
1296 	ND_PRINT((ndo, "[|ccp]"));
1297 	return 0;
1298 }
1299 
1300 /* BACP config options */
1301 static int
print_bacp_config_options(netdissect_options * ndo,const u_char * p,int length)1302 print_bacp_config_options(netdissect_options *ndo,
1303                           const u_char *p, int length)
1304 {
1305 	int len, opt;
1306 
1307 	if (length < 2)
1308 		return 0;
1309 	ND_TCHECK2(*p, 2);
1310 	len = p[1];
1311 	opt = p[0];
1312 	if (length < len)
1313 		return 0;
1314 	if (len < 2) {
1315 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
1316 		          tok2str(bacconfopts_values, "Unknown", opt),
1317 		          opt,
1318 		          len));
1319 		return 0;
1320 	}
1321 
1322 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
1323 	          tok2str(bacconfopts_values, "Unknown", opt),
1324 	          opt,
1325 	          len));
1326 
1327 	switch (opt) {
1328 	case BACPOPT_FPEER:
1329 		if (len != 6) {
1330 			ND_PRINT((ndo, " (length bogus, should be = 6)"));
1331 			return len;
1332 		}
1333 		ND_TCHECK2(*(p + 2), 4);
1334 		ND_PRINT((ndo, ": Magic-Num 0x%08x", EXTRACT_32BITS(p + 2)));
1335 		break;
1336 	default:
1337 		/*
1338 		 * Unknown option; dump it as raw bytes now if we're
1339 		 * not going to do so below.
1340 		 */
1341 		if (ndo->ndo_vflag < 2)
1342 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
1343 		break;
1344 	}
1345 	if (ndo->ndo_vflag > 1)
1346 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
1347 
1348 	return len;
1349 
1350 trunc:
1351 	ND_PRINT((ndo, "[|bacp]"));
1352 	return 0;
1353 }
1354 
1355 static void
ppp_hdlc(netdissect_options * ndo,const u_char * p,int length)1356 ppp_hdlc(netdissect_options *ndo,
1357          const u_char *p, int length)
1358 {
1359 	u_char *b, *t, c;
1360 	const u_char *s;
1361 	int i, proto;
1362 	const void *se;
1363 
1364         if (length <= 0)
1365                 return;
1366 
1367 	b = (u_char *)malloc(length);
1368 	if (b == NULL)
1369 		return;
1370 
1371 	/*
1372 	 * Unescape all the data into a temporary, private, buffer.
1373 	 * Do this so that we dont overwrite the original packet
1374 	 * contents.
1375 	 */
1376 	for (s = p, t = b, i = length; i > 0 && ND_TTEST(*s); i--) {
1377 		c = *s++;
1378 		if (c == 0x7d) {
1379 			if (i <= 1 || !ND_TTEST(*s))
1380 				break;
1381 			i--;
1382 			c = *s++ ^ 0x20;
1383 		}
1384 		*t++ = c;
1385 	}
1386 
1387 	se = ndo->ndo_snapend;
1388 	ndo->ndo_snapend = t;
1389 	length = t - b;
1390 
1391         /* now lets guess about the payload codepoint format */
1392         if (length < 1)
1393                 goto trunc;
1394         proto = *b; /* start with a one-octet codepoint guess */
1395 
1396         switch (proto) {
1397         case PPP_IP:
1398 		ip_print(ndo, b + 1, length - 1);
1399 		goto cleanup;
1400         case PPP_IPV6:
1401 		ip6_print(ndo, b + 1, length - 1);
1402 		goto cleanup;
1403         default: /* no luck - try next guess */
1404 		break;
1405         }
1406 
1407         if (length < 2)
1408                 goto trunc;
1409         proto = EXTRACT_16BITS(b); /* next guess - load two octets */
1410 
1411         switch (proto) {
1412         case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */
1413             if (length < 4)
1414                 goto trunc;
1415             proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */
1416             handle_ppp(ndo, proto, b + 4, length - 4);
1417             break;
1418         default: /* last guess - proto must be a PPP proto-id */
1419             handle_ppp(ndo, proto, b + 2, length - 2);
1420             break;
1421         }
1422 
1423 cleanup:
1424 	ndo->ndo_snapend = se;
1425 	free(b);
1426         return;
1427 
1428 trunc:
1429 	ndo->ndo_snapend = se;
1430 	free(b);
1431 	ND_PRINT((ndo, "[|ppp]"));
1432 }
1433 
1434 
1435 /* PPP */
1436 static void
handle_ppp(netdissect_options * ndo,u_int proto,const u_char * p,int length)1437 handle_ppp(netdissect_options *ndo,
1438            u_int proto, const u_char *p, int length)
1439 {
1440 	if ((proto & 0xff00) == 0x7e00) { /* is this an escape code ? */
1441 		ppp_hdlc(ndo, p - 1, length);
1442 		return;
1443 	}
1444 
1445 	switch (proto) {
1446 	case PPP_LCP: /* fall through */
1447 	case PPP_IPCP:
1448 	case PPP_OSICP:
1449 	case PPP_MPLSCP:
1450 	case PPP_IPV6CP:
1451 	case PPP_CCP:
1452 	case PPP_BACP:
1453 		handle_ctrl_proto(ndo, proto, p, length);
1454 		break;
1455 	case PPP_ML:
1456 		handle_mlppp(ndo, p, length);
1457 		break;
1458 	case PPP_CHAP:
1459 		handle_chap(ndo, p, length);
1460 		break;
1461 	case PPP_PAP:
1462 		handle_pap(ndo, p, length);
1463 		break;
1464 	case PPP_BAP:		/* XXX: not yet completed */
1465 		handle_bap(ndo, p, length);
1466 		break;
1467 	case ETHERTYPE_IP:	/*XXX*/
1468         case PPP_VJNC:
1469 	case PPP_IP:
1470 		ip_print(ndo, p, length);
1471 		break;
1472 	case ETHERTYPE_IPV6:	/*XXX*/
1473 	case PPP_IPV6:
1474 		ip6_print(ndo, p, length);
1475 		break;
1476 	case ETHERTYPE_IPX:	/*XXX*/
1477 	case PPP_IPX:
1478 		ipx_print(ndo, p, length);
1479 		break;
1480 	case PPP_OSI:
1481 		isoclns_print(ndo, p, length, length);
1482 		break;
1483 	case PPP_MPLS_UCAST:
1484 	case PPP_MPLS_MCAST:
1485 		mpls_print(ndo, p, length);
1486 		break;
1487 	case PPP_COMP:
1488 		ND_PRINT((ndo, "compressed PPP data"));
1489 		break;
1490 	default:
1491 		ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto)));
1492 		print_unknown_data(ndo, p, "\n\t", length);
1493 		break;
1494 	}
1495 }
1496 
1497 /* Standard PPP printer */
1498 u_int
ppp_print(netdissect_options * ndo,register const u_char * p,u_int length)1499 ppp_print(netdissect_options *ndo,
1500           register const u_char *p, u_int length)
1501 {
1502 	u_int proto,ppp_header;
1503         u_int olen = length; /* _o_riginal length */
1504 	u_int hdr_len = 0;
1505 
1506 	/*
1507 	 * Here, we assume that p points to the Address and Control
1508 	 * field (if they present).
1509 	 */
1510 	if (length < 2)
1511 		goto trunc;
1512 	ND_TCHECK2(*p, 2);
1513         ppp_header = EXTRACT_16BITS(p);
1514 
1515         switch(ppp_header) {
1516         case (PPP_WITHDIRECTION_IN  << 8 | PPP_CONTROL):
1517             if (ndo->ndo_eflag) ND_PRINT((ndo, "In  "));
1518             p += 2;
1519             length -= 2;
1520             hdr_len += 2;
1521             break;
1522         case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL):
1523             if (ndo->ndo_eflag) ND_PRINT((ndo, "Out "));
1524             p += 2;
1525             length -= 2;
1526             hdr_len += 2;
1527             break;
1528         case (PPP_ADDRESS << 8 | PPP_CONTROL):
1529             p += 2;			/* ACFC not used */
1530             length -= 2;
1531             hdr_len += 2;
1532             break;
1533 
1534         default:
1535             break;
1536         }
1537 
1538 	if (length < 2)
1539 		goto trunc;
1540 	ND_TCHECK(*p);
1541 	if (*p % 2) {
1542 		proto = *p;		/* PFC is used */
1543 		p++;
1544 		length--;
1545 		hdr_len++;
1546 	} else {
1547 		ND_TCHECK2(*p, 2);
1548 		proto = EXTRACT_16BITS(p);
1549 		p += 2;
1550 		length -= 2;
1551 		hdr_len += 2;
1552 	}
1553 
1554 	if (ndo->ndo_eflag)
1555 		ND_PRINT((ndo, "%s (0x%04x), length %u: ",
1556 		          tok2str(ppptype2str, "unknown", proto),
1557 		          proto,
1558 		          olen));
1559 
1560 	handle_ppp(ndo, proto, p, length);
1561 	return (hdr_len);
1562 trunc:
1563 	ND_PRINT((ndo, "[|ppp]"));
1564 	return (0);
1565 }
1566 
1567 
1568 /* PPP I/F printer */
1569 u_int
ppp_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,register const u_char * p)1570 ppp_if_print(netdissect_options *ndo,
1571              const struct pcap_pkthdr *h, register const u_char *p)
1572 {
1573 	register u_int length = h->len;
1574 	register u_int caplen = h->caplen;
1575 
1576 	if (caplen < PPP_HDRLEN) {
1577 		ND_PRINT((ndo, "[|ppp]"));
1578 		return (caplen);
1579 	}
1580 
1581 #if 0
1582 	/*
1583 	 * XXX: seems to assume that there are 2 octets prepended to an
1584 	 * actual PPP frame. The 1st octet looks like Input/Output flag
1585 	 * while 2nd octet is unknown, at least to me
1586 	 * (mshindo@mshindo.net).
1587 	 *
1588 	 * That was what the original tcpdump code did.
1589 	 *
1590 	 * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
1591 	 * packets and 0 for inbound packets - but only if the
1592 	 * protocol field has the 0x8000 bit set (i.e., it's a network
1593 	 * control protocol); it does so before running the packet through
1594 	 * "bpf_filter" to see if it should be discarded, and to see
1595 	 * if we should update the time we sent the most recent packet...
1596 	 *
1597 	 * ...but it puts the original address field back after doing
1598 	 * so.
1599 	 *
1600 	 * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
1601 	 *
1602 	 * I don't know if any PPP implementation handed up to a BPF
1603 	 * device packets with the first octet being 1 for outbound and
1604 	 * 0 for inbound packets, so I (guy@alum.mit.edu) don't know
1605 	 * whether that ever needs to be checked or not.
1606 	 *
1607 	 * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
1608 	 * and its tcpdump appears to assume that the frame always
1609 	 * begins with an address field and a control field, and that
1610 	 * the address field might be 0x0f or 0x8f, for Cisco
1611 	 * point-to-point with HDLC framing as per section 4.3.1 of RFC
1612 	 * 1547, as well as 0xff, for PPP in HDLC-like framing as per
1613 	 * RFC 1662.
1614 	 *
1615 	 * (Is the Cisco framing in question what DLT_C_HDLC, in
1616 	 * BSD/OS, is?)
1617 	 */
1618 	if (ndo->ndo_eflag)
1619 		ND_PRINT((ndo, "%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]));
1620 #endif
1621 
1622 	ppp_print(ndo, p, length);
1623 
1624 	return (0);
1625 }
1626 
1627 /*
1628  * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
1629  * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
1630  * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
1631  * discard them *if* those are the first two octets, and parse the remaining
1632  * packet as a PPP packet, as "ppp_print()" does).
1633  *
1634  * This handles, for example, DLT_PPP_SERIAL in NetBSD.
1635  */
1636 u_int
ppp_hdlc_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,register const u_char * p)1637 ppp_hdlc_if_print(netdissect_options *ndo,
1638                   const struct pcap_pkthdr *h, register const u_char *p)
1639 {
1640 	register u_int length = h->len;
1641 	register u_int caplen = h->caplen;
1642 	u_int proto;
1643 	u_int hdrlen = 0;
1644 
1645 	if (caplen < 2) {
1646 		ND_PRINT((ndo, "[|ppp]"));
1647 		return (caplen);
1648 	}
1649 
1650 	switch (p[0]) {
1651 
1652 	case PPP_ADDRESS:
1653 		if (caplen < 4) {
1654 			ND_PRINT((ndo, "[|ppp]"));
1655 			return (caplen);
1656 		}
1657 
1658 		if (ndo->ndo_eflag)
1659 			ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length));
1660 		p += 2;
1661 		length -= 2;
1662 		hdrlen += 2;
1663 
1664 		proto = EXTRACT_16BITS(p);
1665 		p += 2;
1666 		length -= 2;
1667 		hdrlen += 2;
1668 		ND_PRINT((ndo, "%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto)));
1669 
1670 		handle_ppp(ndo, proto, p, length);
1671 		break;
1672 
1673 	case CHDLC_UNICAST:
1674 	case CHDLC_BCAST:
1675 		return (chdlc_if_print(ndo, h, p));
1676 
1677 	default:
1678 		if (ndo->ndo_eflag)
1679 			ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length));
1680 		p += 2;
1681 		hdrlen += 2;
1682 
1683 		/*
1684 		 * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
1685 		 * the next two octets as an Ethernet type; does that
1686 		 * ever happen?
1687 		 */
1688 		ND_PRINT((ndo, "unknown addr %02x; ctrl %02x", p[0], p[1]));
1689 		break;
1690 	}
1691 
1692 	return (hdrlen);
1693 }
1694 
1695 #define PPP_BSDI_HDRLEN 24
1696 
1697 /* BSD/OS specific PPP printer */
1698 u_int
ppp_bsdos_if_print(netdissect_options * ndo _U_,const struct pcap_pkthdr * h _U_,register const u_char * p _U_)1699 ppp_bsdos_if_print(netdissect_options *ndo _U_,
1700                    const struct pcap_pkthdr *h _U_, register const u_char *p _U_)
1701 {
1702 	register int hdrlength;
1703 #ifdef __bsdi__
1704 	register u_int length = h->len;
1705 	register u_int caplen = h->caplen;
1706 	uint16_t ptype;
1707 	const u_char *q;
1708 	int i;
1709 
1710 	if (caplen < PPP_BSDI_HDRLEN) {
1711 		ND_PRINT((ndo, "[|ppp]"));
1712 		return (caplen)
1713 	}
1714 
1715 	hdrlength = 0;
1716 
1717 #if 0
1718 	if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
1719 		if (ndo->ndo_eflag)
1720 			ND_PRINT((ndo, "%02x %02x ", p[0], p[1]));
1721 		p += 2;
1722 		hdrlength = 2;
1723 	}
1724 
1725 	if (ndo->ndo_eflag)
1726 		ND_PRINT((ndo, "%d ", length));
1727 	/* Retrieve the protocol type */
1728 	if (*p & 01) {
1729 		/* Compressed protocol field */
1730 		ptype = *p;
1731 		if (ndo->ndo_eflag)
1732 			ND_PRINT((ndo, "%02x ", ptype));
1733 		p++;
1734 		hdrlength += 1;
1735 	} else {
1736 		/* Un-compressed protocol field */
1737 		ptype = EXTRACT_16BITS(p);
1738 		if (ndo->ndo_eflag)
1739 			ND_PRINT((ndo, "%04x ", ptype));
1740 		p += 2;
1741 		hdrlength += 2;
1742 	}
1743 #else
1744 	ptype = 0;	/*XXX*/
1745 	if (ndo->ndo_eflag)
1746 		ND_PRINT((ndo, "%c ", p[SLC_DIR] ? 'O' : 'I'));
1747 	if (p[SLC_LLHL]) {
1748 		/* link level header */
1749 		struct ppp_header *ph;
1750 
1751 		q = p + SLC_BPFHDRLEN;
1752 		ph = (struct ppp_header *)q;
1753 		if (ph->phdr_addr == PPP_ADDRESS
1754 		 && ph->phdr_ctl == PPP_CONTROL) {
1755 			if (ndo->ndo_eflag)
1756 				ND_PRINT((ndo, "%02x %02x ", q[0], q[1]));
1757 			ptype = EXTRACT_16BITS(&ph->phdr_type);
1758 			if (ndo->ndo_eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
1759 				ND_PRINT((ndo, "%s ", tok2str(ppptype2str,
1760 						"proto-#%d", ptype)));
1761 			}
1762 		} else {
1763 			if (ndo->ndo_eflag) {
1764 				ND_PRINT((ndo, "LLH=["));
1765 				for (i = 0; i < p[SLC_LLHL]; i++)
1766 					ND_PRINT((ndo, "%02x", q[i]));
1767 				ND_PRINT((ndo, "] "));
1768 			}
1769 		}
1770 	}
1771 	if (ndo->ndo_eflag)
1772 		ND_PRINT((ndo, "%d ", length));
1773 	if (p[SLC_CHL]) {
1774 		q = p + SLC_BPFHDRLEN + p[SLC_LLHL];
1775 
1776 		switch (ptype) {
1777 		case PPP_VJC:
1778 			ptype = vjc_print(ndo, q, ptype);
1779 			hdrlength = PPP_BSDI_HDRLEN;
1780 			p += hdrlength;
1781 			switch (ptype) {
1782 			case PPP_IP:
1783 				ip_print(ndo, p, length);
1784 				break;
1785 			case PPP_IPV6:
1786 				ip6_print(ndo, p, length);
1787 				break;
1788 			case PPP_MPLS_UCAST:
1789 			case PPP_MPLS_MCAST:
1790 				mpls_print(ndo, p, length);
1791 				break;
1792 			}
1793 			goto printx;
1794 		case PPP_VJNC:
1795 			ptype = vjc_print(ndo, q, ptype);
1796 			hdrlength = PPP_BSDI_HDRLEN;
1797 			p += hdrlength;
1798 			switch (ptype) {
1799 			case PPP_IP:
1800 				ip_print(ndo, p, length);
1801 				break;
1802 			case PPP_IPV6:
1803 				ip6_print(ndo, p, length);
1804 				break;
1805 			case PPP_MPLS_UCAST:
1806 			case PPP_MPLS_MCAST:
1807 				mpls_print(ndo, p, length);
1808 				break;
1809 			}
1810 			goto printx;
1811 		default:
1812 			if (ndo->ndo_eflag) {
1813 				ND_PRINT((ndo, "CH=["));
1814 				for (i = 0; i < p[SLC_LLHL]; i++)
1815 					ND_PRINT((ndo, "%02x", q[i]));
1816 				ND_PRINT((ndo, "] "));
1817 			}
1818 			break;
1819 		}
1820 	}
1821 
1822 	hdrlength = PPP_BSDI_HDRLEN;
1823 #endif
1824 
1825 	length -= hdrlength;
1826 	p += hdrlength;
1827 
1828 	switch (ptype) {
1829 	case PPP_IP:
1830 		ip_print(p, length);
1831 		break;
1832 	case PPP_IPV6:
1833 		ip6_print(ndo, p, length);
1834 		break;
1835 	case PPP_MPLS_UCAST:
1836 	case PPP_MPLS_MCAST:
1837 		mpls_print(ndo, p, length);
1838 		break;
1839 	default:
1840 		ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype)));
1841 	}
1842 
1843 printx:
1844 #else /* __bsdi */
1845 	hdrlength = 0;
1846 #endif /* __bsdi__ */
1847 	return (hdrlength);
1848 }
1849 
1850 
1851 /*
1852  * Local Variables:
1853  * c-style: whitesmith
1854  * c-basic-offset: 8
1855  * End:
1856  */
1857