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