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