xref: /dragonfly/contrib/tcpdump/print-ppp.c (revision 67640b13)
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more
22  * complete PPP support.
23  */
24 
25 /*
26  * TODO:
27  * o resolve XXX as much as possible
28  * o MP support
29  * o BAP support
30  */
31 
32 #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 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 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 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 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 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 struct tok ipcpopt_compproto_values[] = {
303         { PPP_VJC, "VJ-Comp" },
304         { IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" },
305 	{ 0,		  NULL }
306 };
307 
308 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 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 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 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 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 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 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@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@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