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