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