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