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