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
35static 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.2 2010/12/05 05:11:30 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
73struct 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
137struct 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
194static 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
251const 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
274const 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
292struct 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
307struct tok ipcpopt_compproto_values[] = {
308        { PPP_VJC, "VJ-Comp" },
309        { IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" },
310	{ 0,		  NULL }
311};
312
313struct 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
322struct 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
341struct 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
366struct 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
383struct 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
397struct 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
414static void handle_ctrl_proto (u_int proto,const u_char *p, int length);
415static void handle_chap (const u_char *p, int length);
416static void handle_pap (const u_char *p, int length);
417static void handle_bap (const u_char *p, int length);
418static void handle_mlppp(const u_char *p, int length);
419static int print_lcp_config_options (const u_char *p, int);
420static int print_ipcp_config_options (const u_char *p, int);
421static int print_ip6cp_config_options (const u_char *p, int);
422static int print_ccp_config_options (const u_char *p, int);
423static int print_bacp_config_options (const u_char *p, int);
424static void handle_ppp (u_int proto, const u_char *p, int length);
425static void ppp_hdlc(const u_char *p, int length);
426
427/* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
428static void
429handle_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
588trunc:
589	printf("[|%s]", typestr);
590}
591
592/* LCP config options */
593static int
594print_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
775trunc:
776	printf("[|lcp]");
777	return 0;
778}
779
780/* ML-PPP*/
781struct tok ppp_ml_flag_values[] = {
782    { 0x80, "begin" },
783    { 0x40, "end" },
784    { 0, NULL }
785};
786
787static void
788handle_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 */
802static void
803handle_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
876trunc:
877	printf("[|chap]");
878}
879
880/* PAP (see RFC 1334) */
881static void
882handle_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
970trunc:
971	printf("[|pap]");
972}
973
974/* BAP */
975static void
976handle_bap(const u_char *p _U_, int length _U_)
977{
978	/* XXX: to be supported!! */
979}
980
981
982/* IPCP config options */
983static int
984print_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
1100invlen:
1101	printf(", invalid-length-%d", opt);
1102	return 0;
1103
1104trunc:
1105	printf("[|ipcp]");
1106	return 0;
1107}
1108
1109/* IP6CP config options */
1110static int
1111print_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
1156invlen:
1157	printf(", invalid-length-%d", opt);
1158	return 0;
1159
1160trunc:
1161	printf("[|ip6cp]");
1162	return 0;
1163}
1164
1165
1166/* CCP config options */
1167static int
1168print_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
1219trunc:
1220	printf("[|ccp]");
1221	return 0;
1222}
1223
1224/* BACP config options */
1225static int
1226print_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
1265trunc:
1266	printf("[|bacp]");
1267	return 0;
1268}
1269
1270
1271static void
1272ppp_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(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
1330cleanup:
1331        snapend = se;
1332	free(b);
1333        return;
1334}
1335
1336
1337/* PPP */
1338static void
1339handle_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(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 */
1401u_int
1402ppp_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);
1464trunc:
1465	printf("[|ppp]");
1466	return (0);
1467}
1468
1469
1470/* PPP I/F printer */
1471u_int
1472ppp_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 */
1537u_int
1538ppp_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 */
1599u_int
1600ppp_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(p, length);
1684				break;
1685#ifdef INET6
1686			case PPP_IPV6:
1687				ip6_print(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(p, length);
1703				break;
1704#ifdef INET6
1705			case PPP_IPV6:
1706				ip6_print(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(p, length);
1739		break;
1740#endif
1741        case PPP_MPLS_UCAST:
1742        case PPP_MPLS_MCAST:
1743                mpls_print(p, length);
1744                break;
1745	default:
1746		printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));
1747	}
1748
1749printx:
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