117680Spst/*
239300Sfenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2053146Sbrian *
2175118Sfenner * Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more
2275118Sfenner * complete PPP support.
2375118Sfenner *
2453146Sbrian * $FreeBSD$
2517680Spst */
2617680Spst
2775118Sfenner/*
2875118Sfenner * TODO:
2975118Sfenner * o resolve XXX as much as possible
3075118Sfenner * o MP support
3175118Sfenner * o BAP support
3275118Sfenner */
3375118Sfenner
3417680Spst#ifndef lint
35127675Sbmsstatic const char rcsid[] _U_ =
36190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.114 2005-12-05 11:35:58 hannes Exp $ (LBL)";
3717680Spst#endif
3817680Spst
3956896Sfenner#ifdef HAVE_CONFIG_H
4056896Sfenner#include "config.h"
4156896Sfenner#endif
4256896Sfenner
43127675Sbms#include <tcpdump-stdinc.h>
4417680Spst
4575118Sfenner#ifdef __bsdi__
4675118Sfenner#include <net/slcompress.h>
4775118Sfenner#include <net/if_ppp.h>
4817680Spst#endif
4917680Spst
5017680Spst#include <pcap.h>
5117680Spst#include <stdio.h>
52146778Ssam#include <stdlib.h>
5317680Spst
5417680Spst#include "interface.h"
5556896Sfenner#include "extract.h"
5617680Spst#include "addrtoname.h"
5739300Sfenner#include "ppp.h"
5875118Sfenner#include "chdlc.h"
5975118Sfenner#include "ethertype.h"
60146778Ssam#include "oui.h"
6117680Spst
6275118Sfenner/*
6375118Sfenner * The following constatns are defined by IANA. Please refer to
6475118Sfenner *    http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
6575118Sfenner * for the up-to-date information.
6675118Sfenner */
6717680Spst
68127675Sbms/* Protocol Codes defined in ppp.h */
6917692Spst
70127675Sbmsstruct tok ppptype2str[] = {
71127675Sbms        { PPP_IP,	  "IP" },
72127675Sbms        { PPP_OSI,	  "OSI" },
73127675Sbms        { PPP_NS,	  "NS" },
74127675Sbms        { PPP_DECNET,	  "DECNET" },
75127675Sbms        { PPP_APPLE,	  "APPLE" },
76127675Sbms	{ PPP_IPX,	  "IPX" },
77146778Ssam	{ PPP_VJC,	  "VJC IP" },
78146778Ssam	{ PPP_VJNC,	  "VJNC IP" },
79127675Sbms	{ PPP_BRPDU,	  "BRPDU" },
80127675Sbms	{ PPP_STII,	  "STII" },
81127675Sbms	{ PPP_VINES,	  "VINES" },
82127675Sbms	{ PPP_MPLS_UCAST, "MPLS" },
83127675Sbms	{ PPP_MPLS_MCAST, "MPLS" },
84146778Ssam        { PPP_COMP,       "Compressed"},
85146778Ssam        { PPP_ML,         "MLPPP"},
86146778Ssam        { PPP_IPV6,       "IP6"},
87127675Sbms
88127675Sbms	{ PPP_HELLO,	  "HELLO" },
89127675Sbms	{ PPP_LUXCOM,	  "LUXCOM" },
90127675Sbms	{ PPP_SNS,	  "SNS" },
91127675Sbms	{ PPP_IPCP,	  "IPCP" },
92127675Sbms	{ PPP_OSICP,	  "OSICP" },
93127675Sbms	{ PPP_NSCP,	  "NSCP" },
94127675Sbms	{ PPP_DECNETCP,   "DECNETCP" },
95127675Sbms	{ PPP_APPLECP,	  "APPLECP" },
96127675Sbms	{ PPP_IPXCP,	  "IPXCP" },
97127675Sbms	{ PPP_STIICP,	  "STIICP" },
98127675Sbms	{ PPP_VINESCP,	  "VINESCP" },
99146778Ssam        { PPP_IPV6CP,     "IP6CP" },
100127675Sbms	{ PPP_MPLSCP,	  "MPLSCP" },
101127675Sbms
102127675Sbms	{ PPP_LCP,	  "LCP" },
103127675Sbms	{ PPP_PAP,	  "PAP" },
104127675Sbms	{ PPP_LQM,	  "LQM" },
105127675Sbms	{ PPP_CHAP,	  "CHAP" },
106146778Ssam	{ PPP_EAP,	  "EAP" },
107146778Ssam	{ PPP_SPAP,	  "SPAP" },
108146778Ssam	{ PPP_SPAP_OLD,	  "Old-SPAP" },
109127675Sbms	{ PPP_BACP,	  "BACP" },
110127675Sbms	{ PPP_BAP,	  "BAP" },
111146778Ssam	{ PPP_MPCP,	  "MLPPP-CP" },
112127675Sbms	{ 0,		  NULL }
113127675Sbms};
114127675Sbms
115127675Sbms/* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */
116127675Sbms
11775118Sfenner#define CPCODES_VEXT		0	/* Vendor-Specific (RFC2153) */
11875118Sfenner#define CPCODES_CONF_REQ	1	/* Configure-Request */
11975118Sfenner#define CPCODES_CONF_ACK	2	/* Configure-Ack */
12075118Sfenner#define CPCODES_CONF_NAK	3	/* Configure-Nak */
12175118Sfenner#define CPCODES_CONF_REJ	4	/* Configure-Reject */
12275118Sfenner#define CPCODES_TERM_REQ	5	/* Terminate-Request */
12375118Sfenner#define CPCODES_TERM_ACK	6	/* Terminate-Ack */
12475118Sfenner#define CPCODES_CODE_REJ	7	/* Code-Reject */
12575118Sfenner#define CPCODES_PROT_REJ	8	/* Protocol-Reject (LCP only) */
12675118Sfenner#define CPCODES_ECHO_REQ	9	/* Echo-Request (LCP only) */
12775118Sfenner#define CPCODES_ECHO_RPL	10	/* Echo-Reply (LCP only) */
12875118Sfenner#define CPCODES_DISC_REQ	11	/* Discard-Request (LCP only) */
129127675Sbms#define CPCODES_ID		12	/* Identification (LCP only) RFC1570 */
130127675Sbms#define CPCODES_TIME_REM	13	/* Time-Remaining (LCP only) RFC1570 */
131127675Sbms#define CPCODES_RESET_REQ	14	/* Reset-Request (CCP only) RFC1962 */
13275118Sfenner#define CPCODES_RESET_REP	15	/* Reset-Reply (CCP only) */
13338638Sthepish
134127675Sbmsstruct tok cpcodes[] = {
135127675Sbms	{CPCODES_VEXT,      "Vendor-Extension"}, /* RFC2153 */
136127675Sbms	{CPCODES_CONF_REQ,  "Conf-Request"},
137127675Sbms        {CPCODES_CONF_ACK,  "Conf-Ack"},
138127675Sbms	{CPCODES_CONF_NAK,  "Conf-Nack"},
139127675Sbms	{CPCODES_CONF_REJ,  "Conf-Reject"},
140127675Sbms	{CPCODES_TERM_REQ,  "Term-Request"},
141127675Sbms	{CPCODES_TERM_ACK,  "Term-Ack"},
142127675Sbms	{CPCODES_CODE_REJ,  "Code-Reject"},
143127675Sbms	{CPCODES_PROT_REJ,  "Prot-Reject"},
144127675Sbms	{CPCODES_ECHO_REQ,  "Echo-Request"},
145127675Sbms	{CPCODES_ECHO_RPL,  "Echo-Reply"},
146127675Sbms	{CPCODES_DISC_REQ,  "Disc-Req"},
147127675Sbms	{CPCODES_ID,        "Ident"},            /* RFC1570 */
148127675Sbms	{CPCODES_TIME_REM,  "Time-Rem"},         /* RFC1570 */
149127675Sbms	{CPCODES_RESET_REQ, "Reset-Req"},        /* RFC1962 */
150127675Sbms	{CPCODES_RESET_REP, "Reset-Ack"},        /* RFC1962 */
151127675Sbms        {0,                 NULL}
15238638Sthepish};
15338638Sthepish
15475118Sfenner/* LCP Config Options */
15575118Sfenner
15638638Sthepish#define LCPOPT_VEXT	0
15738638Sthepish#define LCPOPT_MRU	1
15838638Sthepish#define LCPOPT_ACCM	2
15938638Sthepish#define LCPOPT_AP	3
16038638Sthepish#define LCPOPT_QP	4
16138638Sthepish#define LCPOPT_MN	5
16275118Sfenner#define LCPOPT_DEP6	6
16338638Sthepish#define LCPOPT_PFC	7
16438638Sthepish#define LCPOPT_ACFC	8
16575118Sfenner#define LCPOPT_FCSALT	9
16675118Sfenner#define LCPOPT_SDP	10
16775118Sfenner#define LCPOPT_NUMMODE	11
16875118Sfenner#define LCPOPT_DEP12	12
16975118Sfenner#define LCPOPT_CBACK	13
17075118Sfenner#define LCPOPT_DEP14	14
17175118Sfenner#define LCPOPT_DEP15	15
17275118Sfenner#define LCPOPT_DEP16	16
17375118Sfenner#define LCPOPT_MLMRRU	17
17475118Sfenner#define LCPOPT_MLSSNHF	18
17575118Sfenner#define LCPOPT_MLED	19
17675118Sfenner#define LCPOPT_PROP	20
17775118Sfenner#define LCPOPT_DCEID	21
17875118Sfenner#define LCPOPT_MPP	22
17975118Sfenner#define LCPOPT_LD	23
18075118Sfenner#define LCPOPT_LCPAOPT	24
18175118Sfenner#define LCPOPT_COBS	25
18275118Sfenner#define LCPOPT_PE	26
18375118Sfenner#define LCPOPT_MLHF	27
18475118Sfenner#define LCPOPT_I18N	28
18575118Sfenner#define LCPOPT_SDLOS	29
18675118Sfenner#define LCPOPT_PPPMUX	30
18738638Sthepish
18875118Sfenner#define LCPOPT_MIN LCPOPT_VEXT
18975118Sfenner#define LCPOPT_MAX LCPOPT_PPPMUX
19038638Sthepish
19175118Sfennerstatic const char *lcpconfopts[] = {
19275118Sfenner	"Vend-Ext",		/* (0) */
19375118Sfenner	"MRU",			/* (1) */
19475118Sfenner	"ACCM",			/* (2) */
19575118Sfenner	"Auth-Prot",		/* (3) */
19675118Sfenner	"Qual-Prot",		/* (4) */
19775118Sfenner	"Magic-Num",		/* (5) */
19875118Sfenner	"deprecated(6)",	/* used to be a Quality Protocol */
19975118Sfenner	"PFC",			/* (7) */
20075118Sfenner	"ACFC",			/* (8) */
20175118Sfenner	"FCS-Alt",		/* (9) */
20275118Sfenner	"SDP",			/* (10) */
20375118Sfenner	"Num-Mode",		/* (11) */
20475118Sfenner	"deprecated(12)",	/* used to be a Multi-Link-Procedure*/
20575118Sfenner	"Call-Back",		/* (13) */
20675118Sfenner	"deprecated(14)",	/* used to be a Connect-Time */
20775118Sfenner	"deprecated(15)",	/* used to be a Compund-Frames */
20875118Sfenner	"deprecated(16)",	/* used to be a Nominal-Data-Encap */
20975118Sfenner	"MRRU",			/* (17) */
210146778Ssam	"12-Bit seq #",		/* (18) */
21175118Sfenner	"End-Disc",		/* (19) */
21275118Sfenner	"Proprietary",		/* (20) */
21375118Sfenner	"DCE-Id",		/* (21) */
21475118Sfenner	"MP+",			/* (22) */
21575118Sfenner	"Link-Disc",		/* (23) */
21675118Sfenner	"LCP-Auth-Opt",		/* (24) */
21775118Sfenner	"COBS",			/* (25) */
21875118Sfenner	"Prefix-elision",	/* (26) */
21975118Sfenner	"Multilink-header-Form",/* (27) */
22075118Sfenner	"I18N",			/* (28) */
22175118Sfenner	"SDL-over-SONET/SDH",	/* (29) */
22275118Sfenner	"PPP-Muxing",		/* (30) */
22338638Sthepish};
22438638Sthepish
22575118Sfenner/* ECP - to be supported */
22675118Sfenner
22775118Sfenner/* CCP Config Options */
22875118Sfenner
22975118Sfenner#define CCPOPT_OUI	0	/* RFC1962 */
23075118Sfenner#define CCPOPT_PRED1	1	/* RFC1962 */
23175118Sfenner#define CCPOPT_PRED2	2	/* RFC1962 */
23275118Sfenner#define CCPOPT_PJUMP	3	/* RFC1962 */
23375118Sfenner/* 4-15 unassigned */
23475118Sfenner#define CCPOPT_HPPPC	16	/* RFC1962 */
23575118Sfenner#define CCPOPT_STACLZS	17	/* RFC1974 */
23675118Sfenner#define CCPOPT_MPPC	18	/* RFC2118 */
23775118Sfenner#define CCPOPT_GFZA	19	/* RFC1962 */
23875118Sfenner#define CCPOPT_V42BIS	20	/* RFC1962 */
23975118Sfenner#define CCPOPT_BSDCOMP	21	/* RFC1977 */
24075118Sfenner/* 22 unassigned */
24175118Sfenner#define CCPOPT_LZSDCP	23	/* RFC1967 */
24275118Sfenner#define CCPOPT_MVRCA	24	/* RFC1975 */
24375118Sfenner#define CCPOPT_DEC	25	/* RFC1976 */
24475118Sfenner#define CCPOPT_DEFLATE	26	/* RFC1979 */
24575118Sfenner/* 27-254 unassigned */
24675118Sfenner#define CCPOPT_RESV	255	/* RFC1962 */
24775118Sfenner
248147904Ssamconst struct tok ccpconfopts_values[] = {
249147904Ssam        { CCPOPT_OUI, "OUI" },
250147904Ssam        { CCPOPT_PRED1, "Pred-1" },
251147904Ssam        { CCPOPT_PRED2, "Pred-2" },
252147904Ssam        { CCPOPT_PJUMP, "Puddle" },
253147904Ssam        { CCPOPT_HPPPC, "HP-PPC" },
254147904Ssam        { CCPOPT_STACLZS, "Stac-LZS" },
255147904Ssam        { CCPOPT_MPPC, "MPPC" },
256147904Ssam        { CCPOPT_GFZA, "Gand-FZA" },
257147904Ssam        { CCPOPT_V42BIS, "V.42bis" },
258147904Ssam        { CCPOPT_BSDCOMP, "BSD-Comp" },
259147904Ssam        { CCPOPT_LZSDCP, "LZS-DCP" },
260147904Ssam        { CCPOPT_MVRCA, "MVRCA" },
261147904Ssam        { CCPOPT_DEC, "DEC" },
262147904Ssam        { CCPOPT_DEFLATE, "Deflate" },
263147904Ssam        { CCPOPT_RESV, "Reserved"},
264147904Ssam        {0,                 NULL}
26575118Sfenner};
26675118Sfenner
26775118Sfenner/* BACP Config Options */
26875118Sfenner
26975118Sfenner#define BACPOPT_FPEER	1	/* RFC2125 */
27075118Sfenner
271147904Ssamconst struct tok bacconfopts_values[] = {
272147904Ssam        { BACPOPT_FPEER, "Favored-Peer" },
273147904Ssam        {0,                 NULL}
274147904Ssam};
275147904Ssam
276147904Ssam
27775118Sfenner/* SDCP - to be supported */
27875118Sfenner
27975118Sfenner/* IPCP Config Options */
28075118Sfenner#define IPCPOPT_2ADDR	1	/* RFC1172, RFC1332 (deprecated) */
28175118Sfenner#define IPCPOPT_IPCOMP	2	/* RFC1332 */
28275118Sfenner#define IPCPOPT_ADDR	3	/* RFC1332 */
28375118Sfenner#define IPCPOPT_MOBILE4	4	/* RFC2290 */
28475118Sfenner#define IPCPOPT_PRIDNS	129	/* RFC1877 */
28575118Sfenner#define IPCPOPT_PRINBNS	130	/* RFC1877 */
28675118Sfenner#define IPCPOPT_SECDNS	131	/* RFC1877 */
28775118Sfenner#define IPCPOPT_SECNBNS	132	/* RFC1877 */
28875118Sfenner
289146778Ssamstruct tok ipcpopt_values[] = {
290146778Ssam        { IPCPOPT_2ADDR, "IP-Addrs" },
291146778Ssam        { IPCPOPT_IPCOMP, "IP-Comp" },
292146778Ssam        { IPCPOPT_ADDR, "IP-Addr" },
293146778Ssam        { IPCPOPT_MOBILE4, "Home-Addr" },
294146778Ssam        { IPCPOPT_PRIDNS, "Pri-DNS" },
295146778Ssam        { IPCPOPT_PRINBNS, "Pri-NBNS" },
296146778Ssam        { IPCPOPT_SECDNS, "Sec-DNS" },
297146778Ssam        { IPCPOPT_SECNBNS, "Sec-NBNS" },
298146778Ssam	{ 0,		  NULL }
299146778Ssam};
300146778Ssam
301172686Smlaier#define IPCPOPT_IPCOMP_HDRCOMP 0x61  /* rfc3544 */
302172686Smlaier#define IPCPOPT_IPCOMP_MINLEN    14
303146778Ssam
304172686Smlaierstruct tok ipcpopt_compproto_values[] = {
305172686Smlaier        { PPP_VJC, "VJ-Comp" },
306172686Smlaier        { IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" },
307172686Smlaier	{ 0,		  NULL }
308172686Smlaier};
309172686Smlaier
310172686Smlaierstruct tok ipcpopt_compproto_subopt_values[] = {
311172686Smlaier        { 1, "RTP-Compression" },
312172686Smlaier        { 2, "Enhanced RTP-Compression" },
313172686Smlaier	{ 0,		  NULL }
314172686Smlaier};
315172686Smlaier
316146778Ssam/* IP6CP Config Options */
317146778Ssam#define IP6CP_IFID      1
318146778Ssam
319146778Ssamstruct tok ip6cpopt_values[] = {
320146778Ssam        { IP6CP_IFID, "Interface-ID" },
321146778Ssam	{ 0,		  NULL }
322146778Ssam};
323146778Ssam
32475118Sfenner/* ATCP - to be supported */
32575118Sfenner/* OSINLCP - to be supported */
32675118Sfenner/* BVCP - to be supported */
32775118Sfenner/* BCP - to be supported */
32875118Sfenner/* IPXCP - to be supported */
329127675Sbms/* MPLSCP - to be supported */
33075118Sfenner
33175118Sfenner/* Auth Algorithms */
33275118Sfenner
33375118Sfenner/* 0-4 Reserved (RFC1994) */
33475118Sfenner#define AUTHALG_CHAPMD5	5	/* RFC1994 */
33575118Sfenner#define AUTHALG_MSCHAP1	128	/* RFC2433 */
33675118Sfenner#define AUTHALG_MSCHAP2	129	/* RFC2795 */
33775118Sfenner
338146778Ssamstruct tok authalg_values[] = {
339146778Ssam        { AUTHALG_CHAPMD5, "MD5" },
340146778Ssam        { AUTHALG_MSCHAP1, "MS-CHAPv1" },
341146778Ssam        { AUTHALG_MSCHAP2, "MS-CHAPv2" },
342146778Ssam	{ 0,		  NULL }
343146778Ssam};
344146778Ssam
34575118Sfenner/* FCS Alternatives - to be supported */
34675118Sfenner
34775118Sfenner/* Multilink Endpoint Discriminator (RFC1717) */
34875118Sfenner#define MEDCLASS_NULL	0	/* Null Class */
34975118Sfenner#define MEDCLASS_LOCAL	1	/* Locally Assigned */
35075118Sfenner#define MEDCLASS_IPV4	2	/* Internet Protocol (IPv4) */
35175118Sfenner#define MEDCLASS_MAC	3	/* IEEE 802.1 global MAC address */
35275118Sfenner#define MEDCLASS_MNB	4	/* PPP Magic Number Block */
35375118Sfenner#define MEDCLASS_PSNDN	5	/* Public Switched Network Director Number */
35475118Sfenner
35575118Sfenner/* PPP LCP Callback */
35675118Sfenner#define CALLBACK_AUTH	0	/* Location determined by user auth */
35775118Sfenner#define CALLBACK_DSTR	1	/* Dialing string */
35875118Sfenner#define CALLBACK_LID	2	/* Location identifier */
35975118Sfenner#define CALLBACK_E164	3	/* E.164 number */
36075118Sfenner#define CALLBACK_X500	4	/* X.500 distinguished name */
36175118Sfenner#define CALLBACK_CBCP	6	/* Location is determined during CBCP nego */
36275118Sfenner
363147904Ssamstruct tok ppp_callback_values[] = {
364147904Ssam        { CALLBACK_AUTH, "UserAuth" },
365147904Ssam        { CALLBACK_DSTR, "DialString" },
366147904Ssam        { CALLBACK_LID, "LocalID" },
367147904Ssam        { CALLBACK_E164, "E.164" },
368147904Ssam        { CALLBACK_X500, "X.500" },
369147904Ssam        { CALLBACK_CBCP, "CBCP" },
370147904Ssam	{ 0,		  NULL }
371147904Ssam};
372147904Ssam
37338638Sthepish/* CHAP */
37438638Sthepish
37538638Sthepish#define CHAP_CHAL	1
37638638Sthepish#define CHAP_RESP	2
37738638Sthepish#define CHAP_SUCC	3
37838638Sthepish#define CHAP_FAIL	4
37938638Sthepish
380146778Ssamstruct tok chapcode_values[] = {
381146778Ssam	{ CHAP_CHAL, "Challenge" },
382146778Ssam	{ CHAP_RESP, "Response" },
383146778Ssam	{ CHAP_SUCC, "Success" },
384146778Ssam	{ CHAP_FAIL, "Fail" },
385146778Ssam        { 0, NULL}
38638638Sthepish};
38738638Sthepish
38838638Sthepish/* PAP */
38938638Sthepish
39038638Sthepish#define PAP_AREQ	1
39138638Sthepish#define PAP_AACK	2
39238638Sthepish#define PAP_ANAK	3
39338638Sthepish
394146778Ssamstruct tok papcode_values[] = {
395146778Ssam        { PAP_AREQ, "Auth-Req" },
396146778Ssam        { PAP_AACK, "Auth-ACK" },
397146778Ssam        { PAP_ANAK, "Auth-NACK" },
398146778Ssam        { 0, NULL }
39938638Sthepish};
40038638Sthepish
40175118Sfenner/* BAP */
40275118Sfenner#define BAP_CALLREQ	1
40375118Sfenner#define BAP_CALLRES	2
40475118Sfenner#define BAP_CBREQ	3
40575118Sfenner#define BAP_CBRES	4
40675118Sfenner#define BAP_LDQREQ	5
40775118Sfenner#define BAP_LDQRES	6
40875118Sfenner#define BAP_CSIND	7
40975118Sfenner#define BAP_CSRES	8
41038638Sthepish
41175118Sfennerstatic void handle_ctrl_proto (u_int proto,const u_char *p, int length);
41275118Sfennerstatic void handle_chap (const u_char *p, int length);
41375118Sfennerstatic void handle_pap (const u_char *p, int length);
41475118Sfennerstatic void handle_bap (const u_char *p, int length);
415146778Ssamstatic void handle_mlppp(const u_char *p, int length);
41675118Sfennerstatic int print_lcp_config_options (const u_char *p, int);
41775118Sfennerstatic int print_ipcp_config_options (const u_char *p, int);
418146778Ssamstatic int print_ip6cp_config_options (const u_char *p, int);
41975118Sfennerstatic int print_ccp_config_options (const u_char *p, int);
42075118Sfennerstatic int print_bacp_config_options (const u_char *p, int);
42175118Sfennerstatic void handle_ppp (u_int proto, const u_char *p, int length);
422146778Ssamstatic void ppp_hdlc(const u_char *p, int length);
42338638Sthepish
42475118Sfenner/* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
42556896Sfennerstatic void
426127675Sbmshandle_ctrl_proto(u_int proto, const u_char *pptr, int length)
42717680Spst{
428127675Sbms	const char *typestr;
42975118Sfenner	u_int code, len;
43075118Sfenner	int (*pfunc)(const u_char *, int);
43138638Sthepish	int x, j;
432127675Sbms        const u_char *tptr;
43317680Spst
434127675Sbms        tptr=pptr;
43532149Spst
436146778Ssam        typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto);
437127675Sbms        printf("%s, ",typestr);
43832149Spst
439127675Sbms	if (length < 4) /* FIXME weak boundary checking */
440127675Sbms		goto trunc;
441127675Sbms	TCHECK2(*tptr, 2);
44275118Sfenner
443127675Sbms	code = *tptr++;
444127675Sbms
445147904Ssam        printf("%s (0x%02x), id %u, length %u",
446127675Sbms               tok2str(cpcodes, "Unknown Opcode",code),
447147904Ssam               code,
448147904Ssam               *tptr++, /* ID */
449147904Ssam               length+2);
45075118Sfenner
451147904Ssam        if (!vflag)
452147904Ssam                return;
453147904Ssam
454147904Ssam	if (length <= 4)
455147904Ssam		return;    /* there may be a NULL confreq etc. */
456147904Ssam
457127675Sbms	TCHECK2(*tptr, 2);
458127675Sbms	len = EXTRACT_16BITS(tptr);
459127675Sbms	tptr += 2;
460127675Sbms
461147904Ssam        printf("\n\tencoded length %u (=Option(s) length %u)",len,len-4);
46275118Sfenner
463147904Ssam        if (vflag>1)
464147904Ssam            print_unknown_data(pptr-2,"\n\t",6);
465147904Ssam
466147904Ssam
46775118Sfenner	switch (code) {
46875118Sfenner	case CPCODES_VEXT:
46975118Sfenner		if (length < 11)
47075118Sfenner			break;
471127675Sbms		TCHECK2(*tptr, 4);
472147904Ssam		printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
473127675Sbms		tptr += 4;
474127675Sbms		TCHECK2(*tptr, 3);
475146778Ssam		printf(" Vendor: %s (%u)",
476146778Ssam                       tok2str(oui_values,"Unknown",EXTRACT_24BITS(tptr)),
477146778Ssam                       EXTRACT_24BITS(tptr));
47875118Sfenner		/* XXX: need to decode Kind and Value(s)? */
47975118Sfenner		break;
48075118Sfenner	case CPCODES_CONF_REQ:
48175118Sfenner	case CPCODES_CONF_ACK:
48275118Sfenner	case CPCODES_CONF_NAK:
48375118Sfenner	case CPCODES_CONF_REJ:
48475118Sfenner		x = len - 4;	/* Code(1), Identifier(1) and Length(2) */
48556896Sfenner		do {
48675118Sfenner			switch (proto) {
48775118Sfenner			case PPP_LCP:
48875118Sfenner				pfunc = print_lcp_config_options;
48956896Sfenner				break;
49075118Sfenner			case PPP_IPCP:
49175118Sfenner				pfunc = print_ipcp_config_options;
49275118Sfenner				break;
493146778Ssam			case PPP_IPV6CP:
494146778Ssam				pfunc = print_ip6cp_config_options;
495146778Ssam				break;
49675118Sfenner			case PPP_CCP:
49775118Sfenner				pfunc = print_ccp_config_options;
49875118Sfenner				break;
49975118Sfenner			case PPP_BACP:
50075118Sfenner				pfunc = print_bacp_config_options;
50175118Sfenner				break;
50275118Sfenner			default:
50375118Sfenner				/*
504146778Ssam				 * No print routine for the options for
505146778Ssam				 * this protocol.
50675118Sfenner				 */
50775118Sfenner				pfunc = NULL;
50875118Sfenner				break;
50975118Sfenner			}
510140744Sbms
511146778Ssam			if (pfunc == NULL) /* catch the above null pointer if unknown CP */
512146778Ssam				break;
513146778Ssam
514127675Sbms			if ((j = (*pfunc)(tptr, len)) == 0)
51575118Sfenner				break;
51656896Sfenner			x -= j;
517127675Sbms			tptr += j;
51856896Sfenner		} while (x > 0);
51956896Sfenner		break;
52032149Spst
52175118Sfenner	case CPCODES_TERM_REQ:
52275118Sfenner	case CPCODES_TERM_ACK:
52375118Sfenner		/* XXX: need to decode Data? */
52456896Sfenner		break;
52575118Sfenner	case CPCODES_CODE_REJ:
52675118Sfenner		/* XXX: need to decode Rejected-Packet? */
52775118Sfenner		break;
52875118Sfenner	case CPCODES_PROT_REJ:
52975118Sfenner		if (length < 6)
53075118Sfenner			break;
531127675Sbms		TCHECK2(*tptr, 2);
532147904Ssam		printf("\n\t  Rejected %s Protocol (0x%04x)",
533127675Sbms		       tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)),
534127675Sbms		       EXTRACT_16BITS(tptr));
535147904Ssam		/* XXX: need to decode Rejected-Information? - hexdump for now */
536147904Ssam                if (len > 6) {
537147904Ssam                        printf("\n\t  Rejected Packet");
538147904Ssam                        print_unknown_data(tptr+2,"\n\t    ",len-2);
539147904Ssam                }
54075118Sfenner		break;
54175118Sfenner	case CPCODES_ECHO_REQ:
54275118Sfenner	case CPCODES_ECHO_RPL:
54375118Sfenner	case CPCODES_DISC_REQ:
544147904Ssam		if (length < 8)
545147904Ssam			break;
546147904Ssam		TCHECK2(*tptr, 4);
547147904Ssam		printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
548147904Ssam		/* XXX: need to decode Data? - hexdump for now */
549147904Ssam                if (len > 8) {
550172686Smlaier                        printf("\n\t  -----trailing data-----");
551172686Smlaier                        TCHECK2(tptr[4], len-8);
552172686Smlaier                        print_unknown_data(tptr+4,"\n\t  ",len-8);
553147904Ssam                }
554147904Ssam		break;
55575118Sfenner	case CPCODES_ID:
55675118Sfenner		if (length < 8)
55775118Sfenner			break;
558127675Sbms		TCHECK2(*tptr, 4);
559147904Ssam		printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
560147904Ssam		/* RFC 1661 says this is intended to be human readable */
561147904Ssam                if (len > 8) {
562147904Ssam                        printf("\n\t  Message\n\t    ");
563147904Ssam                        fn_printn(tptr+4,len-4,snapend);
564147904Ssam                }
56575118Sfenner		break;
56675118Sfenner	case CPCODES_TIME_REM:
56775118Sfenner		if (length < 12)
56875118Sfenner			break;
569127675Sbms		TCHECK2(*tptr, 4);
570147904Ssam		printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
571127675Sbms		TCHECK2(*(tptr + 4), 4);
572127675Sbms		printf(", Seconds-Remaining %us", EXTRACT_32BITS(tptr + 4));
57375118Sfenner		/* XXX: need to decode Message? */
57475118Sfenner		break;
57556896Sfenner	default:
576127675Sbms            /* XXX this is dirty but we do not get the
577127675Sbms             * original pointer passed to the begin
578127675Sbms             * the PPP packet */
579127675Sbms                if (vflag <= 1)
580147904Ssam                    print_unknown_data(pptr-2,"\n\t  ",length+2);
58156896Sfenner		break;
58238638Sthepish	}
583127675Sbms	return;
584127675Sbms
585127675Sbmstrunc:
586127675Sbms	printf("[|%s]", typestr);
58738638Sthepish}
58832149Spst
58938638Sthepish/* LCP config options */
59038638Sthepishstatic int
59175118Sfennerprint_lcp_config_options(const u_char *p, int length)
59238638Sthepish{
59375118Sfenner	int len, opt;
59475118Sfenner
59575118Sfenner	if (length < 2)
59675118Sfenner		return 0;
597127675Sbms	TCHECK2(*p, 2);
59875118Sfenner	len = p[1];
59975118Sfenner	opt = p[0];
60075118Sfenner	if (length < len)
60175118Sfenner		return 0;
602147904Ssam	if (len < 2) {
603147904Ssam		if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
604147904Ssam			printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)", lcpconfopts[opt],opt,len);
605147904Ssam		else
606147904Ssam			printf("\n\tunknown LCP option 0x%02x", opt);
607147904Ssam		return 0;
608147904Ssam	}
60956896Sfenner	if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
610147904Ssam		printf("\n\t  %s Option (0x%02x), length %u: ", lcpconfopts[opt],opt,len);
61175118Sfenner	else {
612147904Ssam		printf("\n\tunknown LCP option 0x%02x", opt);
61375118Sfenner		return len;
61475118Sfenner	}
61538638Sthepish
61656896Sfenner	switch (opt) {
61775118Sfenner	case LCPOPT_VEXT:
61875118Sfenner		if (len >= 6) {
619127675Sbms			TCHECK2(*(p + 2), 3);
620147904Ssam			printf("Vendor: %s (%u)",
621146778Ssam                               tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)),
622146778Ssam                               EXTRACT_24BITS(p+2));
62375118Sfenner#if 0
624127675Sbms			TCHECK(p[5]);
625146778Ssam			printf(", kind: 0x%02x", p[5]);
626146778Ssam			printf(", Value: 0x")
62775118Sfenner			for (i = 0; i < len - 6; i++) {
628127675Sbms				TCHECK(p[6 + i]);
62975118Sfenner				printf("%02x", p[6 + i]);
63075118Sfenner			}
63175118Sfenner#endif
63275118Sfenner		}
63375118Sfenner		break;
63456896Sfenner	case LCPOPT_MRU:
635127675Sbms		if (len == 4) {
636127675Sbms			TCHECK2(*(p + 2), 2);
637147904Ssam			printf("%u", EXTRACT_16BITS(p + 2));
638127675Sbms		}
63956896Sfenner		break;
64075118Sfenner	case LCPOPT_ACCM:
641127675Sbms		if (len == 6) {
642127675Sbms			TCHECK2(*(p + 2), 4);
643147904Ssam			printf("0x%08x", EXTRACT_32BITS(p + 2));
644127675Sbms		}
64575118Sfenner		break;
64656896Sfenner	case LCPOPT_AP:
64756896Sfenner		if (len >= 4) {
648127675Sbms		    TCHECK2(*(p + 2), 2);
649147904Ssam                    printf("%s", tok2str(ppptype2str,"Unknown Auth Proto (0x04x)",EXTRACT_16BITS(p+2)));
650146778Ssam
651127675Sbms		    switch (EXTRACT_16BITS(p+2)) {
652127675Sbms		    case PPP_CHAP:
653127675Sbms		        TCHECK(p[4]);
654146778Ssam                        printf(", %s",tok2str(authalg_values,"Unknown Auth Alg %u",p[4]));
655127675Sbms			break;
656146778Ssam		    case PPP_PAP: /* fall through */
657127675Sbms		    case PPP_EAP:
658127675Sbms		    case PPP_SPAP:
659127675Sbms		    case PPP_SPAP_OLD:
660146778Ssam                        break;
661127675Sbms		    default:
662146778Ssam                        print_unknown_data(p,"\n\t",len);
663127675Sbms		    }
66456896Sfenner		}
66556896Sfenner		break;
66656896Sfenner	case LCPOPT_QP:
66756896Sfenner		if (len >= 4) {
668127675Sbms			TCHECK2(*(p + 2), 2);
669127675Sbms		        if (EXTRACT_16BITS(p+2) == PPP_LQM)
67056896Sfenner				printf(" LQR");
67156896Sfenner			else
67256896Sfenner				printf(" unknown");
67356896Sfenner		}
67456896Sfenner		break;
67556896Sfenner	case LCPOPT_MN:
676127675Sbms		if (len == 6) {
677127675Sbms			TCHECK2(*(p + 2), 4);
678147904Ssam			printf("0x%08x", EXTRACT_32BITS(p + 2));
679127675Sbms		}
68056896Sfenner		break;
68156896Sfenner	case LCPOPT_PFC:
68256896Sfenner		break;
68356896Sfenner	case LCPOPT_ACFC:
68456896Sfenner		break;
68575118Sfenner	case LCPOPT_LD:
686127675Sbms		if (len == 4) {
687127675Sbms			TCHECK2(*(p + 2), 2);
688147904Ssam			printf("0x%04x", EXTRACT_16BITS(p + 2));
689127675Sbms		}
69075118Sfenner		break;
69175118Sfenner	case LCPOPT_CBACK:
69275118Sfenner		if (len < 3)
69375118Sfenner			break;
694127675Sbms		TCHECK(p[2]);
695147904Ssam                printf("Callback Operation %s (%u)",
696147904Ssam                       tok2str(ppp_callback_values,"Unknown",p[2]),
697147904Ssam                       p[2]);
69875118Sfenner		break;
69975118Sfenner	case LCPOPT_MLMRRU:
700127675Sbms		if (len == 4) {
701127675Sbms			TCHECK2(*(p + 2), 2);
702147904Ssam			printf("%u", EXTRACT_16BITS(p + 2));
703127675Sbms		}
70475118Sfenner		break;
70575118Sfenner	case LCPOPT_MLED:
70675118Sfenner		if (len < 3)
70775118Sfenner			break;
708127675Sbms		TCHECK(p[2]);
70975118Sfenner		switch (p[2]) {		/* class */
71075118Sfenner		case MEDCLASS_NULL:
711147904Ssam			printf("Null");
71275118Sfenner			break;
71375118Sfenner		case MEDCLASS_LOCAL:
714147904Ssam			printf("Local"); /* XXX */
71575118Sfenner			break;
71675118Sfenner		case MEDCLASS_IPV4:
71775118Sfenner			if (len != 7)
71875118Sfenner				break;
719127675Sbms			TCHECK2(*(p + 3), 4);
720147904Ssam			printf("IPv4 %s", ipaddr_string(p + 3));
72175118Sfenner			break;
72275118Sfenner		case MEDCLASS_MAC:
72375118Sfenner			if (len != 9)
72475118Sfenner				break;
725127675Sbms			TCHECK(p[8]);
726147904Ssam			printf("MAC %02x:%02x:%02x:%02x:%02x:%02x",
72775118Sfenner			       p[3], p[4], p[5], p[6], p[7], p[8]);
72875118Sfenner			break;
72975118Sfenner		case MEDCLASS_MNB:
730147904Ssam			printf("Magic-Num-Block"); /* XXX */
73175118Sfenner			break;
73275118Sfenner		case MEDCLASS_PSNDN:
733147904Ssam			printf("PSNDN"); /* XXX */
73475118Sfenner			break;
73575118Sfenner		}
73675118Sfenner		break;
73775118Sfenner
73875118Sfenner/* XXX: to be supported */
73975118Sfenner#if 0
74075118Sfenner	case LCPOPT_DEP6:
74175118Sfenner	case LCPOPT_FCSALT:
74275118Sfenner	case LCPOPT_SDP:
74375118Sfenner	case LCPOPT_NUMMODE:
74475118Sfenner	case LCPOPT_DEP12:
74575118Sfenner	case LCPOPT_DEP14:
74675118Sfenner	case LCPOPT_DEP15:
74775118Sfenner	case LCPOPT_DEP16:
748146778Ssam        case LCPOPT_MLSSNHF:
74975118Sfenner	case LCPOPT_PROP:
75075118Sfenner	case LCPOPT_DCEID:
75175118Sfenner	case LCPOPT_MPP:
75275118Sfenner	case LCPOPT_LCPAOPT:
75375118Sfenner	case LCPOPT_COBS:
75475118Sfenner	case LCPOPT_PE:
75575118Sfenner	case LCPOPT_MLHF:
75675118Sfenner	case LCPOPT_I18N:
75775118Sfenner	case LCPOPT_SDLOS:
75875118Sfenner	case LCPOPT_PPPMUX:
75975118Sfenner		break;
76075118Sfenner#endif
761147904Ssam        default:
762147904Ssam                if(vflag<2)
763147904Ssam                        print_unknown_data(&p[2],"\n\t    ",len-2);
764147904Ssam                break;
76538638Sthepish	}
766147904Ssam
767147904Ssam        if (vflag>1)
768147904Ssam                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
769147904Ssam
77056896Sfenner	return len;
771127675Sbms
772127675Sbmstrunc:
773127675Sbms	printf("[|lcp]");
774127675Sbms	return 0;
77538638Sthepish}
77638638Sthepish
777146778Ssam/* ML-PPP*/
778146778Ssamstruct tok ppp_ml_flag_values[] = {
779146778Ssam    { 0x80, "begin" },
780146778Ssam    { 0x40, "end" },
781146778Ssam    { 0, NULL }
782146778Ssam};
783146778Ssam
784146778Ssamstatic void
785146778Ssamhandle_mlppp(const u_char *p, int length) {
786146778Ssam
787146778Ssam    if (!eflag)
788146778Ssam        printf("MLPPP, ");
789146778Ssam
790146778Ssam    printf("seq 0x%03x, Flags [%s], length %u",
791146778Ssam           (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */
792146778Ssam           bittok2str(ppp_ml_flag_values, "none", *p & 0xc0),
793146778Ssam           length);
794146778Ssam
795146778Ssam    return;
796146778Ssam}
797146778Ssam
79838638Sthepish/* CHAP */
79956896Sfennerstatic void
80038638Sthepishhandle_chap(const u_char *p, int length)
80138638Sthepish{
80275118Sfenner	u_int code, len;
80375118Sfenner	int val_size, name_size, msg_size;
80475118Sfenner	const u_char *p0;
80575118Sfenner	int i;
80638638Sthepish
80775118Sfenner	p0 = p;
80875118Sfenner	if (length < 1) {
80975118Sfenner		printf("[|chap]");
81075118Sfenner		return;
81175118Sfenner	} else if (length < 4) {
812127675Sbms		TCHECK(*p);
81375118Sfenner		printf("[|chap 0x%02x]", *p);
81475118Sfenner		return;
81575118Sfenner	}
81638638Sthepish
817127675Sbms	TCHECK(*p);
81875118Sfenner	code = *p;
819146778Ssam        printf("CHAP, %s (0x%02x)",
820146778Ssam               tok2str(chapcode_values,"unknown",code),
821146778Ssam               code);
82275118Sfenner	p++;
82332149Spst
824127675Sbms	TCHECK(*p);
825146778Ssam	printf(", id %u", *p);		/* ID */
82675118Sfenner	p++;
82775118Sfenner
828127675Sbms	TCHECK2(*p, 2);
82975118Sfenner	len = EXTRACT_16BITS(p);
83075118Sfenner	p += 2;
83175118Sfenner
83275118Sfenner	/*
83375118Sfenner	 * Note that this is a generic CHAP decoding routine. Since we
83475118Sfenner	 * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
83575118Sfenner	 * MS-CHAPv2) is used at this point, we can't decode packet
83675118Sfenner	 * specifically to each algorithms. Instead, we simply decode
83775118Sfenner	 * the GCD (Gratest Common Denominator) for all algorithms.
83875118Sfenner	 */
83975118Sfenner	switch (code) {
84056896Sfenner	case CHAP_CHAL:
84156896Sfenner	case CHAP_RESP:
84275118Sfenner		if (length - (p - p0) < 1)
84375118Sfenner			return;
844127675Sbms		TCHECK(*p);
84575118Sfenner		val_size = *p;		/* value size */
84675118Sfenner		p++;
84775118Sfenner		if (length - (p - p0) < val_size)
84875118Sfenner			return;
849127675Sbms		printf(", Value ");
850127675Sbms		for (i = 0; i < val_size; i++) {
851127675Sbms			TCHECK(*p);
85275118Sfenner			printf("%02x", *p++);
853127675Sbms		}
85475118Sfenner		name_size = len - (p - p0);
855127675Sbms		printf(", Name ");
856127675Sbms		for (i = 0; i < name_size; i++) {
857127675Sbms			TCHECK(*p);
85875118Sfenner			safeputchar(*p++);
859127675Sbms		}
86056896Sfenner		break;
86175118Sfenner	case CHAP_SUCC:
86275118Sfenner	case CHAP_FAIL:
86375118Sfenner		msg_size = len - (p - p0);
864127675Sbms		printf(", Msg ");
865127675Sbms		for (i = 0; i< msg_size; i++) {
866127675Sbms			TCHECK(*p);
86775118Sfenner			safeputchar(*p++);
868127675Sbms		}
86975118Sfenner		break;
87038638Sthepish	}
871127675Sbms	return;
872127675Sbms
873127675Sbmstrunc:
874127675Sbms	printf("[|chap]");
87538638Sthepish}
87638638Sthepish
87775118Sfenner/* PAP (see RFC 1334) */
87856896Sfennerstatic void
87938638Sthepishhandle_pap(const u_char *p, int length)
88038638Sthepish{
88175118Sfenner	u_int code, len;
88275118Sfenner	int peerid_len, passwd_len, msg_len;
88375118Sfenner	const u_char *p0;
88475118Sfenner	int i;
88538638Sthepish
88675118Sfenner	p0 = p;
88775118Sfenner	if (length < 1) {
88875118Sfenner		printf("[|pap]");
88975118Sfenner		return;
89075118Sfenner	} else if (length < 4) {
891127675Sbms		TCHECK(*p);
89275118Sfenner		printf("[|pap 0x%02x]", *p);
89375118Sfenner		return;
89475118Sfenner	}
89538638Sthepish
896127675Sbms	TCHECK(*p);
89775118Sfenner	code = *p;
898146778Ssam        printf("PAP, %s (0x%02x)",
899146778Ssam               tok2str(papcode_values,"unknown",code),
900146778Ssam               code);
90175118Sfenner	p++;
90238638Sthepish
903127675Sbms	TCHECK(*p);
904146778Ssam	printf(", id %u", *p);		/* ID */
90575118Sfenner	p++;
90675118Sfenner
907127675Sbms	TCHECK2(*p, 2);
90875118Sfenner	len = EXTRACT_16BITS(p);
90975118Sfenner	p += 2;
91075118Sfenner
911147904Ssam	if ((int)len > length) {
912147904Ssam		printf(", length %u > packet size", len);
913147904Ssam		return;
914147904Ssam	}
915147904Ssam	length = len;
916147904Ssam	if (length < (p - p0)) {
917147904Ssam		printf(", length %u < PAP header length", length);
918147904Ssam		return;
919147904Ssam	}
920147904Ssam
92175118Sfenner	switch (code) {
92256896Sfenner	case PAP_AREQ:
92375118Sfenner		if (length - (p - p0) < 1)
92475118Sfenner			return;
925127675Sbms		TCHECK(*p);
92675118Sfenner		peerid_len = *p;	/* Peer-ID Length */
92775118Sfenner		p++;
92875118Sfenner		if (length - (p - p0) < peerid_len)
92975118Sfenner			return;
930127675Sbms		printf(", Peer ");
931127675Sbms		for (i = 0; i < peerid_len; i++) {
932127675Sbms			TCHECK(*p);
93375118Sfenner			safeputchar(*p++);
934127675Sbms		}
93575118Sfenner
93675118Sfenner		if (length - (p - p0) < 1)
93775118Sfenner			return;
938127675Sbms		TCHECK(*p);
93975118Sfenner		passwd_len = *p;	/* Password Length */
94075118Sfenner		p++;
94175118Sfenner		if (length - (p - p0) < passwd_len)
94275118Sfenner			return;
943127675Sbms		printf(", Name ");
944127675Sbms		for (i = 0; i < passwd_len; i++) {
945127675Sbms			TCHECK(*p);
94675118Sfenner			safeputchar(*p++);
947127675Sbms		}
94856896Sfenner		break;
94956896Sfenner	case PAP_AACK:
95056896Sfenner	case PAP_ANAK:
95175118Sfenner		if (length - (p - p0) < 1)
95275118Sfenner			return;
953127675Sbms		TCHECK(*p);
95475118Sfenner		msg_len = *p;		/* Msg-Length */
95575118Sfenner		p++;
95675118Sfenner		if (length - (p - p0) < msg_len)
95775118Sfenner			return;
958127675Sbms		printf(", Msg ");
959127675Sbms		for (i = 0; i< msg_len; i++) {
960127675Sbms			TCHECK(*p);
96175118Sfenner			safeputchar(*p++);
962127675Sbms		}
96356896Sfenner		break;
96438638Sthepish	}
96575118Sfenner	return;
966127675Sbms
967127675Sbmstrunc:
968127675Sbms	printf("[|pap]");
96938638Sthepish}
97038638Sthepish
97175118Sfenner/* BAP */
97256896Sfennerstatic void
973127675Sbmshandle_bap(const u_char *p _U_, int length _U_)
97438638Sthepish{
97575118Sfenner	/* XXX: to be supported!! */
97675118Sfenner}
97775118Sfenner
97875118Sfenner
97975118Sfenner/* IPCP config options */
98075118Sfennerstatic int
98175118Sfennerprint_ipcp_config_options(const u_char *p, int length)
98275118Sfenner{
98375118Sfenner	int len, opt;
984172686Smlaier        u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen;
98575118Sfenner
98675118Sfenner	if (length < 2)
98775118Sfenner		return 0;
988127675Sbms	TCHECK2(*p, 2);
98975118Sfenner	len = p[1];
99075118Sfenner	opt = p[0];
99175118Sfenner	if (length < len)
99275118Sfenner		return 0;
993147904Ssam	if (len < 2) {
994147904Ssam		printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
995147904Ssam		       tok2str(ipcpopt_values,"unknown",opt),
996147904Ssam		       opt,
997147904Ssam        	       len);
998147904Ssam		return 0;
999147904Ssam	}
1000146778Ssam
1001147904Ssam	printf("\n\t  %s Option (0x%02x), length %u: ",
1002146778Ssam	       tok2str(ipcpopt_values,"unknown",opt),
1003147904Ssam	       opt,
1004147904Ssam               len);
1005146778Ssam
100675118Sfenner	switch (opt) {
100775118Sfenner	case IPCPOPT_2ADDR:		/* deprecated */
100875118Sfenner		if (len != 10)
100975118Sfenner			goto invlen;
1010127675Sbms		TCHECK2(*(p + 6), 4);
1011146778Ssam		printf("src %s, dst %s",
101275118Sfenner		       ipaddr_string(p + 2),
101375118Sfenner		       ipaddr_string(p + 6));
101456896Sfenner		break;
101575118Sfenner	case IPCPOPT_IPCOMP:
101675118Sfenner		if (len < 4)
101775118Sfenner			goto invlen;
1018127675Sbms		TCHECK2(*(p + 2), 2);
1019172686Smlaier                compproto = EXTRACT_16BITS(p+2);
1020172686Smlaier
1021172686Smlaier                printf("%s (0x%02x):",
1022172686Smlaier                       tok2str(ipcpopt_compproto_values,"Unknown",compproto),
1023172686Smlaier                       compproto);
1024172686Smlaier
1025172686Smlaier		switch (compproto) {
1026172686Smlaier                case PPP_VJC:
102775118Sfenner			/* XXX: VJ-Comp parameters should be decoded */
1028172686Smlaier                        break;
1029172686Smlaier                case IPCPOPT_IPCOMP_HDRCOMP:
1030172686Smlaier                        if (len < IPCPOPT_IPCOMP_MINLEN)
1031172686Smlaier                                goto invlen;
1032172686Smlaier
1033172686Smlaier                        TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN);
1034172686Smlaier                        printf("\n\t    TCP Space %u, non-TCP Space %u" \
1035172686Smlaier                               ", maxPeriod %u, maxTime %u, maxHdr %u",
1036172686Smlaier                               EXTRACT_16BITS(p+4),
1037172686Smlaier                               EXTRACT_16BITS(p+6),
1038172686Smlaier                               EXTRACT_16BITS(p+8),
1039172686Smlaier                               EXTRACT_16BITS(p+10),
1040172686Smlaier                               EXTRACT_16BITS(p+12));
1041172686Smlaier
1042172686Smlaier                        /* suboptions present ? */
1043172686Smlaier                        if (len > IPCPOPT_IPCOMP_MINLEN) {
1044172686Smlaier                                ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN;
1045172686Smlaier                                p += IPCPOPT_IPCOMP_MINLEN;
1046172686Smlaier
1047172686Smlaier                                printf("\n\t      Suboptions, length %u", ipcomp_subopttotallen);
1048172686Smlaier
1049172686Smlaier                                while (ipcomp_subopttotallen >= 2) {
1050172686Smlaier                                        TCHECK2(*p, 2);
1051172686Smlaier                                        ipcomp_subopt = *p;
1052172686Smlaier                                        ipcomp_suboptlen = *(p+1);
1053172686Smlaier
1054172686Smlaier                                        /* sanity check */
1055172686Smlaier                                        if (ipcomp_subopt == 0 ||
1056172686Smlaier                                            ipcomp_suboptlen == 0 )
1057172686Smlaier                                                break;
1058172686Smlaier
1059172686Smlaier                                        /* XXX: just display the suboptions for now */
1060172686Smlaier                                        printf("\n\t\t%s Suboption #%u, length %u",
1061172686Smlaier                                               tok2str(ipcpopt_compproto_subopt_values,
1062172686Smlaier                                                       "Unknown",
1063172686Smlaier                                                       ipcomp_subopt),
1064172686Smlaier                                               ipcomp_subopt,
1065172686Smlaier                                               ipcomp_suboptlen);
1066172686Smlaier
1067172686Smlaier                                        ipcomp_subopttotallen -= ipcomp_suboptlen;
1068172686Smlaier                                        p += ipcomp_suboptlen;
1069172686Smlaier                                }
1070172686Smlaier                        }
1071172686Smlaier                        break;
1072172686Smlaier                default:
1073172686Smlaier                        break;
1074172686Smlaier		}
107556896Sfenner		break;
1076146778Ssam
1077146778Ssam	case IPCPOPT_ADDR:     /* those options share the same format - fall through */
107875118Sfenner	case IPCPOPT_MOBILE4:
107975118Sfenner	case IPCPOPT_PRIDNS:
108075118Sfenner	case IPCPOPT_PRINBNS:
108175118Sfenner	case IPCPOPT_SECDNS:
108275118Sfenner	case IPCPOPT_SECNBNS:
108375118Sfenner		if (len != 6)
108475118Sfenner			goto invlen;
1085127675Sbms		TCHECK2(*(p + 2), 4);
1086146778Ssam		printf("%s", ipaddr_string(p + 2));
108775118Sfenner		break;
108875118Sfenner	default:
1089147904Ssam                if(vflag<2)
1090147904Ssam                        print_unknown_data(&p[2],"\n\t    ",len-2);
109175118Sfenner		break;
109275118Sfenner	}
1093147904Ssam        if (vflag>1)
1094147904Ssam                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
109575118Sfenner	return len;
109638638Sthepish
109775118Sfennerinvlen:
109875118Sfenner	printf(", invalid-length-%d", opt);
109975118Sfenner	return 0;
1100127675Sbms
1101127675Sbmstrunc:
1102127675Sbms	printf("[|ipcp]");
1103127675Sbms	return 0;
110475118Sfenner}
110575118Sfenner
1106146778Ssam/* IP6CP config options */
1107146778Ssamstatic int
1108146778Ssamprint_ip6cp_config_options(const u_char *p, int length)
1109146778Ssam{
1110146778Ssam	int len, opt;
1111146778Ssam
1112146778Ssam	if (length < 2)
1113146778Ssam		return 0;
1114146778Ssam	TCHECK2(*p, 2);
1115146778Ssam	len = p[1];
1116146778Ssam	opt = p[0];
1117146778Ssam	if (length < len)
1118146778Ssam		return 0;
1119147904Ssam	if (len < 2) {
1120147904Ssam		printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
1121147904Ssam		       tok2str(ip6cpopt_values,"unknown",opt),
1122147904Ssam		       opt,
1123147904Ssam	               len);
1124147904Ssam	        return 0;
1125147904Ssam	}
1126146778Ssam
1127147904Ssam	printf("\n\t  %s Option (0x%02x), length %u: ",
1128146778Ssam	       tok2str(ip6cpopt_values,"unknown",opt),
1129147904Ssam	       opt,
1130147904Ssam               len);
1131146778Ssam
1132146778Ssam	switch (opt) {
1133146778Ssam	case IP6CP_IFID:
1134146778Ssam		if (len != 10)
1135146778Ssam			goto invlen;
1136146778Ssam		TCHECK2(*(p + 2), 8);
1137146778Ssam		printf("%04x:%04x:%04x:%04x",
1138146778Ssam		       EXTRACT_16BITS(p + 2),
1139146778Ssam		       EXTRACT_16BITS(p + 4),
1140146778Ssam		       EXTRACT_16BITS(p + 6),
1141146778Ssam		       EXTRACT_16BITS(p + 8));
1142146778Ssam		break;
1143146778Ssam	default:
1144147904Ssam                if(vflag<2)
1145147904Ssam                        print_unknown_data(&p[2],"\n\t    ",len-2);
1146146778Ssam		break;
1147146778Ssam	}
1148147904Ssam        if (vflag>1)
1149147904Ssam                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1150147904Ssam
1151146778Ssam	return len;
1152146778Ssam
1153146778Ssaminvlen:
1154146778Ssam	printf(", invalid-length-%d", opt);
1155146778Ssam	return 0;
1156146778Ssam
1157146778Ssamtrunc:
1158146778Ssam	printf("[|ip6cp]");
1159146778Ssam	return 0;
1160146778Ssam}
1161146778Ssam
1162146778Ssam
116375118Sfenner/* CCP config options */
116475118Sfennerstatic int
116575118Sfennerprint_ccp_config_options(const u_char *p, int length)
116675118Sfenner{
116775118Sfenner	int len, opt;
116875118Sfenner
116975118Sfenner	if (length < 2)
117075118Sfenner		return 0;
1171127675Sbms	TCHECK2(*p, 2);
117275118Sfenner	len = p[1];
117375118Sfenner	opt = p[0];
117475118Sfenner	if (length < len)
117575118Sfenner		return 0;
1176147904Ssam	if (len < 2) {
1177147904Ssam	        printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
1178147904Ssam        	       tok2str(ccpconfopts_values, "Unknown", opt),
1179147904Ssam	               opt,
1180147904Ssam        	       len);
1181147904Ssam        	return 0;
1182147904Ssam        }
1183147904Ssam
1184147904Ssam        printf("\n\t  %s Option (0x%02x), length %u:",
1185147904Ssam               tok2str(ccpconfopts_values, "Unknown", opt),
1186147904Ssam               opt,
1187147904Ssam               len);
1188147904Ssam
118975118Sfenner	switch (opt) {
1190147904Ssam                /* fall through --> default: nothing supported yet */
119175118Sfenner	case CCPOPT_OUI:
119275118Sfenner	case CCPOPT_PRED1:
119375118Sfenner	case CCPOPT_PRED2:
119475118Sfenner	case CCPOPT_PJUMP:
119575118Sfenner	case CCPOPT_HPPPC:
119675118Sfenner	case CCPOPT_STACLZS:
119775118Sfenner	case CCPOPT_MPPC:
119875118Sfenner	case CCPOPT_GFZA:
119975118Sfenner	case CCPOPT_V42BIS:
120075118Sfenner	case CCPOPT_BSDCOMP:
120175118Sfenner	case CCPOPT_LZSDCP:
120275118Sfenner	case CCPOPT_MVRCA:
120375118Sfenner	case CCPOPT_DEC:
120475118Sfenner	case CCPOPT_DEFLATE:
120575118Sfenner	case CCPOPT_RESV:
120675118Sfenner	default:
1207147904Ssam                if(vflag<2)
1208147904Ssam                        print_unknown_data(&p[2],"\n\t    ",len-2);
120975118Sfenner		break;
121038638Sthepish	}
1211147904Ssam        if (vflag>1)
1212147904Ssam                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1213147904Ssam
121475118Sfenner	return len;
1215127675Sbms
1216127675Sbmstrunc:
1217127675Sbms	printf("[|ccp]");
1218127675Sbms	return 0;
121938638Sthepish}
122075118Sfenner
122175118Sfenner/* BACP config options */
122275118Sfennerstatic int
122375118Sfennerprint_bacp_config_options(const u_char *p, int length)
122475118Sfenner{
122575118Sfenner	int len, opt;
122675118Sfenner
122775118Sfenner	if (length < 2)
122875118Sfenner		return 0;
1229127675Sbms	TCHECK2(*p, 2);
123075118Sfenner	len = p[1];
123175118Sfenner	opt = p[0];
123275118Sfenner	if (length < len)
123375118Sfenner		return 0;
1234147904Ssam	if (len < 2) {
1235147904Ssam	        printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
1236147904Ssam        	       tok2str(bacconfopts_values, "Unknown", opt),
1237147904Ssam	               opt,
1238147904Ssam        	       len);
1239147904Ssam        	return 0;
1240147904Ssam        }
1241147904Ssam
1242147904Ssam        printf("\n\t  %s Option (0x%02x), length %u:",
1243147904Ssam               tok2str(bacconfopts_values, "Unknown", opt),
1244147904Ssam               opt,
1245147904Ssam               len);
1246147904Ssam
1247147904Ssam	switch (opt) {
1248147904Ssam	case BACPOPT_FPEER:
1249127675Sbms		TCHECK2(*(p + 2), 4);
1250127675Sbms		printf(", Magic-Num 0x%08x", EXTRACT_32BITS(p + 2));
1251147904Ssam                break;
1252147904Ssam	default:
1253147904Ssam                if(vflag<2)
1254147904Ssam                        print_unknown_data(&p[2],"\n\t    ",len-2);
1255147904Ssam		break;
125675118Sfenner	}
1257147904Ssam        if (vflag>1)
1258147904Ssam                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1259147904Ssam
126075118Sfenner	return len;
1261127675Sbms
1262127675Sbmstrunc:
1263127675Sbms	printf("[|bacp]");
1264127675Sbms	return 0;
126575118Sfenner}
126675118Sfenner
126775118Sfenner
1268146778Ssamstatic void
1269146778Ssamppp_hdlc(const u_char *p, int length)
1270146778Ssam{
1271146778Ssam	u_char *b, *s, *t, c;
1272146778Ssam	int i, proto;
1273146778Ssam	const void *se;
1274146778Ssam
1275146778Ssam	b = (u_int8_t *)malloc(length);
1276146778Ssam	if (b == NULL)
1277146778Ssam		return;
1278146778Ssam
1279146778Ssam	/*
1280146778Ssam	 * Unescape all the data into a temporary, private, buffer.
1281146778Ssam	 * Do this so that we dont overwrite the original packet
1282146778Ssam	 * contents.
1283146778Ssam	 */
1284146778Ssam	for (s = (u_char *)p, t = b, i = length; i > 0; i--) {
1285146778Ssam		c = *s++;
1286146778Ssam		if (c == 0x7d) {
1287146778Ssam			if (i > 1) {
1288146778Ssam				i--;
1289146778Ssam				c = *s++ ^ 0x20;
1290146778Ssam			} else
1291146778Ssam				continue;
1292146778Ssam		}
1293146778Ssam		*t++ = c;
1294146778Ssam	}
1295146778Ssam
1296146778Ssam	se = snapend;
1297146778Ssam	snapend = t;
1298146778Ssam
1299146778Ssam        /* now lets guess about the payload codepoint format */
1300146778Ssam        proto = *b; /* start with a one-octet codepoint guess */
1301146778Ssam
1302146778Ssam        switch (proto) {
1303146778Ssam        case PPP_IP:
1304146778Ssam		ip_print(gndo, b+1, t - b - 1);
1305146778Ssam		goto cleanup;
1306146778Ssam#ifdef INET6
1307146778Ssam        case PPP_IPV6:
1308235530Sdelphij		ip6_print(gndo, b+1, t - b - 1);
1309235530Sdelphij		goto cleanup;
1310146778Ssam#endif
1311146778Ssam        default: /* no luck - try next guess */
1312235530Sdelphij		break;
1313146778Ssam        }
1314146778Ssam
1315146778Ssam        proto = EXTRACT_16BITS(b); /* next guess - load two octets */
1316146778Ssam
1317146778Ssam        switch (proto) {
1318146778Ssam        case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */
1319146778Ssam            proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */
1320146778Ssam            handle_ppp(proto, b+4, t - b - 4);
1321146778Ssam            break;
1322146778Ssam        default: /* last guess - proto must be a PPP proto-id */
1323146778Ssam            handle_ppp(proto, b+2, t - b - 2);
1324146778Ssam            break;
1325146778Ssam        }
1326146778Ssam
1327146778Ssamcleanup:
1328146778Ssam        snapend = se;
1329146778Ssam	free(b);
1330146778Ssam        return;
1331146778Ssam}
1332146778Ssam
1333146778Ssam
133475118Sfenner/* PPP */
133575118Sfennerstatic void
133675118Sfennerhandle_ppp(u_int proto, const u_char *p, int length)
133775118Sfenner{
1338146778Ssam        if ((proto & 0xff00) == 0x7e00) {/* is this an escape code ? */
1339146778Ssam            ppp_hdlc(p-1, length);
1340146778Ssam            return;
1341146778Ssam        }
1342146778Ssam
134375118Sfenner	switch (proto) {
1344146778Ssam	case PPP_LCP: /* fall through */
134575118Sfenner	case PPP_IPCP:
1346127675Sbms	case PPP_OSICP:
1347127675Sbms	case PPP_MPLSCP:
1348127675Sbms	case PPP_IPV6CP:
134975118Sfenner	case PPP_CCP:
135075118Sfenner	case PPP_BACP:
135175118Sfenner		handle_ctrl_proto(proto, p, length);
135275118Sfenner		break;
1353146778Ssam        case PPP_ML:
1354146778Ssam                handle_mlppp(p, length);
1355146778Ssam                break;
135675118Sfenner	case PPP_CHAP:
135775118Sfenner		handle_chap(p, length);
135875118Sfenner		break;
135975118Sfenner	case PPP_PAP:
136075118Sfenner		handle_pap(p, length);
136175118Sfenner		break;
136275118Sfenner	case PPP_BAP:		/* XXX: not yet completed */
136375118Sfenner		handle_bap(p, length);
136475118Sfenner		break;
136575118Sfenner	case ETHERTYPE_IP:	/*XXX*/
1366146778Ssam        case PPP_VJNC:
136775118Sfenner	case PPP_IP:
1368146778Ssam		ip_print(gndo, p, length);
136975118Sfenner		break;
137075118Sfenner#ifdef INET6
137175118Sfenner	case ETHERTYPE_IPV6:	/*XXX*/
137275118Sfenner	case PPP_IPV6:
1373235530Sdelphij		ip6_print(gndo, p, length);
137475118Sfenner		break;
137575118Sfenner#endif
137675118Sfenner	case ETHERTYPE_IPX:	/*XXX*/
137775118Sfenner	case PPP_IPX:
137875118Sfenner		ipx_print(p, length);
137975118Sfenner		break;
138098527Sfenner	case PPP_OSI:
1381127675Sbms	        isoclns_print(p, length, length);
138298527Sfenner	        break;
1383127675Sbms	case PPP_MPLS_UCAST:
1384127675Sbms	case PPP_MPLS_MCAST:
1385127675Sbms		mpls_print(p, length);
1386127675Sbms		break;
1387146778Ssam	case PPP_COMP:
1388146778Ssam		printf("compressed PPP data");
1389146778Ssam		break;
139098527Sfenner	default:
1391146778Ssam		printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
1392146778Ssam		print_unknown_data(p,"\n\t",length);
1393146778Ssam		break;
139475118Sfenner	}
139575118Sfenner}
139675118Sfenner
139756896Sfenner/* Standard PPP printer */
1398127675Sbmsu_int
139975118Sfennerppp_print(register const u_char *p, u_int length)
140075118Sfenner{
1401146778Ssam	u_int proto,ppp_header;
1402127675Sbms        u_int olen = length; /* _o_riginal length */
1403127675Sbms	u_int hdr_len = 0;
140475118Sfenner
140575118Sfenner	/*
140675118Sfenner	 * Here, we assume that p points to the Address and Control
140775118Sfenner	 * field (if they present).
140875118Sfenner	 */
140975118Sfenner	if (length < 2)
141075118Sfenner		goto trunc;
1411127675Sbms	TCHECK2(*p, 2);
1412146778Ssam        ppp_header = EXTRACT_16BITS(p);
141375118Sfenner
1414146778Ssam        switch(ppp_header) {
1415146778Ssam        case (PPP_WITHDIRECTION_IN  << 8 | PPP_CONTROL):
1416146778Ssam            if (eflag) printf("In  ");
1417146778Ssam            p += 2;
1418146778Ssam            length -= 2;
1419146778Ssam            hdr_len += 2;
1420146778Ssam            break;
1421146778Ssam        case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL):
1422146778Ssam            if (eflag) printf("Out ");
1423146778Ssam            p += 2;
1424146778Ssam            length -= 2;
1425146778Ssam            hdr_len += 2;
1426146778Ssam            break;
1427146778Ssam        case (PPP_ADDRESS << 8 | PPP_CONTROL):
1428146778Ssam            p += 2;			/* ACFC not used */
1429146778Ssam            length -= 2;
1430146778Ssam            hdr_len += 2;
1431146778Ssam            break;
1432146778Ssam
1433146778Ssam        default:
1434146778Ssam            break;
1435146778Ssam        }
1436146778Ssam
143775118Sfenner	if (length < 2)
143875118Sfenner		goto trunc;
1439127675Sbms	TCHECK(*p);
144075118Sfenner	if (*p % 2) {
144175118Sfenner		proto = *p;		/* PFC is used */
144275118Sfenner		p++;
144375118Sfenner		length--;
1444127675Sbms		hdr_len++;
144575118Sfenner	} else {
1446127675Sbms		TCHECK2(*p, 2);
144775118Sfenner		proto = EXTRACT_16BITS(p);
144875118Sfenner		p += 2;
144975118Sfenner		length -= 2;
1450127675Sbms		hdr_len += 2;
145175118Sfenner	}
145275118Sfenner
1453127675Sbms        if (eflag)
1454146778Ssam            printf("%s (0x%04x), length %u: ",
1455127675Sbms                   tok2str(ppptype2str, "unknown", proto),
1456127675Sbms                   proto,
1457127675Sbms                   olen);
145875118Sfenner
145975118Sfenner	handle_ppp(proto, p, length);
1460127675Sbms	return (hdr_len);
146175118Sfennertrunc:
146275118Sfenner	printf("[|ppp]");
1463127675Sbms	return (0);
146475118Sfenner}
146575118Sfenner
146675118Sfenner
146775118Sfenner/* PPP I/F printer */
1468127675Sbmsu_int
1469127675Sbmsppp_if_print(const struct pcap_pkthdr *h, register const u_char *p)
147038638Sthepish{
147138638Sthepish	register u_int length = h->len;
147238638Sthepish	register u_int caplen = h->caplen;
147338638Sthepish
147417680Spst	if (caplen < PPP_HDRLEN) {
147575118Sfenner		printf("[|ppp]");
1476127675Sbms		return (caplen);
147717680Spst	}
147817680Spst
147975118Sfenner#if 0
148075118Sfenner	/*
148175118Sfenner	 * XXX: seems to assume that there are 2 octets prepended to an
148275118Sfenner	 * actual PPP frame. The 1st octet looks like Input/Output flag
148375118Sfenner	 * while 2nd octet is unknown, at least to me
148475118Sfenner	 * (mshindo@mshindo.net).
148575118Sfenner	 *
148675118Sfenner	 * That was what the original tcpdump code did.
148775118Sfenner	 *
148875118Sfenner	 * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
148975118Sfenner	 * packets and 0 for inbound packets - but only if the
149075118Sfenner	 * protocol field has the 0x8000 bit set (i.e., it's a network
149175118Sfenner	 * control protocol); it does so before running the packet through
149275118Sfenner	 * "bpf_filter" to see if it should be discarded, and to see
149375118Sfenner	 * if we should update the time we sent the most recent packet...
149475118Sfenner	 *
149575118Sfenner	 * ...but it puts the original address field back after doing
149675118Sfenner	 * so.
149775118Sfenner	 *
149875118Sfenner	 * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
149975118Sfenner	 *
150075118Sfenner	 * I don't know if any PPP implementation handed up to a BPF
150175118Sfenner	 * device packets with the first octet being 1 for outbound and
150275118Sfenner	 * 0 for inbound packets, so I (guy@alum.mit.edu) don't know
150375118Sfenner	 * whether that ever needs to be checked or not.
150475118Sfenner	 *
150575118Sfenner	 * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
150675118Sfenner	 * and its tcpdump appears to assume that the frame always
150775118Sfenner	 * begins with an address field and a control field, and that
150875118Sfenner	 * the address field might be 0x0f or 0x8f, for Cisco
150975118Sfenner	 * point-to-point with HDLC framing as per section 4.3.1 of RFC
151075118Sfenner	 * 1547, as well as 0xff, for PPP in HDLC-like framing as per
151175118Sfenner	 * RFC 1662.
151275118Sfenner	 *
151375118Sfenner	 * (Is the Cisco framing in question what DLT_C_HDLC, in
151475118Sfenner	 * BSD/OS, is?)
151575118Sfenner	 */
151675118Sfenner	if (eflag)
151775118Sfenner		printf("%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]);
151875118Sfenner#endif
151975118Sfenner
152075118Sfenner	ppp_print(p, length);
152175118Sfenner
1522127675Sbms	return (0);
152353146Sbrian}
152453146Sbrian
152553146Sbrian/*
152675118Sfenner * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
152775118Sfenner * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
152875118Sfenner * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
152975118Sfenner * discard them *if* those are the first two octets, and parse the remaining
153075118Sfenner * packet as a PPP packet, as "ppp_print()" does).
153175118Sfenner *
153275118Sfenner * This handles, for example, DLT_PPP_SERIAL in NetBSD.
153353146Sbrian */
1534127675Sbmsu_int
1535127675Sbmsppp_hdlc_if_print(const struct pcap_pkthdr *h, register const u_char *p)
153653146Sbrian{
153775118Sfenner	register u_int length = h->len;
153875118Sfenner	register u_int caplen = h->caplen;
153975118Sfenner	u_int proto;
1540127675Sbms	u_int hdrlen = 0;
154117680Spst
154275118Sfenner	if (caplen < 2) {
154375118Sfenner		printf("[|ppp]");
1544127675Sbms		return (caplen);
154575118Sfenner	}
154617680Spst
154775118Sfenner	switch (p[0]) {
154875118Sfenner
154975118Sfenner	case PPP_ADDRESS:
155075118Sfenner		if (caplen < 4) {
155175118Sfenner			printf("[|ppp]");
1552127675Sbms			return (caplen);
155375118Sfenner		}
155475118Sfenner
155575118Sfenner		if (eflag)
155675118Sfenner			printf("%02x %02x %d ", p[0], p[1], length);
155775118Sfenner		p += 2;
155875118Sfenner		length -= 2;
1559127675Sbms		hdrlen += 2;
156075118Sfenner
156175118Sfenner		proto = EXTRACT_16BITS(p);
156275118Sfenner		p += 2;
156375118Sfenner		length -= 2;
1564127675Sbms		hdrlen += 2;
1565127675Sbms		printf("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
156675118Sfenner
156775118Sfenner		handle_ppp(proto, p, length);
156817692Spst		break;
156938638Sthepish
157075118Sfenner	case CHDLC_UNICAST:
157175118Sfenner	case CHDLC_BCAST:
1572127675Sbms		return (chdlc_if_print(h, p));
157375118Sfenner
157417692Spst	default:
157575118Sfenner		if (eflag)
157675118Sfenner			printf("%02x %02x %d ", p[0], p[1], length);
157775118Sfenner		p += 2;
157875118Sfenner		length -= 2;
1579127675Sbms		hdrlen += 2;
158075118Sfenner
158175118Sfenner		/*
158275118Sfenner		 * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
158375118Sfenner		 * the next two octets as an Ethernet type; does that
158475118Sfenner		 * ever happen?
158575118Sfenner		 */
158675118Sfenner		printf("unknown addr %02x; ctrl %02x", p[0], p[1]);
158775118Sfenner		break;
158817692Spst	}
158917692Spst
1590127675Sbms	return (hdrlen);
159117680Spst}
159217680Spst
159339300Sfenner#define PPP_BSDI_HDRLEN 24
159439300Sfenner
159539300Sfenner/* BSD/OS specific PPP printer */
1596127675Sbmsu_int
1597127675Sbmsppp_bsdos_if_print(const struct pcap_pkthdr *h _U_, register const u_char *p _U_)
159817680Spst{
1599127675Sbms	register int hdrlength;
160056896Sfenner#ifdef __bsdi__
160139300Sfenner	register u_int length = h->len;
160239300Sfenner	register u_int caplen = h->caplen;
160375118Sfenner	u_int16_t ptype;
160456896Sfenner	const u_char *q;
160556896Sfenner	int i;
160639300Sfenner
160739300Sfenner	if (caplen < PPP_BSDI_HDRLEN) {
160839300Sfenner		printf("[|ppp]");
1609127675Sbms		return (caplen)
161039300Sfenner	}
161139300Sfenner
161239300Sfenner	hdrlength = 0;
161339300Sfenner
161456896Sfenner#if 0
161539300Sfenner	if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
161675118Sfenner		if (eflag)
161739300Sfenner			printf("%02x %02x ", p[0], p[1]);
161839300Sfenner		p += 2;
161939300Sfenner		hdrlength = 2;
162039300Sfenner	}
162139300Sfenner
162275118Sfenner	if (eflag)
162339300Sfenner		printf("%d ", length);
162439300Sfenner	/* Retrieve the protocol type */
162539300Sfenner	if (*p & 01) {
162639300Sfenner		/* Compressed protocol field */
162739300Sfenner		ptype = *p;
162875118Sfenner		if (eflag)
162939300Sfenner			printf("%02x ", ptype);
163039300Sfenner		p++;
163139300Sfenner		hdrlength += 1;
163239300Sfenner	} else {
163339300Sfenner		/* Un-compressed protocol field */
1634214478Srpaulo		ptype = EXTRACT_16BITS(p);
163575118Sfenner		if (eflag)
163639300Sfenner			printf("%04x ", ptype);
163739300Sfenner		p += 2;
163839300Sfenner		hdrlength += 2;
163939300Sfenner	}
164056896Sfenner#else
164156896Sfenner	ptype = 0;	/*XXX*/
164256896Sfenner	if (eflag)
164356896Sfenner		printf("%c ", p[SLC_DIR] ? 'O' : 'I');
164456896Sfenner	if (p[SLC_LLHL]) {
164556896Sfenner		/* link level header */
164656896Sfenner		struct ppp_header *ph;
164756896Sfenner
164856896Sfenner		q = p + SLC_BPFHDRLEN;
164956896Sfenner		ph = (struct ppp_header *)q;
165056896Sfenner		if (ph->phdr_addr == PPP_ADDRESS
165156896Sfenner		 && ph->phdr_ctl == PPP_CONTROL) {
165275118Sfenner			if (eflag)
165356896Sfenner				printf("%02x %02x ", q[0], q[1]);
1654214478Srpaulo			ptype = EXTRACT_16BITS(&ph->phdr_type);
165556896Sfenner			if (eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
165656896Sfenner				printf("%s ", tok2str(ppptype2str,
165756896Sfenner						"proto-#%d", ptype));
165856896Sfenner			}
165956896Sfenner		} else {
166056896Sfenner			if (eflag) {
166156896Sfenner				printf("LLH=[");
166256896Sfenner				for (i = 0; i < p[SLC_LLHL]; i++)
166356896Sfenner					printf("%02x", q[i]);
166456896Sfenner				printf("] ");
166556896Sfenner			}
166656896Sfenner		}
166756896Sfenner	}
166875118Sfenner	if (eflag)
166975118Sfenner		printf("%d ", length);
167056896Sfenner	if (p[SLC_CHL]) {
167156896Sfenner		q = p + SLC_BPFHDRLEN + p[SLC_LLHL];
167256896Sfenner
167356896Sfenner		switch (ptype) {
167456896Sfenner		case PPP_VJC:
1675127675Sbms			ptype = vjc_print(q, ptype);
167656896Sfenner			hdrlength = PPP_BSDI_HDRLEN;
167756896Sfenner			p += hdrlength;
167875118Sfenner			switch (ptype) {
167975118Sfenner			case PPP_IP:
1680235530Sdelphij				ip_print(gndo, p, length);
168175118Sfenner				break;
168275118Sfenner#ifdef INET6
168375118Sfenner			case PPP_IPV6:
1684235530Sdelphij				ip6_print(gndo, p, length);
168575118Sfenner				break;
168675118Sfenner#endif
1687127675Sbms			case PPP_MPLS_UCAST:
1688127675Sbms			case PPP_MPLS_MCAST:
1689127675Sbms				mpls_print(p, length);
1690127675Sbms				break;
169175118Sfenner			}
169256896Sfenner			goto printx;
169356896Sfenner		case PPP_VJNC:
1694127675Sbms			ptype = vjc_print(q, ptype);
169556896Sfenner			hdrlength = PPP_BSDI_HDRLEN;
169656896Sfenner			p += hdrlength;
169775118Sfenner			switch (ptype) {
169875118Sfenner			case PPP_IP:
1699235530Sdelphij				ip_print(gndo, p, length);
170075118Sfenner				break;
170175118Sfenner#ifdef INET6
170275118Sfenner			case PPP_IPV6:
1703235530Sdelphij				ip6_print(gndo, p, length);
170475118Sfenner				break;
170575118Sfenner#endif
1706127675Sbms			case PPP_MPLS_UCAST:
1707127675Sbms			case PPP_MPLS_MCAST:
1708127675Sbms				mpls_print(p, length);
1709127675Sbms				break;
171075118Sfenner			}
171156896Sfenner			goto printx;
171256896Sfenner		default:
171356896Sfenner			if (eflag) {
171456896Sfenner				printf("CH=[");
171556896Sfenner				for (i = 0; i < p[SLC_LLHL]; i++)
171656896Sfenner					printf("%02x", q[i]);
171756896Sfenner				printf("] ");
171856896Sfenner			}
171956896Sfenner			break;
172056896Sfenner		}
172156896Sfenner	}
172256896Sfenner
172356896Sfenner	hdrlength = PPP_BSDI_HDRLEN;
172456896Sfenner#endif
172556896Sfenner
172639300Sfenner	length -= hdrlength;
172756896Sfenner	p += hdrlength;
172839300Sfenner
172975118Sfenner	switch (ptype) {
173075118Sfenner	case PPP_IP:
173139300Sfenner		ip_print(p, length);
173275118Sfenner		break;
173375118Sfenner#ifdef INET6
173475118Sfenner	case PPP_IPV6:
1735235530Sdelphij		ip6_print(gndo, p, length);
173675118Sfenner		break;
173775118Sfenner#endif
1738127675Sbms        case PPP_MPLS_UCAST:
1739127675Sbms        case PPP_MPLS_MCAST:
1740235530Sdelphij                mpls_print(gndo, p, length);
1741127675Sbms                break;
174275118Sfenner	default:
1743127675Sbms		printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));
174475118Sfenner	}
174539300Sfenner
174656896Sfennerprintx:
1747127675Sbms#else /* __bsdi */
1748127675Sbms	hdrlength = 0;
174956896Sfenner#endif /* __bsdi__ */
1750127675Sbms	return (hdrlength);
175117680Spst}
1752146778Ssam
1753146778Ssam
1754146778Ssam/*
1755146778Ssam * Local Variables:
1756146778Ssam * c-style: whitesmith
1757146778Ssam * c-basic-offset: 8
1758146778Ssam * End:
1759146778Ssam */
1760