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_TCHECK2(*(p + 2), 3);
    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_TCHECK2(*(p + 2), 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_TCHECK2(*(p + 2), 4);
    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_TCHECK2(*(p + 2), 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_TCHECK2(*(p + 2), 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_TCHECK2(*(p + 2), 4);
    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_TCHECK2(*(p + 2), 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_TCHECK2(*(p + 2), 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     ND_PRINT((ndo, "seq 0x%03x, Flags [%s], length %u",
    815            (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */
    816            bittok2str(ppp_ml_flag_values, "none", *p & 0xc0),
    817            length));
    818 }
    819 
    820 /* CHAP */
    821 static void
    822 handle_chap(netdissect_options *ndo,
    823             const u_char *p, int length)
    824 {
    825 	u_int code, len;
    826 	int val_size, name_size, msg_size;
    827 	const u_char *p0;
    828 	int i;
    829 
    830 	p0 = p;
    831 	if (length < 1) {
    832 		ND_PRINT((ndo, "[|chap]"));
    833 		return;
    834 	} else if (length < 4) {
    835 		ND_TCHECK(*p);
    836 		ND_PRINT((ndo, "[|chap 0x%02x]", *p));
    837 		return;
    838 	}
    839 
    840 	ND_TCHECK(*p);
    841 	code = *p;
    842 	ND_PRINT((ndo, "CHAP, %s (0x%02x)",
    843                tok2str(chapcode_values,"unknown",code),
    844                code));
    845 	p++;
    846 
    847 	ND_TCHECK(*p);
    848 	ND_PRINT((ndo, ", id %u", *p));		/* ID */
    849 	p++;
    850 
    851 	ND_TCHECK2(*p, 2);
    852 	len = EXTRACT_16BITS(p);
    853 	p += 2;
    854 
    855 	/*
    856 	 * Note that this is a generic CHAP decoding routine. Since we
    857 	 * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
    858 	 * MS-CHAPv2) is used at this point, we can't decode packet
    859 	 * specifically to each algorithms. Instead, we simply decode
    860 	 * the GCD (Gratest Common Denominator) for all algorithms.
    861 	 */
    862 	switch (code) {
    863 	case CHAP_CHAL:
    864 	case CHAP_RESP:
    865 		if (length - (p - p0) < 1)
    866 			return;
    867 		ND_TCHECK(*p);
    868 		val_size = *p;		/* value size */
    869 		p++;
    870 		if (length - (p - p0) < val_size)
    871 			return;
    872 		ND_PRINT((ndo, ", Value "));
    873 		for (i = 0; i < val_size; i++) {
    874 			ND_TCHECK(*p);
    875 			ND_PRINT((ndo, "%02x", *p++));
    876 		}
    877 		name_size = len - (p - p0);
    878 		ND_PRINT((ndo, ", Name "));
    879 		for (i = 0; i < name_size; i++) {
    880 			ND_TCHECK(*p);
    881 			safeputchar(ndo, *p++);
    882 		}
    883 		break;
    884 	case CHAP_SUCC:
    885 	case CHAP_FAIL:
    886 		msg_size = len - (p - p0);
    887 		ND_PRINT((ndo, ", Msg "));
    888 		for (i = 0; i< msg_size; i++) {
    889 			ND_TCHECK(*p);
    890 			safeputchar(ndo, *p++);
    891 		}
    892 		break;
    893 	}
    894 	return;
    895 
    896 trunc:
    897 	ND_PRINT((ndo, "[|chap]"));
    898 }
    899 
    900 /* PAP (see RFC 1334) */
    901 static void
    902 handle_pap(netdissect_options *ndo,
    903            const u_char *p, int length)
    904 {
    905 	u_int code, len;
    906 	int peerid_len, passwd_len, msg_len;
    907 	const u_char *p0;
    908 	int i;
    909 
    910 	p0 = p;
    911 	if (length < 1) {
    912 		ND_PRINT((ndo, "[|pap]"));
    913 		return;
    914 	} else if (length < 4) {
    915 		ND_TCHECK(*p);
    916 		ND_PRINT((ndo, "[|pap 0x%02x]", *p));
    917 		return;
    918 	}
    919 
    920 	ND_TCHECK(*p);
    921 	code = *p;
    922 	ND_PRINT((ndo, "PAP, %s (0x%02x)",
    923 	          tok2str(papcode_values, "unknown", code),
    924 	          code));
    925 	p++;
    926 
    927 	ND_TCHECK(*p);
    928 	ND_PRINT((ndo, ", id %u", *p));		/* ID */
    929 	p++;
    930 
    931 	ND_TCHECK2(*p, 2);
    932 	len = EXTRACT_16BITS(p);
    933 	p += 2;
    934 
    935 	if ((int)len > length) {
    936 		ND_PRINT((ndo, ", length %u > packet size", len));
    937 		return;
    938 	}
    939 	length = len;
    940 	if (length < (p - p0)) {
    941 		ND_PRINT((ndo, ", length %u < PAP header length", length));
    942 		return;
    943 	}
    944 
    945 	switch (code) {
    946 	case PAP_AREQ:
    947 		/* A valid Authenticate-Request is 6 or more octets long. */
    948 		if (len < 6)
    949 			goto trunc;
    950 		if (length - (p - p0) < 1)
    951 			return;
    952 		ND_TCHECK(*p);
    953 		peerid_len = *p;	/* Peer-ID Length */
    954 		p++;
    955 		if (length - (p - p0) < peerid_len)
    956 			return;
    957 		ND_PRINT((ndo, ", Peer "));
    958 		for (i = 0; i < peerid_len; i++) {
    959 			ND_TCHECK(*p);
    960 			safeputchar(ndo, *p++);
    961 		}
    962 
    963 		if (length - (p - p0) < 1)
    964 			return;
    965 		ND_TCHECK(*p);
    966 		passwd_len = *p;	/* Password Length */
    967 		p++;
    968 		if (length - (p - p0) < passwd_len)
    969 			return;
    970 		ND_PRINT((ndo, ", Name "));
    971 		for (i = 0; i < passwd_len; i++) {
    972 			ND_TCHECK(*p);
    973 			safeputchar(ndo, *p++);
    974 		}
    975 		break;
    976 	case PAP_AACK:
    977 	case PAP_ANAK:
    978 		/* Although some implementations ignore truncation at
    979 		 * this point and at least one generates a truncated
    980 		 * packet, RFC 1334 section 2.2.2 clearly states that
    981 		 * both AACK and ANAK are at least 5 bytes long.
    982 		 */
    983 		if (len < 5)
    984 			goto trunc;
    985 		if (length - (p - p0) < 1)
    986 			return;
    987 		ND_TCHECK(*p);
    988 		msg_len = *p;		/* Msg-Length */
    989 		p++;
    990 		if (length - (p - p0) < msg_len)
    991 			return;
    992 		ND_PRINT((ndo, ", Msg "));
    993 		for (i = 0; i< msg_len; i++) {
    994 			ND_TCHECK(*p);
    995 			safeputchar(ndo, *p++);
    996 		}
    997 		break;
    998 	}
    999 	return;
   1000 
   1001 trunc:
   1002 	ND_PRINT((ndo, "[|pap]"));
   1003 }
   1004 
   1005 /* BAP */
   1006 static void
   1007 handle_bap(netdissect_options *ndo _U_,
   1008            const u_char *p _U_, int length _U_)
   1009 {
   1010 	/* XXX: to be supported!! */
   1011 }
   1012 
   1013 
   1014 /* IPCP config options */
   1015 static int
   1016 print_ipcp_config_options(netdissect_options *ndo,
   1017                           const u_char *p, int length)
   1018 {
   1019 	int len, opt;
   1020         u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen;
   1021 
   1022 	if (length < 2)
   1023 		return 0;
   1024 	ND_TCHECK2(*p, 2);
   1025 	len = p[1];
   1026 	opt = p[0];
   1027 	if (length < len)
   1028 		return 0;
   1029 	if (len < 2) {
   1030 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
   1031 		       tok2str(ipcpopt_values,"unknown",opt),
   1032 		       opt,
   1033 		       len));
   1034 		return 0;
   1035 	}
   1036 
   1037 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
   1038 	       tok2str(ipcpopt_values,"unknown",opt),
   1039 	       opt,
   1040 	       len));
   1041 
   1042 	switch (opt) {
   1043 	case IPCPOPT_2ADDR:		/* deprecated */
   1044 		if (len != 10) {
   1045 			ND_PRINT((ndo, " (length bogus, should be = 10)"));
   1046 			return len;
   1047 		}
   1048 		ND_TCHECK2(*(p + 6), 4);
   1049 		ND_PRINT((ndo, ": src %s, dst %s",
   1050 		       ipaddr_string(ndo, p + 2),
   1051 		       ipaddr_string(ndo, p + 6)));
   1052 		break;
   1053 	case IPCPOPT_IPCOMP:
   1054 		if (len < 4) {
   1055 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
   1056 			return 0;
   1057 		}
   1058 		ND_TCHECK2(*(p + 2), 2);
   1059 		compproto = EXTRACT_16BITS(p+2);
   1060 
   1061 		ND_PRINT((ndo, ": %s (0x%02x):",
   1062 		          tok2str(ipcpopt_compproto_values, "Unknown", compproto),
   1063 		          compproto));
   1064 
   1065 		switch (compproto) {
   1066                 case PPP_VJC:
   1067 			/* XXX: VJ-Comp parameters should be decoded */
   1068                         break;
   1069                 case IPCPOPT_IPCOMP_HDRCOMP:
   1070                         if (len < IPCPOPT_IPCOMP_MINLEN) {
   1071                         	ND_PRINT((ndo, " (length bogus, should be >= %u)",
   1072                         		IPCPOPT_IPCOMP_MINLEN));
   1073                         	return 0;
   1074                         }
   1075 
   1076                         ND_TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN);
   1077                         ND_PRINT((ndo, "\n\t    TCP Space %u, non-TCP Space %u" \
   1078                                ", maxPeriod %u, maxTime %u, maxHdr %u",
   1079                                EXTRACT_16BITS(p+4),
   1080                                EXTRACT_16BITS(p+6),
   1081                                EXTRACT_16BITS(p+8),
   1082                                EXTRACT_16BITS(p+10),
   1083                                EXTRACT_16BITS(p+12)));
   1084 
   1085                         /* suboptions present ? */
   1086                         if (len > IPCPOPT_IPCOMP_MINLEN) {
   1087                                 ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN;
   1088                                 p += IPCPOPT_IPCOMP_MINLEN;
   1089 
   1090                                 ND_PRINT((ndo, "\n\t      Suboptions, length %u", ipcomp_subopttotallen));
   1091 
   1092                                 while (ipcomp_subopttotallen >= 2) {
   1093                                         ND_TCHECK2(*p, 2);
   1094                                         ipcomp_subopt = *p;
   1095                                         ipcomp_suboptlen = *(p+1);
   1096 
   1097                                         /* sanity check */
   1098                                         if (ipcomp_subopt == 0 ||
   1099                                             ipcomp_suboptlen == 0 )
   1100                                                 break;
   1101 
   1102                                         /* XXX: just display the suboptions for now */
   1103                                         ND_PRINT((ndo, "\n\t\t%s Suboption #%u, length %u",
   1104                                                tok2str(ipcpopt_compproto_subopt_values,
   1105                                                        "Unknown",
   1106                                                        ipcomp_subopt),
   1107                                                ipcomp_subopt,
   1108                                                ipcomp_suboptlen));
   1109 
   1110                                         ipcomp_subopttotallen -= ipcomp_suboptlen;
   1111                                         p += ipcomp_suboptlen;
   1112                                 }
   1113                         }
   1114                         break;
   1115                 default:
   1116                         break;
   1117 		}
   1118 		break;
   1119 
   1120 	case IPCPOPT_ADDR:     /* those options share the same format - fall through */
   1121 	case IPCPOPT_MOBILE4:
   1122 	case IPCPOPT_PRIDNS:
   1123 	case IPCPOPT_PRINBNS:
   1124 	case IPCPOPT_SECDNS:
   1125 	case IPCPOPT_SECNBNS:
   1126 		if (len != 6) {
   1127 			ND_PRINT((ndo, " (length bogus, should be = 6)"));
   1128 			return 0;
   1129 		}
   1130 		ND_TCHECK2(*(p + 2), 4);
   1131 		ND_PRINT((ndo, ": %s", ipaddr_string(ndo, p + 2)));
   1132 		break;
   1133 	default:
   1134 		/*
   1135 		 * Unknown option; dump it as raw bytes now if we're
   1136 		 * not going to do so below.
   1137 		 */
   1138 		if (ndo->ndo_vflag < 2)
   1139 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
   1140 		break;
   1141 	}
   1142 	if (ndo->ndo_vflag > 1)
   1143 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
   1144 	return len;
   1145 
   1146 trunc:
   1147 	ND_PRINT((ndo, "[|ipcp]"));
   1148 	return 0;
   1149 }
   1150 
   1151 /* IP6CP config options */
   1152 static int
   1153 print_ip6cp_config_options(netdissect_options *ndo,
   1154                            const u_char *p, int length)
   1155 {
   1156 	int len, opt;
   1157 
   1158 	if (length < 2)
   1159 		return 0;
   1160 	ND_TCHECK2(*p, 2);
   1161 	len = p[1];
   1162 	opt = p[0];
   1163 	if (length < len)
   1164 		return 0;
   1165 	if (len < 2) {
   1166 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
   1167 		       tok2str(ip6cpopt_values,"unknown",opt),
   1168 		       opt,
   1169 		       len));
   1170 		return 0;
   1171 	}
   1172 
   1173 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
   1174 	       tok2str(ip6cpopt_values,"unknown",opt),
   1175 	       opt,
   1176 	       len));
   1177 
   1178 	switch (opt) {
   1179 	case IP6CP_IFID:
   1180 		if (len != 10) {
   1181 			ND_PRINT((ndo, " (length bogus, should be = 10)"));
   1182 			return len;
   1183 		}
   1184 		ND_TCHECK2(*(p + 2), 8);
   1185 		ND_PRINT((ndo, ": %04x:%04x:%04x:%04x",
   1186 		       EXTRACT_16BITS(p + 2),
   1187 		       EXTRACT_16BITS(p + 4),
   1188 		       EXTRACT_16BITS(p + 6),
   1189 		       EXTRACT_16BITS(p + 8)));
   1190 		break;
   1191 	default:
   1192 		/*
   1193 		 * Unknown option; dump it as raw bytes now if we're
   1194 		 * not going to do so below.
   1195 		 */
   1196 		if (ndo->ndo_vflag < 2)
   1197 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
   1198 		break;
   1199 	}
   1200 	if (ndo->ndo_vflag > 1)
   1201 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
   1202 
   1203 	return len;
   1204 
   1205 trunc:
   1206 	ND_PRINT((ndo, "[|ip6cp]"));
   1207 	return 0;
   1208 }
   1209 
   1210 
   1211 /* CCP config options */
   1212 static int
   1213 print_ccp_config_options(netdissect_options *ndo,
   1214                          const u_char *p, int length)
   1215 {
   1216 	int len, opt;
   1217 
   1218 	if (length < 2)
   1219 		return 0;
   1220 	ND_TCHECK2(*p, 2);
   1221 	len = p[1];
   1222 	opt = p[0];
   1223 	if (length < len)
   1224 		return 0;
   1225 	if (len < 2) {
   1226 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
   1227 		          tok2str(ccpconfopts_values, "Unknown", opt),
   1228 		          opt,
   1229 		          len));
   1230 		return 0;
   1231 	}
   1232 
   1233 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
   1234 	          tok2str(ccpconfopts_values, "Unknown", opt),
   1235 	          opt,
   1236 	          len));
   1237 
   1238 	switch (opt) {
   1239 	case CCPOPT_BSDCOMP:
   1240 		if (len < 3) {
   1241 			ND_PRINT((ndo, " (length bogus, should be >= 3)"));
   1242 			return len;
   1243 		}
   1244 		ND_TCHECK2(*(p + 2), 1);
   1245 		ND_PRINT((ndo, ": Version: %u, Dictionary Bits: %u",
   1246 			p[2] >> 5, p[2] & 0x1f));
   1247 		break;
   1248 	case CCPOPT_MVRCA:
   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, ": Features: %u, PxP: %s, History: %u, #CTX-ID: %u",
   1255 				(p[2] & 0xc0) >> 6,
   1256 				(p[2] & 0x20) ? "Enabled" : "Disabled",
   1257 				p[2] & 0x1f, p[3]));
   1258 		break;
   1259 	case CCPOPT_DEFLATE:
   1260 		if (len < 4) {
   1261 			ND_PRINT((ndo, " (length bogus, should be >= 4)"));
   1262 			return len;
   1263 		}
   1264 		ND_TCHECK2(*(p + 2), 1);
   1265 		ND_PRINT((ndo, ": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u",
   1266 			(p[2] & 0xf0) >> 4,
   1267 			((p[2] & 0x0f) == 8) ? "zlib" : "unkown",
   1268 			p[2] & 0x0f, (p[3] & 0xfc) >> 2, p[3] & 0x03));
   1269 		break;
   1270 
   1271 /* XXX: to be supported */
   1272 #if 0
   1273 	case CCPOPT_OUI:
   1274 	case CCPOPT_PRED1:
   1275 	case CCPOPT_PRED2:
   1276 	case CCPOPT_PJUMP:
   1277 	case CCPOPT_HPPPC:
   1278 	case CCPOPT_STACLZS:
   1279 	case CCPOPT_MPPC:
   1280 	case CCPOPT_GFZA:
   1281 	case CCPOPT_V42BIS:
   1282 	case CCPOPT_LZSDCP:
   1283 	case CCPOPT_DEC:
   1284 	case CCPOPT_RESV:
   1285 		break;
   1286 #endif
   1287 	default:
   1288 		/*
   1289 		 * Unknown option; dump it as raw bytes now if we're
   1290 		 * not going to do so below.
   1291 		 */
   1292 		if (ndo->ndo_vflag < 2)
   1293 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
   1294 		break;
   1295 	}
   1296 	if (ndo->ndo_vflag > 1)
   1297 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
   1298 
   1299 	return len;
   1300 
   1301 trunc:
   1302 	ND_PRINT((ndo, "[|ccp]"));
   1303 	return 0;
   1304 }
   1305 
   1306 /* BACP config options */
   1307 static int
   1308 print_bacp_config_options(netdissect_options *ndo,
   1309                           const u_char *p, int length)
   1310 {
   1311 	int len, opt;
   1312 
   1313 	if (length < 2)
   1314 		return 0;
   1315 	ND_TCHECK2(*p, 2);
   1316 	len = p[1];
   1317 	opt = p[0];
   1318 	if (length < len)
   1319 		return 0;
   1320 	if (len < 2) {
   1321 		ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
   1322 		          tok2str(bacconfopts_values, "Unknown", opt),
   1323 		          opt,
   1324 		          len));
   1325 		return 0;
   1326 	}
   1327 
   1328 	ND_PRINT((ndo, "\n\t  %s Option (0x%02x), length %u",
   1329 	          tok2str(bacconfopts_values, "Unknown", opt),
   1330 	          opt,
   1331 	          len));
   1332 
   1333 	switch (opt) {
   1334 	case BACPOPT_FPEER:
   1335 		if (len != 6) {
   1336 			ND_PRINT((ndo, " (length bogus, should be = 6)"));
   1337 			return len;
   1338 		}
   1339 		ND_TCHECK2(*(p + 2), 4);
   1340 		ND_PRINT((ndo, ": Magic-Num 0x%08x", EXTRACT_32BITS(p + 2)));
   1341 		break;
   1342 	default:
   1343 		/*
   1344 		 * Unknown option; dump it as raw bytes now if we're
   1345 		 * not going to do so below.
   1346 		 */
   1347 		if (ndo->ndo_vflag < 2)
   1348 			print_unknown_data(ndo, &p[2], "\n\t    ", len - 2);
   1349 		break;
   1350 	}
   1351 	if (ndo->ndo_vflag > 1)
   1352 		print_unknown_data(ndo, &p[2], "\n\t    ", len - 2); /* exclude TLV header */
   1353 
   1354 	return len;
   1355 
   1356 trunc:
   1357 	ND_PRINT((ndo, "[|bacp]"));
   1358 	return 0;
   1359 }
   1360 
   1361 static void
   1362 ppp_hdlc(netdissect_options *ndo,
   1363          const u_char *p, int length)
   1364 {
   1365 	u_char *b, *t, c;
   1366 	const u_char *s;
   1367 	int i, proto;
   1368 	const void *se;
   1369 
   1370         if (length <= 0)
   1371                 return;
   1372 
   1373 	b = (u_char *)malloc(length);
   1374 	if (b == NULL)
   1375 		return;
   1376 
   1377 	/*
   1378 	 * Unescape all the data into a temporary, private, buffer.
   1379 	 * Do this so that we dont overwrite the original packet
   1380 	 * contents.
   1381 	 */
   1382 	for (s = p, t = b, i = length; i > 0 && ND_TTEST(*s); i--) {
   1383 		c = *s++;
   1384 		if (c == 0x7d) {
   1385 			if (i <= 1 || !ND_TTEST(*s))
   1386 				break;
   1387 			i--;
   1388 			c = *s++ ^ 0x20;
   1389 		}
   1390 		*t++ = c;
   1391 	}
   1392 
   1393 	se = ndo->ndo_snapend;
   1394 	ndo->ndo_snapend = t;
   1395 	length = t - b;
   1396 
   1397         /* now lets guess about the payload codepoint format */
   1398         if (length < 1)
   1399                 goto trunc;
   1400         proto = *b; /* start with a one-octet codepoint guess */
   1401 
   1402         switch (proto) {
   1403         case PPP_IP:
   1404 		ip_print(ndo, b + 1, length - 1);
   1405 		goto cleanup;
   1406         case PPP_IPV6:
   1407 		ip6_print(ndo, b + 1, length - 1);
   1408 		goto cleanup;
   1409         default: /* no luck - try next guess */
   1410 		break;
   1411         }
   1412 
   1413         if (length < 2)
   1414                 goto trunc;
   1415         proto = EXTRACT_16BITS(b); /* next guess - load two octets */
   1416 
   1417         switch (proto) {
   1418         case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */
   1419             if (length < 4)
   1420                 goto trunc;
   1421             proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */
   1422             handle_ppp(ndo, proto, b + 4, length - 4);
   1423             break;
   1424         default: /* last guess - proto must be a PPP proto-id */
   1425             handle_ppp(ndo, proto, b + 2, length - 2);
   1426             break;
   1427         }
   1428 
   1429 cleanup:
   1430 	ndo->ndo_snapend = se;
   1431 	free(b);
   1432         return;
   1433 
   1434 trunc:
   1435 	ndo->ndo_snapend = se;
   1436 	free(b);
   1437 	ND_PRINT((ndo, "[|ppp]"));
   1438 }
   1439 
   1440 
   1441 /* PPP */
   1442 static void
   1443 handle_ppp(netdissect_options *ndo,
   1444            u_int proto, const u_char *p, int length)
   1445 {
   1446 	if ((proto & 0xff00) == 0x7e00) { /* is this an escape code ? */
   1447 		ppp_hdlc(ndo, p - 1, length);
   1448 		return;
   1449 	}
   1450 
   1451 	switch (proto) {
   1452 	case PPP_LCP: /* fall through */
   1453 	case PPP_IPCP:
   1454 	case PPP_OSICP:
   1455 	case PPP_MPLSCP:
   1456 	case PPP_IPV6CP:
   1457 	case PPP_CCP:
   1458 	case PPP_BACP:
   1459 		handle_ctrl_proto(ndo, proto, p, length);
   1460 		break;
   1461 	case PPP_ML:
   1462 		handle_mlppp(ndo, p, length);
   1463 		break;
   1464 	case PPP_CHAP:
   1465 		handle_chap(ndo, p, length);
   1466 		break;
   1467 	case PPP_PAP:
   1468 		handle_pap(ndo, p, length);
   1469 		break;
   1470 	case PPP_BAP:		/* XXX: not yet completed */
   1471 		handle_bap(ndo, p, length);
   1472 		break;
   1473 	case ETHERTYPE_IP:	/*XXX*/
   1474         case PPP_VJNC:
   1475 	case PPP_IP:
   1476 		ip_print(ndo, p, length);
   1477 		break;
   1478 	case ETHERTYPE_IPV6:	/*XXX*/
   1479 	case PPP_IPV6:
   1480 		ip6_print(ndo, p, length);
   1481 		break;
   1482 	case ETHERTYPE_IPX:	/*XXX*/
   1483 	case PPP_IPX:
   1484 		ipx_print(ndo, p, length);
   1485 		break;
   1486 	case PPP_OSI:
   1487 		isoclns_print(ndo, p, length, length);
   1488 		break;
   1489 	case PPP_MPLS_UCAST:
   1490 	case PPP_MPLS_MCAST:
   1491 		mpls_print(ndo, p, length);
   1492 		break;
   1493 	case PPP_COMP:
   1494 		ND_PRINT((ndo, "compressed PPP data"));
   1495 		break;
   1496 	default:
   1497 		ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto)));
   1498 		print_unknown_data(ndo, p, "\n\t", length);
   1499 		break;
   1500 	}
   1501 }
   1502 
   1503 /* Standard PPP printer */
   1504 u_int
   1505 ppp_print(netdissect_options *ndo,
   1506           register const u_char *p, u_int length)
   1507 {
   1508 	u_int proto,ppp_header;
   1509         u_int olen = length; /* _o_riginal length */
   1510 	u_int hdr_len = 0;
   1511 
   1512 	/*
   1513 	 * Here, we assume that p points to the Address and Control
   1514 	 * field (if they present).
   1515 	 */
   1516 	if (length < 2)
   1517 		goto trunc;
   1518 	ND_TCHECK2(*p, 2);
   1519         ppp_header = EXTRACT_16BITS(p);
   1520 
   1521         switch(ppp_header) {
   1522         case (PPP_WITHDIRECTION_IN  << 8 | PPP_CONTROL):
   1523             if (ndo->ndo_eflag) ND_PRINT((ndo, "In  "));
   1524             p += 2;
   1525             length -= 2;
   1526             hdr_len += 2;
   1527             break;
   1528         case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL):
   1529             if (ndo->ndo_eflag) ND_PRINT((ndo, "Out "));
   1530             p += 2;
   1531             length -= 2;
   1532             hdr_len += 2;
   1533             break;
   1534         case (PPP_ADDRESS << 8 | PPP_CONTROL):
   1535             p += 2;			/* ACFC not used */
   1536             length -= 2;
   1537             hdr_len += 2;
   1538             break;
   1539 
   1540         default:
   1541             break;
   1542         }
   1543 
   1544 	if (length < 2)
   1545 		goto trunc;
   1546 	ND_TCHECK(*p);
   1547 	if (*p % 2) {
   1548 		proto = *p;		/* PFC is used */
   1549 		p++;
   1550 		length--;
   1551 		hdr_len++;
   1552 	} else {
   1553 		ND_TCHECK2(*p, 2);
   1554 		proto = EXTRACT_16BITS(p);
   1555 		p += 2;
   1556 		length -= 2;
   1557 		hdr_len += 2;
   1558 	}
   1559 
   1560 	if (ndo->ndo_eflag)
   1561 		ND_PRINT((ndo, "%s (0x%04x), length %u: ",
   1562 		          tok2str(ppptype2str, "unknown", proto),
   1563 		          proto,
   1564 		          olen));
   1565 
   1566 	handle_ppp(ndo, proto, p, length);
   1567 	return (hdr_len);
   1568 trunc:
   1569 	ND_PRINT((ndo, "[|ppp]"));
   1570 	return (0);
   1571 }
   1572 
   1573 
   1574 /* PPP I/F printer */
   1575 u_int
   1576 ppp_if_print(netdissect_options *ndo,
   1577              const struct pcap_pkthdr *h, register const u_char *p)
   1578 {
   1579 	register u_int length = h->len;
   1580 	register u_int caplen = h->caplen;
   1581 
   1582 	if (caplen < PPP_HDRLEN) {
   1583 		ND_PRINT((ndo, "[|ppp]"));
   1584 		return (caplen);
   1585 	}
   1586 
   1587 #if 0
   1588 	/*
   1589 	 * XXX: seems to assume that there are 2 octets prepended to an
   1590 	 * actual PPP frame. The 1st octet looks like Input/Output flag
   1591 	 * while 2nd octet is unknown, at least to me
   1592 	 * (mshindo (at) mshindo.net).
   1593 	 *
   1594 	 * That was what the original tcpdump code did.
   1595 	 *
   1596 	 * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
   1597 	 * packets and 0 for inbound packets - but only if the
   1598 	 * protocol field has the 0x8000 bit set (i.e., it's a network
   1599 	 * control protocol); it does so before running the packet through
   1600 	 * "bpf_filter" to see if it should be discarded, and to see
   1601 	 * if we should update the time we sent the most recent packet...
   1602 	 *
   1603 	 * ...but it puts the original address field back after doing
   1604 	 * so.
   1605 	 *
   1606 	 * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
   1607 	 *
   1608 	 * I don't know if any PPP implementation handed up to a BPF
   1609 	 * device packets with the first octet being 1 for outbound and
   1610 	 * 0 for inbound packets, so I (guy (at) alum.mit.edu) don't know
   1611 	 * whether that ever needs to be checked or not.
   1612 	 *
   1613 	 * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
   1614 	 * and its tcpdump appears to assume that the frame always
   1615 	 * begins with an address field and a control field, and that
   1616 	 * the address field might be 0x0f or 0x8f, for Cisco
   1617 	 * point-to-point with HDLC framing as per section 4.3.1 of RFC
   1618 	 * 1547, as well as 0xff, for PPP in HDLC-like framing as per
   1619 	 * RFC 1662.
   1620 	 *
   1621 	 * (Is the Cisco framing in question what DLT_C_HDLC, in
   1622 	 * BSD/OS, is?)
   1623 	 */
   1624 	if (ndo->ndo_eflag)
   1625 		ND_PRINT((ndo, "%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]));
   1626 #endif
   1627 
   1628 	ppp_print(ndo, p, length);
   1629 
   1630 	return (0);
   1631 }
   1632 
   1633 /*
   1634  * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
   1635  * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
   1636  * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
   1637  * discard them *if* those are the first two octets, and parse the remaining
   1638  * packet as a PPP packet, as "ppp_print()" does).
   1639  *
   1640  * This handles, for example, DLT_PPP_SERIAL in NetBSD.
   1641  */
   1642 u_int
   1643 ppp_hdlc_if_print(netdissect_options *ndo,
   1644                   const struct pcap_pkthdr *h, register const u_char *p)
   1645 {
   1646 	register u_int length = h->len;
   1647 	register u_int caplen = h->caplen;
   1648 	u_int proto;
   1649 	u_int hdrlen = 0;
   1650 
   1651 	if (caplen < 2) {
   1652 		ND_PRINT((ndo, "[|ppp]"));
   1653 		return (caplen);
   1654 	}
   1655 
   1656 	switch (p[0]) {
   1657 
   1658 	case PPP_ADDRESS:
   1659 		if (caplen < 4) {
   1660 			ND_PRINT((ndo, "[|ppp]"));
   1661 			return (caplen);
   1662 		}
   1663 
   1664 		if (ndo->ndo_eflag)
   1665 			ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length));
   1666 		p += 2;
   1667 		length -= 2;
   1668 		hdrlen += 2;
   1669 
   1670 		proto = EXTRACT_16BITS(p);
   1671 		p += 2;
   1672 		length -= 2;
   1673 		hdrlen += 2;
   1674 		ND_PRINT((ndo, "%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto)));
   1675 
   1676 		handle_ppp(ndo, proto, p, length);
   1677 		break;
   1678 
   1679 	case CHDLC_UNICAST:
   1680 	case CHDLC_BCAST:
   1681 		return (chdlc_if_print(ndo, h, p));
   1682 
   1683 	default:
   1684 		if (caplen < 4) {
   1685 			ND_PRINT((ndo, "[|ppp]"));
   1686 			return (caplen);
   1687 		}
   1688 
   1689 		if (ndo->ndo_eflag)
   1690 			ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length));
   1691 		p += 2;
   1692 		hdrlen += 2;
   1693 
   1694 		/*
   1695 		 * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
   1696 		 * the next two octets as an Ethernet type; does that
   1697 		 * ever happen?
   1698 		 */
   1699 		ND_PRINT((ndo, "unknown addr %02x; ctrl %02x", p[0], p[1]));
   1700 		break;
   1701 	}
   1702 
   1703 	return (hdrlen);
   1704 }
   1705 
   1706 #define PPP_BSDI_HDRLEN 24
   1707 
   1708 /* BSD/OS specific PPP printer */
   1709 u_int
   1710 ppp_bsdos_if_print(netdissect_options *ndo _U_,
   1711                    const struct pcap_pkthdr *h _U_, register const u_char *p _U_)
   1712 {
   1713 	register int hdrlength;
   1714 #ifdef __bsdi__
   1715 	register u_int length = h->len;
   1716 	register u_int caplen = h->caplen;
   1717 	uint16_t ptype;
   1718 	const u_char *q;
   1719 	int i;
   1720 
   1721 	if (caplen < PPP_BSDI_HDRLEN) {
   1722 		ND_PRINT((ndo, "[|ppp]"));
   1723 		return (caplen)
   1724 	}
   1725 
   1726 	hdrlength = 0;
   1727 
   1728 #if 0
   1729 	if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
   1730 		if (ndo->ndo_eflag)
   1731 			ND_PRINT((ndo, "%02x %02x ", p[0], p[1]));
   1732 		p += 2;
   1733 		hdrlength = 2;
   1734 	}
   1735 
   1736 	if (ndo->ndo_eflag)
   1737 		ND_PRINT((ndo, "%d ", length));
   1738 	/* Retrieve the protocol type */
   1739 	if (*p & 01) {
   1740 		/* Compressed protocol field */
   1741 		ptype = *p;
   1742 		if (ndo->ndo_eflag)
   1743 			ND_PRINT((ndo, "%02x ", ptype));
   1744 		p++;
   1745 		hdrlength += 1;
   1746 	} else {
   1747 		/* Un-compressed protocol field */
   1748 		ptype = EXTRACT_16BITS(p);
   1749 		if (ndo->ndo_eflag)
   1750 			ND_PRINT((ndo, "%04x ", ptype));
   1751 		p += 2;
   1752 		hdrlength += 2;
   1753 	}
   1754 #else
   1755 	ptype = 0;	/*XXX*/
   1756 	if (ndo->ndo_eflag)
   1757 		ND_PRINT((ndo, "%c ", p[SLC_DIR] ? 'O' : 'I'));
   1758 	if (p[SLC_LLHL]) {
   1759 		/* link level header */
   1760 		struct ppp_header *ph;
   1761 
   1762 		q = p + SLC_BPFHDRLEN;
   1763 		ph = (struct ppp_header *)q;
   1764 		if (ph->phdr_addr == PPP_ADDRESS
   1765 		 && ph->phdr_ctl == PPP_CONTROL) {
   1766 			if (ndo->ndo_eflag)
   1767 				ND_PRINT((ndo, "%02x %02x ", q[0], q[1]));
   1768 			ptype = EXTRACT_16BITS(&ph->phdr_type);
   1769 			if (ndo->ndo_eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
   1770 				ND_PRINT((ndo, "%s ", tok2str(ppptype2str,
   1771 						"proto-#%d", ptype)));
   1772 			}
   1773 		} else {
   1774 			if (ndo->ndo_eflag) {
   1775 				ND_PRINT((ndo, "LLH=["));
   1776 				for (i = 0; i < p[SLC_LLHL]; i++)
   1777 					ND_PRINT((ndo, "%02x", q[i]));
   1778 				ND_PRINT((ndo, "] "));
   1779 			}
   1780 		}
   1781 	}
   1782 	if (ndo->ndo_eflag)
   1783 		ND_PRINT((ndo, "%d ", length));
   1784 	if (p[SLC_CHL]) {
   1785 		q = p + SLC_BPFHDRLEN + p[SLC_LLHL];
   1786 
   1787 		switch (ptype) {
   1788 		case PPP_VJC:
   1789 			ptype = vjc_print(ndo, q, ptype);
   1790 			hdrlength = PPP_BSDI_HDRLEN;
   1791 			p += hdrlength;
   1792 			switch (ptype) {
   1793 			case PPP_IP:
   1794 				ip_print(ndo, p, length);
   1795 				break;
   1796 			case PPP_IPV6:
   1797 				ip6_print(ndo, p, length);
   1798 				break;
   1799 			case PPP_MPLS_UCAST:
   1800 			case PPP_MPLS_MCAST:
   1801 				mpls_print(ndo, p, length);
   1802 				break;
   1803 			}
   1804 			goto printx;
   1805 		case PPP_VJNC:
   1806 			ptype = vjc_print(ndo, q, ptype);
   1807 			hdrlength = PPP_BSDI_HDRLEN;
   1808 			p += hdrlength;
   1809 			switch (ptype) {
   1810 			case PPP_IP:
   1811 				ip_print(ndo, p, length);
   1812 				break;
   1813 			case PPP_IPV6:
   1814 				ip6_print(ndo, p, length);
   1815 				break;
   1816 			case PPP_MPLS_UCAST:
   1817 			case PPP_MPLS_MCAST:
   1818 				mpls_print(ndo, p, length);
   1819 				break;
   1820 			}
   1821 			goto printx;
   1822 		default:
   1823 			if (ndo->ndo_eflag) {
   1824 				ND_PRINT((ndo, "CH=["));
   1825 				for (i = 0; i < p[SLC_LLHL]; i++)
   1826 					ND_PRINT((ndo, "%02x", q[i]));
   1827 				ND_PRINT((ndo, "] "));
   1828 			}
   1829 			break;
   1830 		}
   1831 	}
   1832 
   1833 	hdrlength = PPP_BSDI_HDRLEN;
   1834 #endif
   1835 
   1836 	length -= hdrlength;
   1837 	p += hdrlength;
   1838 
   1839 	switch (ptype) {
   1840 	case PPP_IP:
   1841 		ip_print(p, length);
   1842 		break;
   1843 	case PPP_IPV6:
   1844 		ip6_print(ndo, p, length);
   1845 		break;
   1846 	case PPP_MPLS_UCAST:
   1847 	case PPP_MPLS_MCAST:
   1848 		mpls_print(ndo, p, length);
   1849 		break;
   1850 	default:
   1851 		ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype)));
   1852 	}
   1853 
   1854 printx:
   1855 #else /* __bsdi */
   1856 	hdrlength = 0;
   1857 #endif /* __bsdi__ */
   1858 	return (hdrlength);
   1859 }
   1860 
   1861 
   1862 /*
   1863  * Local Variables:
   1864  * c-style: whitesmith
   1865  * c-basic-offset: 8
   1866  * End:
   1867  */
   1868