xref: /freebsd/contrib/tcpdump/print-l2tp.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
1b0453382SBill Fenner /*
2b0453382SBill Fenner  * Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
3b0453382SBill Fenner  *      The Regents of the University of California.  All rights reserved.
4b0453382SBill Fenner  *
5b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
6b0453382SBill Fenner  * modification, are permitted provided that: (1) source code distributions
7b0453382SBill Fenner  * retain the above copyright notice and this paragraph in its entirety, (2)
8b0453382SBill Fenner  * distributions including binary code include the above copyright notice and
9b0453382SBill Fenner  * this paragraph in its entirety in the documentation or other materials
10b0453382SBill Fenner  * provided with the distribution, and (3) all advertising materials mentioning
11b0453382SBill Fenner  * features or use of this software display the following acknowledgement:
12b0453382SBill Fenner  * ``This product includes software developed by the University of California,
13b0453382SBill Fenner  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14b0453382SBill Fenner  * the University nor the names of its contributors may be used to endorse
15b0453382SBill Fenner  * or promote products derived from this software without specific prior
16b0453382SBill Fenner  * written permission.
17b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18b0453382SBill Fenner  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19b0453382SBill Fenner  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20b0453382SBill Fenner  *
21685295f4SBill Fenner  * L2TP support contributed by Motonori Shindo (mshindo@mshindo.net)
22b0453382SBill Fenner  */
23b0453382SBill Fenner 
243340d773SGleb Smirnoff /* \summary: Layer Two Tunneling Protocol (L2TP) printer */
253340d773SGleb Smirnoff 
2639e421e8SCy Schubert /* specification: RFC 2661 */
2739e421e8SCy Schubert 
28*ee67461eSJoseph Mingrone #include <config.h>
29b0453382SBill Fenner 
30*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
315b0fe478SBruce M Simpson 
323340d773SGleb Smirnoff #include "netdissect.h"
339afd0c29SBill Fenner #include "extract.h"
34b0453382SBill Fenner 
353c602fabSXin LI #define L2TP_FLAG_TYPE		0x8000	/* Type (0=Data, 1=Control) */
363c602fabSXin LI #define L2TP_FLAG_LENGTH	0x4000	/* Length */
373c602fabSXin LI #define L2TP_FLAG_SEQUENCE	0x0800	/* Sequence */
383c602fabSXin LI #define L2TP_FLAG_OFFSET	0x0200	/* Offset */
393c602fabSXin LI #define L2TP_FLAG_PRIORITY	0x0100	/* Priority */
403c602fabSXin LI 
413c602fabSXin LI #define L2TP_VERSION_MASK	0x000f	/* Version Mask */
423c602fabSXin LI #define L2TP_VERSION_L2F	0x0001	/* L2F */
433c602fabSXin LI #define L2TP_VERSION_L2TP	0x0002	/* L2TP */
443c602fabSXin LI 
453c602fabSXin LI #define L2TP_AVP_HDR_FLAG_MANDATORY	0x8000	/* Mandatory Flag */
463c602fabSXin LI #define L2TP_AVP_HDR_FLAG_HIDDEN	0x4000	/* Hidden Flag */
473c602fabSXin LI #define L2TP_AVP_HDR_LEN_MASK		0x03ff	/* Length Mask */
483c602fabSXin LI 
493c602fabSXin LI #define L2TP_FRAMING_CAP_SYNC_MASK	0x00000001	/* Synchronous */
503c602fabSXin LI #define L2TP_FRAMING_CAP_ASYNC_MASK	0x00000002	/* Asynchronous */
513c602fabSXin LI 
523c602fabSXin LI #define L2TP_FRAMING_TYPE_SYNC_MASK	0x00000001	/* Synchronous */
533c602fabSXin LI #define L2TP_FRAMING_TYPE_ASYNC_MASK	0x00000002	/* Asynchronous */
543c602fabSXin LI 
553c602fabSXin LI #define L2TP_BEARER_CAP_DIGITAL_MASK	0x00000001	/* Digital */
563c602fabSXin LI #define L2TP_BEARER_CAP_ANALOG_MASK	0x00000002	/* Analog */
573c602fabSXin LI 
583c602fabSXin LI #define L2TP_BEARER_TYPE_DIGITAL_MASK	0x00000001	/* Digital */
593c602fabSXin LI #define L2TP_BEARER_TYPE_ANALOG_MASK	0x00000002	/* Analog */
603c602fabSXin LI 
613c602fabSXin LI /* Authen Type */
623c602fabSXin LI #define L2TP_AUTHEN_TYPE_RESERVED	0x0000	/* Reserved */
633c602fabSXin LI #define L2TP_AUTHEN_TYPE_TEXTUAL	0x0001	/* Textual username/password exchange */
643c602fabSXin LI #define L2TP_AUTHEN_TYPE_CHAP		0x0002	/* PPP CHAP */
653c602fabSXin LI #define L2TP_AUTHEN_TYPE_PAP		0x0003	/* PPP PAP */
663c602fabSXin LI #define L2TP_AUTHEN_TYPE_NO_AUTH	0x0004	/* No Authentication */
673c602fabSXin LI #define L2TP_AUTHEN_TYPE_MSCHAPv1	0x0005	/* MSCHAPv1 */
683c602fabSXin LI 
693c602fabSXin LI #define L2TP_PROXY_AUTH_ID_MASK		0x00ff
703c602fabSXin LI 
71b0453382SBill Fenner 
72a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
73a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
74a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
75a90e161bSBill Fenner #define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
76a90e161bSBill Fenner #define	L2TP_MSGTYPE_HELLO	6  /* Hello */
77a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
78a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
79a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
80a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
81a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
82a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
83a90e161bSBill Fenner #define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
84a90e161bSBill Fenner #define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
85a90e161bSBill Fenner #define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
86a90e161bSBill Fenner 
873c602fabSXin LI static const struct tok l2tp_msgtype2str[] = {
88a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRQ,	"SCCRQ" },
89a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
90a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
91a90e161bSBill Fenner 	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
92a90e161bSBill Fenner 	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
93a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
94a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
95a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
96a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
97a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
98a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
99a90e161bSBill Fenner 	{ L2TP_MSGTYPE_CDN,	"CDN" },
100a90e161bSBill Fenner 	{ L2TP_MSGTYPE_WEN,	"WEN" },
101a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SLI,	"SLI" },
102a90e161bSBill Fenner 	{ 0,			NULL }
103b0453382SBill Fenner };
104b0453382SBill Fenner 
105a90e161bSBill Fenner #define L2TP_AVP_MSGTYPE		0  /* Message Type */
106a90e161bSBill Fenner #define L2TP_AVP_RESULT_CODE		1  /* Result Code */
107a90e161bSBill Fenner #define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
108a90e161bSBill Fenner #define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
109a90e161bSBill Fenner #define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
110a90e161bSBill Fenner #define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
111a90e161bSBill Fenner #define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
112a90e161bSBill Fenner #define L2TP_AVP_HOST_NAME		7  /* Host Name */
113a90e161bSBill Fenner #define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
114a90e161bSBill Fenner #define L2TP_AVP_ASSND_TUN_ID		9  /* Assigned Tunnel ID */
115a90e161bSBill Fenner #define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
116a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE		11 /* Challenge */
117a90e161bSBill Fenner #define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
118a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
119a90e161bSBill Fenner #define L2TP_AVP_ASSND_SESS_ID		14 /* Assigned Session ID */
120a90e161bSBill Fenner #define L2TP_AVP_CALL_SER_NUM		15 /* Call Serial Number */
121a90e161bSBill Fenner #define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
122a90e161bSBill Fenner #define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
123a90e161bSBill Fenner #define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
124a90e161bSBill Fenner #define L2TP_AVP_FRAMING_TYPE		19 /* Framing Type */
125a90e161bSBill Fenner #define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
126a90e161bSBill Fenner #define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
127a90e161bSBill Fenner #define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
128a90e161bSBill Fenner #define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
129a90e161bSBill Fenner #define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
130a90e161bSBill Fenner #define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
131a90e161bSBill Fenner #define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
132a90e161bSBill Fenner #define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
133a90e161bSBill Fenner #define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
134a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
135a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
136a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
137a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
138a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
139a90e161bSBill Fenner #define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
140a90e161bSBill Fenner #define L2TP_AVP_ACCM			35 /* ACCM */
141a90e161bSBill Fenner #define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
142a90e161bSBill Fenner #define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
143a90e161bSBill Fenner #define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
144a90e161bSBill Fenner #define L2TP_AVP_SEQ_REQUIRED		39 /* Sequencing Required */
14539e421e8SCy Schubert #define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code - RFC 3145 */
146b0453382SBill Fenner 
1473c602fabSXin LI static const struct tok l2tp_avp2str[] = {
148a90e161bSBill Fenner 	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
149a90e161bSBill Fenner 	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
150a90e161bSBill Fenner 	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
151a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
152a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
153a90e161bSBill Fenner 	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
154a90e161bSBill Fenner 	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
155a90e161bSBill Fenner 	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
156a90e161bSBill Fenner 	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
157a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
158a90e161bSBill Fenner 	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
159a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
160a90e161bSBill Fenner 	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
161a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
162a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
163a90e161bSBill Fenner 	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
164a90e161bSBill Fenner 	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
165a90e161bSBill Fenner 	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
166a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
167a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
168a90e161bSBill Fenner 	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
169a90e161bSBill Fenner 	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
170a90e161bSBill Fenner 	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
171a90e161bSBill Fenner 	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
172a90e161bSBill Fenner 	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
173a90e161bSBill Fenner 	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
174a90e161bSBill Fenner 	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
175a90e161bSBill Fenner 	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
176a90e161bSBill Fenner 	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
177a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
178a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
179a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
180a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
181a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
182a90e161bSBill Fenner 	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
183a90e161bSBill Fenner 	{ L2TP_AVP_ACCM,		"ACCM" },
184a90e161bSBill Fenner 	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
185a90e161bSBill Fenner 	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
186a90e161bSBill Fenner 	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
187a90e161bSBill Fenner 	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
188a90e161bSBill Fenner 	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
189a90e161bSBill Fenner 	{ 0,				NULL }
190a90e161bSBill Fenner };
191a90e161bSBill Fenner 
1923c602fabSXin LI static const struct tok l2tp_authentype2str[] = {
193a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
194a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
195a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
196a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
197a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
198a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
199a90e161bSBill Fenner 	{ 0,				NULL }
200a90e161bSBill Fenner };
201a90e161bSBill Fenner 
202a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
203a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
204a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
205a90e161bSBill Fenner 
2063c602fabSXin LI static const struct tok l2tp_cc_direction2str[] = {
207a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
208a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
209a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
210a90e161bSBill Fenner 	{ 0,					NULL }
211b0453382SBill Fenner };
212b0453382SBill Fenner 
213b0453382SBill Fenner #if 0
214b0453382SBill Fenner static char *l2tp_result_code_StopCCN[] = {
215b0453382SBill Fenner          "Reserved",
216b0453382SBill Fenner          "General request to clear control connection",
217b0453382SBill Fenner          "General error--Error Code indicates the problem",
218b0453382SBill Fenner          "Control channel already exists",
219b0453382SBill Fenner          "Requester is not authorized to establish a control channel",
220b0453382SBill Fenner          "The protocol version of the requester is not supported",
221b0453382SBill Fenner          "Requester is being shut down",
222b0453382SBill Fenner          "Finite State Machine error"
223b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
224b0453382SBill Fenner };
225b0453382SBill Fenner #endif
226b0453382SBill Fenner 
227b0453382SBill Fenner #if 0
228b0453382SBill Fenner static char *l2tp_result_code_CDN[] = {
229b0453382SBill Fenner 	"Reserved",
230b0453382SBill Fenner 	"Call disconnected due to loss of carrier",
231b0453382SBill Fenner 	"Call disconnected for the reason indicated in error code",
232b0453382SBill Fenner 	"Call disconnected for administrative reasons",
233*ee67461eSJoseph Mingrone 	"Call failed due to lack of appropriate facilities being "
234b0453382SBill Fenner 	"available (temporary condition)",
235*ee67461eSJoseph Mingrone 	"Call failed due to lack of appropriate facilities being "
236b0453382SBill Fenner 	"available (permanent condition)",
237b0453382SBill Fenner 	"Invalid destination",
238b0453382SBill Fenner 	"Call failed due to no carrier detected",
239b0453382SBill Fenner 	"Call failed due to detection of a busy signal",
240b0453382SBill Fenner 	"Call failed due to lack of a dial tone",
241b0453382SBill Fenner 	"Call was not established within time allotted by LAC",
242b0453382SBill Fenner 	"Call was connected but no appropriate framing was detected"
243b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
244b0453382SBill Fenner };
245b0453382SBill Fenner #endif
246b0453382SBill Fenner 
247b0453382SBill Fenner #if 0
248b0453382SBill Fenner static char *l2tp_error_code_general[] = {
249b0453382SBill Fenner 	"No general error",
250b0453382SBill Fenner 	"No control connection exists yet for this LAC-LNS pair",
251b0453382SBill Fenner 	"Length is wrong",
252*ee67461eSJoseph Mingrone 	"One of the field values was out of range or "
253b0453382SBill Fenner 	"reserved field was non-zero"
254b0453382SBill Fenner 	"Insufficient resources to handle this operation now",
255b0453382SBill Fenner 	"The Session ID is invalid in this context",
256b0453382SBill Fenner 	"A generic vendor-specific error occurred in the LAC",
257b0453382SBill Fenner 	"Try another"
258b0453382SBill Fenner #define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
259b0453382SBill Fenner };
260b0453382SBill Fenner #endif
261b0453382SBill Fenner 
262b0453382SBill Fenner /******************************/
263b0453382SBill Fenner /* generic print out routines */
264b0453382SBill Fenner /******************************/
265b0453382SBill Fenner static void
print_string(netdissect_options * ndo,const u_char * dat,u_int length)2663c602fabSXin LI print_string(netdissect_options *ndo, const u_char *dat, u_int length)
267b0453382SBill Fenner {
2685b0fe478SBruce M Simpson 	u_int i;
269b0453382SBill Fenner 	for (i=0; i<length; i++) {
270*ee67461eSJoseph Mingrone 		fn_print_char(ndo, GET_U_1(dat));
271*ee67461eSJoseph Mingrone 		dat++;
272b0453382SBill Fenner 	}
273b0453382SBill Fenner }
274b0453382SBill Fenner 
275b0453382SBill Fenner static void
print_octets(netdissect_options * ndo,const u_char * dat,u_int length)2763c602fabSXin LI print_octets(netdissect_options *ndo, const u_char *dat, u_int length)
277b0453382SBill Fenner {
2785b0fe478SBruce M Simpson 	u_int i;
279b0453382SBill Fenner 	for (i=0; i<length; i++) {
280*ee67461eSJoseph Mingrone 		ND_PRINT("%02x", GET_U_1(dat));
281*ee67461eSJoseph Mingrone 		dat++;
282b0453382SBill Fenner 	}
283b0453382SBill Fenner }
284b0453382SBill Fenner 
285b0453382SBill Fenner static void
print_16bits_val(netdissect_options * ndo,const uint8_t * dat)28639e421e8SCy Schubert print_16bits_val(netdissect_options *ndo, const uint8_t *dat)
287b0453382SBill Fenner {
288*ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_2(dat));
289b0453382SBill Fenner }
290b0453382SBill Fenner 
291b0453382SBill Fenner static void
print_32bits_val(netdissect_options * ndo,const uint8_t * dat)29239e421e8SCy Schubert print_32bits_val(netdissect_options *ndo, const uint8_t *dat)
293b0453382SBill Fenner {
294*ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_4(dat));
295b0453382SBill Fenner }
296b0453382SBill Fenner 
297a90e161bSBill Fenner /***********************************/
298b0453382SBill Fenner /* AVP-specific print out routines */
299a90e161bSBill Fenner /***********************************/
300b0453382SBill Fenner static void
l2tp_msgtype_print(netdissect_options * ndo,const u_char * dat,u_int length)3010bff6a5aSEd Maste l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length)
302b0453382SBill Fenner {
3030bff6a5aSEd Maste 	if (length < 2) {
304*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3050bff6a5aSEd Maste 		return;
3060bff6a5aSEd Maste 	}
307*ee67461eSJoseph Mingrone 	ND_PRINT("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
308*ee67461eSJoseph Mingrone 	    GET_BE_U_2(dat)));
309b0453382SBill Fenner }
310b0453382SBill Fenner 
311b0453382SBill Fenner static void
l2tp_result_code_print(netdissect_options * ndo,const u_char * dat,u_int length)3123c602fabSXin LI l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length)
313b0453382SBill Fenner {
3140bff6a5aSEd Maste 	/* Result Code */
3150bff6a5aSEd Maste 	if (length < 2) {
316*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3170bff6a5aSEd Maste 		return;
318a90e161bSBill Fenner 	}
319*ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_2(dat));
32039e421e8SCy Schubert 	dat += 2;
3210bff6a5aSEd Maste 	length -= 2;
3220bff6a5aSEd Maste 
3230bff6a5aSEd Maste 	/* Error Code (opt) */
3240bff6a5aSEd Maste 	if (length == 0)
3250bff6a5aSEd Maste 		return;
3260bff6a5aSEd Maste 	if (length < 2) {
327*ee67461eSJoseph Mingrone 		ND_PRINT(" AVP too short");
3280bff6a5aSEd Maste 		return;
3290bff6a5aSEd Maste 	}
330*ee67461eSJoseph Mingrone 	ND_PRINT("/%u", GET_BE_U_2(dat));
33139e421e8SCy Schubert 	dat += 2;
3320bff6a5aSEd Maste 	length -= 2;
3330bff6a5aSEd Maste 
3340bff6a5aSEd Maste 	/* Error Message (opt) */
3350bff6a5aSEd Maste 	if (length == 0)
3360bff6a5aSEd Maste 		return;
337*ee67461eSJoseph Mingrone 	ND_PRINT(" ");
33839e421e8SCy Schubert 	print_string(ndo, dat, length);
339b0453382SBill Fenner }
340b0453382SBill Fenner 
341b0453382SBill Fenner static void
l2tp_proto_ver_print(netdissect_options * ndo,const u_char * dat,u_int length)34239e421e8SCy Schubert l2tp_proto_ver_print(netdissect_options *ndo, const u_char *dat, u_int length)
343b0453382SBill Fenner {
3440bff6a5aSEd Maste 	if (length < 2) {
345*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3460bff6a5aSEd Maste 		return;
3470bff6a5aSEd Maste 	}
348*ee67461eSJoseph Mingrone 	ND_PRINT("%u.%u", (GET_BE_U_2(dat) >> 8),
349*ee67461eSJoseph Mingrone 		  (GET_BE_U_2(dat) & 0xff));
350b0453382SBill Fenner }
351b0453382SBill Fenner 
352b0453382SBill Fenner static void
l2tp_framing_cap_print(netdissect_options * ndo,const u_char * dat,u_int length)3530bff6a5aSEd Maste l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
354b0453382SBill Fenner {
3550bff6a5aSEd Maste 	if (length < 4) {
356*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3570bff6a5aSEd Maste 		return;
3580bff6a5aSEd Maste 	}
359*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
360*ee67461eSJoseph Mingrone 		ND_PRINT("A");
361b0453382SBill Fenner 	}
362*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_CAP_SYNC_MASK) {
363*ee67461eSJoseph Mingrone 		ND_PRINT("S");
364b0453382SBill Fenner 	}
365b0453382SBill Fenner }
366b0453382SBill Fenner 
367b0453382SBill Fenner static void
l2tp_bearer_cap_print(netdissect_options * ndo,const u_char * dat,u_int length)3680bff6a5aSEd Maste l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
369b0453382SBill Fenner {
3700bff6a5aSEd Maste 	if (length < 4) {
371*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3720bff6a5aSEd Maste 		return;
3730bff6a5aSEd Maste 	}
374*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_CAP_ANALOG_MASK) {
375*ee67461eSJoseph Mingrone 		ND_PRINT("A");
376b0453382SBill Fenner 	}
377*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
378*ee67461eSJoseph Mingrone 		ND_PRINT("D");
379b0453382SBill Fenner 	}
380b0453382SBill Fenner }
381b0453382SBill Fenner 
382b0453382SBill Fenner static void
l2tp_q931_cc_print(netdissect_options * ndo,const u_char * dat,u_int length)3833c602fabSXin LI l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
384b0453382SBill Fenner {
3850bff6a5aSEd Maste 	if (length < 3) {
386*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3870bff6a5aSEd Maste 		return;
3880bff6a5aSEd Maste 	}
38939e421e8SCy Schubert 	print_16bits_val(ndo, dat);
390*ee67461eSJoseph Mingrone 	ND_PRINT(", %02x", GET_U_1(dat + 2));
3910bff6a5aSEd Maste 	dat += 3;
3920bff6a5aSEd Maste 	length -= 3;
3930bff6a5aSEd Maste 	if (length != 0) {
394*ee67461eSJoseph Mingrone 		ND_PRINT(" ");
3950bff6a5aSEd Maste 		print_string(ndo, dat, length);
396b0453382SBill Fenner 	}
397b0453382SBill Fenner }
398b0453382SBill Fenner 
399b0453382SBill Fenner static void
l2tp_bearer_type_print(netdissect_options * ndo,const u_char * dat,u_int length)4000bff6a5aSEd Maste l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
401b0453382SBill Fenner {
4020bff6a5aSEd Maste 	if (length < 4) {
403*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4040bff6a5aSEd Maste 		return;
4050bff6a5aSEd Maste 	}
406*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
407*ee67461eSJoseph Mingrone 		ND_PRINT("A");
408b0453382SBill Fenner 	}
409*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
410*ee67461eSJoseph Mingrone 		ND_PRINT("D");
411b0453382SBill Fenner 	}
412b0453382SBill Fenner }
413b0453382SBill Fenner 
414b0453382SBill Fenner static void
l2tp_framing_type_print(netdissect_options * ndo,const u_char * dat,u_int length)4150bff6a5aSEd Maste l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
416b0453382SBill Fenner {
4170bff6a5aSEd Maste 	if (length < 4) {
418*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4190bff6a5aSEd Maste 		return;
4200bff6a5aSEd Maste 	}
421*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
422*ee67461eSJoseph Mingrone 		ND_PRINT("A");
423b0453382SBill Fenner 	}
424*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
425*ee67461eSJoseph Mingrone 		ND_PRINT("S");
426b0453382SBill Fenner 	}
427b0453382SBill Fenner }
428b0453382SBill Fenner 
429b0453382SBill Fenner static void
l2tp_packet_proc_delay_print(netdissect_options * ndo)4303c602fabSXin LI l2tp_packet_proc_delay_print(netdissect_options *ndo)
431b0453382SBill Fenner {
432*ee67461eSJoseph Mingrone 	ND_PRINT("obsolete");
433b0453382SBill Fenner }
434b0453382SBill Fenner 
435b0453382SBill Fenner static void
l2tp_proxy_auth_type_print(netdissect_options * ndo,const u_char * dat,u_int length)4360bff6a5aSEd Maste l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
437b0453382SBill Fenner {
4380bff6a5aSEd Maste 	if (length < 2) {
439*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4400bff6a5aSEd Maste 		return;
4410bff6a5aSEd Maste 	}
442*ee67461eSJoseph Mingrone 	ND_PRINT("%s", tok2str(l2tp_authentype2str,
443*ee67461eSJoseph Mingrone 			     "AuthType-#%u", GET_BE_U_2(dat)));
444b0453382SBill Fenner }
445b0453382SBill Fenner 
446b0453382SBill Fenner static void
l2tp_proxy_auth_id_print(netdissect_options * ndo,const u_char * dat,u_int length)4470bff6a5aSEd Maste l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length)
448b0453382SBill Fenner {
4490bff6a5aSEd Maste 	if (length < 2) {
450*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4510bff6a5aSEd Maste 		return;
4520bff6a5aSEd Maste 	}
453*ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_2(dat) & L2TP_PROXY_AUTH_ID_MASK);
454b0453382SBill Fenner }
455b0453382SBill Fenner 
456b0453382SBill Fenner static void
l2tp_call_errors_print(netdissect_options * ndo,const u_char * dat,u_int length)4570bff6a5aSEd Maste l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length)
458b0453382SBill Fenner {
45939e421e8SCy Schubert 	uint32_t val;
460a90e161bSBill Fenner 
4610bff6a5aSEd Maste 	if (length < 2) {
462*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4630bff6a5aSEd Maste 		return;
4640bff6a5aSEd Maste 	}
46539e421e8SCy Schubert 	dat += 2;	/* skip "Reserved" */
4660bff6a5aSEd Maste 	length -= 2;
467a90e161bSBill Fenner 
4680bff6a5aSEd Maste 	if (length < 4) {
469*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4700bff6a5aSEd Maste 		return;
4710bff6a5aSEd Maste 	}
472*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
473*ee67461eSJoseph Mingrone 	ND_PRINT("CRCErr=%u ", val);
474a90e161bSBill Fenner 
4750bff6a5aSEd Maste 	if (length < 4) {
476*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4770bff6a5aSEd Maste 		return;
4780bff6a5aSEd Maste 	}
479*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
480*ee67461eSJoseph Mingrone 	ND_PRINT("FrameErr=%u ", val);
481a90e161bSBill Fenner 
4820bff6a5aSEd Maste 	if (length < 4) {
483*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4840bff6a5aSEd Maste 		return;
4850bff6a5aSEd Maste 	}
486*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
487*ee67461eSJoseph Mingrone 	ND_PRINT("HardOver=%u ", val);
488a90e161bSBill Fenner 
4890bff6a5aSEd Maste 	if (length < 4) {
490*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4910bff6a5aSEd Maste 		return;
4920bff6a5aSEd Maste 	}
493*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
494*ee67461eSJoseph Mingrone 	ND_PRINT("BufOver=%u ", val);
495a90e161bSBill Fenner 
4960bff6a5aSEd Maste 	if (length < 4) {
497*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4980bff6a5aSEd Maste 		return;
4990bff6a5aSEd Maste 	}
500*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
501*ee67461eSJoseph Mingrone 	ND_PRINT("Timeout=%u ", val);
502a90e161bSBill Fenner 
5030bff6a5aSEd Maste 	if (length < 4) {
504*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5050bff6a5aSEd Maste 		return;
5060bff6a5aSEd Maste 	}
507*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
508*ee67461eSJoseph Mingrone 	ND_PRINT("AlignErr=%u ", val);
509b0453382SBill Fenner }
510b0453382SBill Fenner 
511b0453382SBill Fenner static void
l2tp_accm_print(netdissect_options * ndo,const u_char * dat,u_int length)5120bff6a5aSEd Maste l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length)
513b0453382SBill Fenner {
51439e421e8SCy Schubert 	uint32_t val;
515b0453382SBill Fenner 
5160bff6a5aSEd Maste 	if (length < 2) {
517*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5180bff6a5aSEd Maste 		return;
5190bff6a5aSEd Maste 	}
52039e421e8SCy Schubert 	dat += 2;	/* skip "Reserved" */
5210bff6a5aSEd Maste 	length -= 2;
522a90e161bSBill Fenner 
5230bff6a5aSEd Maste 	if (length < 4) {
524*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5250bff6a5aSEd Maste 		return;
5260bff6a5aSEd Maste 	}
527*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
528*ee67461eSJoseph Mingrone 	ND_PRINT("send=%08x ", val);
529a90e161bSBill Fenner 
5300bff6a5aSEd Maste 	if (length < 4) {
531*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5320bff6a5aSEd Maste 		return;
5330bff6a5aSEd Maste 	}
534*ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
535*ee67461eSJoseph Mingrone 	ND_PRINT("recv=%08x ", val);
536b0453382SBill Fenner }
537b0453382SBill Fenner 
538b0453382SBill Fenner static void
l2tp_ppp_discon_cc_print(netdissect_options * ndo,const u_char * dat,u_int length)5393c602fabSXin LI l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
540b0453382SBill Fenner {
5410bff6a5aSEd Maste 	if (length < 5) {
542*ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5430bff6a5aSEd Maste 		return;
5440bff6a5aSEd Maste 	}
5450bff6a5aSEd Maste 	/* Disconnect Code */
546*ee67461eSJoseph Mingrone 	ND_PRINT("%04x, ", GET_BE_U_2(dat));
5470bff6a5aSEd Maste 	dat += 2;
5480bff6a5aSEd Maste 	length -= 2;
5490bff6a5aSEd Maste 	/* Control Protocol Number */
550*ee67461eSJoseph Mingrone 	ND_PRINT("%04x ",  GET_BE_U_2(dat));
5510bff6a5aSEd Maste 	dat += 2;
5520bff6a5aSEd Maste 	length -= 2;
5530bff6a5aSEd Maste 	/* Direction */
554*ee67461eSJoseph Mingrone 	ND_PRINT("%s", tok2str(l2tp_cc_direction2str,
555*ee67461eSJoseph Mingrone 			     "Direction-#%u", GET_U_1(dat)));
55639e421e8SCy Schubert 	dat++;
5570bff6a5aSEd Maste 	length--;
558a90e161bSBill Fenner 
5590bff6a5aSEd Maste 	if (length != 0) {
560*ee67461eSJoseph Mingrone 		ND_PRINT(" ");
56139e421e8SCy Schubert 		print_string(ndo, (const u_char *)dat, length);
562a90e161bSBill Fenner 	}
563b0453382SBill Fenner }
564b0453382SBill Fenner 
56539e421e8SCy Schubert static u_int
l2tp_avp_print(netdissect_options * ndo,const u_char * dat,u_int length)56639e421e8SCy Schubert l2tp_avp_print(netdissect_options *ndo, const u_char *dat, u_int length)
567b0453382SBill Fenner {
568a90e161bSBill Fenner 	u_int len;
5693c602fabSXin LI 	uint16_t attr_type;
570a90e161bSBill Fenner 	int hidden = FALSE;
571b0453382SBill Fenner 
572*ee67461eSJoseph Mingrone 	ND_PRINT(" ");
573*ee67461eSJoseph Mingrone 	/* Flags & Length */
574*ee67461eSJoseph Mingrone 	len = GET_BE_U_2(dat) & L2TP_AVP_HDR_LEN_MASK;
575a90e161bSBill Fenner 
576b97c9af5SBill Fenner 	/* If it is not long enough to contain the header, we'll give up. */
577b97c9af5SBill Fenner 	if (len < 6)
578b97c9af5SBill Fenner 		goto trunc;
579b97c9af5SBill Fenner 
580b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the packet,
581b97c9af5SBill Fenner 	   we'll give up. */
582b97c9af5SBill Fenner 	if (len > (u_int)length)
583b97c9af5SBill Fenner 		goto trunc;
584b97c9af5SBill Fenner 
585b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the captured
586b97c9af5SBill Fenner 	   data, we'll give up. */
587*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(dat, len);
5880bff6a5aSEd Maste 
5890bff6a5aSEd Maste 	/*
5900bff6a5aSEd Maste 	 * After this point, we don't need to check whether we go past
5910bff6a5aSEd Maste 	 * the length of the captured data; however, we *do* need to
5920bff6a5aSEd Maste 	 * check whether we go past the end of the AVP.
5930bff6a5aSEd Maste 	 */
594a90e161bSBill Fenner 
595*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_MANDATORY) {
596*ee67461eSJoseph Mingrone 		ND_PRINT("*");
597b0453382SBill Fenner 	}
598*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_HIDDEN) {
599b0453382SBill Fenner 		hidden = TRUE;
600*ee67461eSJoseph Mingrone 		ND_PRINT("?");
601b0453382SBill Fenner 	}
60239e421e8SCy Schubert 	dat += 2;
603b0453382SBill Fenner 
604*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(dat)) {
605685295f4SBill Fenner 		/* Vendor Specific Attribute */
606*ee67461eSJoseph Mingrone 	        ND_PRINT("VENDOR%04x:", GET_BE_U_2(dat)); dat += 2;
607*ee67461eSJoseph Mingrone 		ND_PRINT("ATTR%04x", GET_BE_U_2(dat)); dat += 2;
608*ee67461eSJoseph Mingrone 		ND_PRINT("(");
60939e421e8SCy Schubert 		print_octets(ndo, dat, len-6);
610*ee67461eSJoseph Mingrone 		ND_PRINT(")");
611685295f4SBill Fenner 	} else {
612a90e161bSBill Fenner 		/* IETF-defined Attributes */
61339e421e8SCy Schubert 		dat += 2;
614*ee67461eSJoseph Mingrone 		attr_type = GET_BE_U_2(dat); dat += 2;
615*ee67461eSJoseph Mingrone 		ND_PRINT("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
616*ee67461eSJoseph Mingrone 		ND_PRINT("(");
617a90e161bSBill Fenner 		if (hidden) {
618*ee67461eSJoseph Mingrone 			ND_PRINT("???");
619a90e161bSBill Fenner 		} else {
620a90e161bSBill Fenner 			switch (attr_type) {
621a90e161bSBill Fenner 			case L2TP_AVP_MSGTYPE:
62239e421e8SCy Schubert 				l2tp_msgtype_print(ndo, dat, len-6);
623a90e161bSBill Fenner 				break;
624a90e161bSBill Fenner 			case L2TP_AVP_RESULT_CODE:
62539e421e8SCy Schubert 				l2tp_result_code_print(ndo, dat, len-6);
626a90e161bSBill Fenner 				break;
627a90e161bSBill Fenner 			case L2TP_AVP_PROTO_VER:
62839e421e8SCy Schubert 				l2tp_proto_ver_print(ndo, dat, len-6);
629a90e161bSBill Fenner 				break;
630a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_CAP:
63139e421e8SCy Schubert 				l2tp_framing_cap_print(ndo, dat, len-6);
632a90e161bSBill Fenner 				break;
633a90e161bSBill Fenner 			case L2TP_AVP_BEARER_CAP:
63439e421e8SCy Schubert 				l2tp_bearer_cap_print(ndo, dat, len-6);
635a90e161bSBill Fenner 				break;
636a90e161bSBill Fenner 			case L2TP_AVP_TIE_BREAKER:
6370bff6a5aSEd Maste 				if (len-6 < 8) {
638*ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6390bff6a5aSEd Maste 					break;
6400bff6a5aSEd Maste 				}
64139e421e8SCy Schubert 				print_octets(ndo, dat, 8);
642a90e161bSBill Fenner 				break;
643a90e161bSBill Fenner 			case L2TP_AVP_FIRM_VER:
644a90e161bSBill Fenner 			case L2TP_AVP_ASSND_TUN_ID:
645a90e161bSBill Fenner 			case L2TP_AVP_RECV_WIN_SIZE:
646a90e161bSBill Fenner 			case L2TP_AVP_ASSND_SESS_ID:
6470bff6a5aSEd Maste 				if (len-6 < 2) {
648*ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6490bff6a5aSEd Maste 					break;
6500bff6a5aSEd Maste 				}
65139e421e8SCy Schubert 				print_16bits_val(ndo, dat);
652a90e161bSBill Fenner 				break;
653a90e161bSBill Fenner 			case L2TP_AVP_HOST_NAME:
654a90e161bSBill Fenner 			case L2TP_AVP_VENDOR_NAME:
655a90e161bSBill Fenner 			case L2TP_AVP_CALLING_NUMBER:
656a90e161bSBill Fenner 			case L2TP_AVP_CALLED_NUMBER:
657a90e161bSBill Fenner 			case L2TP_AVP_SUB_ADDRESS:
658a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_NAME:
659a90e161bSBill Fenner 			case L2TP_AVP_PRIVATE_GRP_ID:
66039e421e8SCy Schubert 				print_string(ndo, dat, len-6);
661a90e161bSBill Fenner 				break;
662a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE:
663a90e161bSBill Fenner 			case L2TP_AVP_INI_RECV_LCP:
664a90e161bSBill Fenner 			case L2TP_AVP_LAST_SENT_LCP:
665a90e161bSBill Fenner 			case L2TP_AVP_LAST_RECV_LCP:
666a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_CHAL:
667a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_RESP:
668a90e161bSBill Fenner 			case L2TP_AVP_RANDOM_VECTOR:
66939e421e8SCy Schubert 				print_octets(ndo, dat, len-6);
670a90e161bSBill Fenner 				break;
671a90e161bSBill Fenner 			case L2TP_AVP_Q931_CC:
67239e421e8SCy Schubert 				l2tp_q931_cc_print(ndo, dat, len-6);
673a90e161bSBill Fenner 				break;
674a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE_RESP:
6750bff6a5aSEd Maste 				if (len-6 < 16) {
676*ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6770bff6a5aSEd Maste 					break;
6780bff6a5aSEd Maste 				}
67939e421e8SCy Schubert 				print_octets(ndo, dat, 16);
680a90e161bSBill Fenner 				break;
681a90e161bSBill Fenner 			case L2TP_AVP_CALL_SER_NUM:
682a90e161bSBill Fenner 			case L2TP_AVP_MINIMUM_BPS:
683a90e161bSBill Fenner 			case L2TP_AVP_MAXIMUM_BPS:
684a90e161bSBill Fenner 			case L2TP_AVP_TX_CONN_SPEED:
685a90e161bSBill Fenner 			case L2TP_AVP_PHY_CHANNEL_ID:
686a90e161bSBill Fenner 			case L2TP_AVP_RX_CONN_SPEED:
6870bff6a5aSEd Maste 				if (len-6 < 4) {
688*ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6890bff6a5aSEd Maste 					break;
6900bff6a5aSEd Maste 				}
69139e421e8SCy Schubert 				print_32bits_val(ndo, dat);
692a90e161bSBill Fenner 				break;
693a90e161bSBill Fenner 			case L2TP_AVP_BEARER_TYPE:
69439e421e8SCy Schubert 				l2tp_bearer_type_print(ndo, dat, len-6);
695a90e161bSBill Fenner 				break;
696a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_TYPE:
69739e421e8SCy Schubert 				l2tp_framing_type_print(ndo, dat, len-6);
698a90e161bSBill Fenner 				break;
699a90e161bSBill Fenner 			case L2TP_AVP_PACKET_PROC_DELAY:
7003c602fabSXin LI 				l2tp_packet_proc_delay_print(ndo);
701a90e161bSBill Fenner 				break;
702a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_TYPE:
70339e421e8SCy Schubert 				l2tp_proxy_auth_type_print(ndo, dat, len-6);
704a90e161bSBill Fenner 				break;
705a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_ID:
70639e421e8SCy Schubert 				l2tp_proxy_auth_id_print(ndo, dat, len-6);
707a90e161bSBill Fenner 				break;
708a90e161bSBill Fenner 			case L2TP_AVP_CALL_ERRORS:
70939e421e8SCy Schubert 				l2tp_call_errors_print(ndo, dat, len-6);
710a90e161bSBill Fenner 				break;
711a90e161bSBill Fenner 			case L2TP_AVP_ACCM:
71239e421e8SCy Schubert 				l2tp_accm_print(ndo, dat, len-6);
713a90e161bSBill Fenner 				break;
714a90e161bSBill Fenner 			case L2TP_AVP_SEQ_REQUIRED:
715a90e161bSBill Fenner 				break;	/* No Attribute Value */
716a90e161bSBill Fenner 			case L2TP_AVP_PPP_DISCON_CC:
71739e421e8SCy Schubert 				l2tp_ppp_discon_cc_print(ndo, dat, len-6);
718a90e161bSBill Fenner 				break;
719a90e161bSBill Fenner 			default:
720a90e161bSBill Fenner 				break;
721a90e161bSBill Fenner 			}
722b0453382SBill Fenner 		}
723*ee67461eSJoseph Mingrone 		ND_PRINT(")");
724685295f4SBill Fenner 	}
725b0453382SBill Fenner 
72639e421e8SCy Schubert 	return (len);
727a90e161bSBill Fenner 
728a90e161bSBill Fenner  trunc:
729*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
73039e421e8SCy Schubert 	return (0);
731b0453382SBill Fenner }
732b0453382SBill Fenner 
733b0453382SBill Fenner 
734b0453382SBill Fenner void
l2tp_print(netdissect_options * ndo,const u_char * dat,u_int length)7353c602fabSXin LI l2tp_print(netdissect_options *ndo, const u_char *dat, u_int length)
736b0453382SBill Fenner {
73727df3f5dSRui Paulo 	const u_char *ptr = dat;
738b0453382SBill Fenner 	u_int cnt = 0;			/* total octets consumed */
7393c602fabSXin LI 	uint16_t pad;
740f4d0c64aSSam Leffler 	int flag_t, flag_l, flag_s, flag_o;
7413c602fabSXin LI 	uint16_t l2tp_len;
742b0453382SBill Fenner 
743*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "l2tp";
744f4d0c64aSSam Leffler 	flag_t = flag_l = flag_s = flag_o = FALSE;
745b0453382SBill Fenner 
746*ee67461eSJoseph Mingrone 	if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
747*ee67461eSJoseph Mingrone 		ND_PRINT(" l2tp:");
748*ee67461eSJoseph Mingrone 	} else if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
749*ee67461eSJoseph Mingrone 		ND_PRINT(" l2f:");
750b0453382SBill Fenner 		return;		/* nothing to do */
751b0453382SBill Fenner 	} else {
752*ee67461eSJoseph Mingrone 		ND_PRINT(" Unknown Version, neither L2F(1) nor L2TP(2)");
753b0453382SBill Fenner 		return;		/* nothing we can do */
754b0453382SBill Fenner 	}
755b0453382SBill Fenner 
756*ee67461eSJoseph Mingrone 	ND_PRINT("[");
757*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_TYPE) {
758b0453382SBill Fenner 		flag_t = TRUE;
759*ee67461eSJoseph Mingrone 		ND_PRINT("T");
760b0453382SBill Fenner 	}
761*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_LENGTH) {
762b0453382SBill Fenner 		flag_l = TRUE;
763*ee67461eSJoseph Mingrone 		ND_PRINT("L");
764b0453382SBill Fenner 	}
765*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_SEQUENCE) {
766b0453382SBill Fenner 		flag_s = TRUE;
767*ee67461eSJoseph Mingrone 		ND_PRINT("S");
768b0453382SBill Fenner 	}
769*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_OFFSET) {
770b0453382SBill Fenner 		flag_o = TRUE;
771*ee67461eSJoseph Mingrone 		ND_PRINT("O");
772b0453382SBill Fenner 	}
773*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_PRIORITY)
774*ee67461eSJoseph Mingrone 		ND_PRINT("P");
775*ee67461eSJoseph Mingrone 	ND_PRINT("]");
776b0453382SBill Fenner 
77727df3f5dSRui Paulo 	ptr += 2;
778b0453382SBill Fenner 	cnt += 2;
779b0453382SBill Fenner 
780b0453382SBill Fenner 	if (flag_l) {
781*ee67461eSJoseph Mingrone 		l2tp_len = GET_BE_U_2(ptr);
78227df3f5dSRui Paulo 		ptr += 2;
783b0453382SBill Fenner 		cnt += 2;
784b0453382SBill Fenner 	} else {
785b0453382SBill Fenner 		l2tp_len = 0;
786b0453382SBill Fenner 	}
787*ee67461eSJoseph Mingrone 	/* Tunnel ID */
788*ee67461eSJoseph Mingrone 	ND_PRINT("(%u/", GET_BE_U_2(ptr));
78927df3f5dSRui Paulo 	ptr += 2;
790a90e161bSBill Fenner 	cnt += 2;
791*ee67461eSJoseph Mingrone 	/* Session ID */
792*ee67461eSJoseph Mingrone 	ND_PRINT("%u)",  GET_BE_U_2(ptr));
79327df3f5dSRui Paulo 	ptr += 2;
794a90e161bSBill Fenner 	cnt += 2;
795b0453382SBill Fenner 
796b0453382SBill Fenner 	if (flag_s) {
797*ee67461eSJoseph Mingrone 		ND_PRINT("Ns=%u,", GET_BE_U_2(ptr));
79827df3f5dSRui Paulo 		ptr += 2;
799a90e161bSBill Fenner 		cnt += 2;
800*ee67461eSJoseph Mingrone 		ND_PRINT("Nr=%u",  GET_BE_U_2(ptr));
80127df3f5dSRui Paulo 		ptr += 2;
802a90e161bSBill Fenner 		cnt += 2;
803b0453382SBill Fenner 	}
804b0453382SBill Fenner 
805*ee67461eSJoseph Mingrone 	if (flag_o) {	/* Offset Size */
806*ee67461eSJoseph Mingrone 		pad =  GET_BE_U_2(ptr);
807*ee67461eSJoseph Mingrone 		/* Offset padding octets in packet buffer? */
808*ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(ptr + 2, pad);
80927df3f5dSRui Paulo 		ptr += (2 + pad);
810b0453382SBill Fenner 		cnt += (2 + pad);
811b0453382SBill Fenner 	}
812b0453382SBill Fenner 
813f4d0c64aSSam Leffler 	if (flag_l) {
814f4d0c64aSSam Leffler 		if (length < l2tp_len) {
815*ee67461eSJoseph Mingrone 			ND_PRINT(" Length %u larger than packet", l2tp_len);
816f4d0c64aSSam Leffler 			return;
817f4d0c64aSSam Leffler 		}
818f4d0c64aSSam Leffler 		length = l2tp_len;
819f4d0c64aSSam Leffler 	}
820f4d0c64aSSam Leffler 	if (length < cnt) {
821*ee67461eSJoseph Mingrone 		ND_PRINT(" Length %u smaller than header length", length);
822f4d0c64aSSam Leffler 		return;
823f4d0c64aSSam Leffler 	}
824b0453382SBill Fenner 	if (flag_t) {
825f4d0c64aSSam Leffler 		if (!flag_l) {
826*ee67461eSJoseph Mingrone 			ND_PRINT(" No length");
827f4d0c64aSSam Leffler 			return;
828f4d0c64aSSam Leffler 		}
829b0453382SBill Fenner 		if (length - cnt == 0) {
830*ee67461eSJoseph Mingrone 			ND_PRINT(" ZLB");
831b0453382SBill Fenner 		} else {
83239e421e8SCy Schubert 			/*
83339e421e8SCy Schubert 			 * Print AVPs.
83439e421e8SCy Schubert 			 */
83539e421e8SCy Schubert 			while (length - cnt != 0) {
83639e421e8SCy Schubert 				u_int avp_length;
83739e421e8SCy Schubert 
83839e421e8SCy Schubert 				avp_length = l2tp_avp_print(ndo, ptr, length - cnt);
83939e421e8SCy Schubert 				if (avp_length == 0) {
84039e421e8SCy Schubert 					/*
84139e421e8SCy Schubert 					 * Truncated.
84239e421e8SCy Schubert 					 */
84339e421e8SCy Schubert 					break;
84439e421e8SCy Schubert 				}
84539e421e8SCy Schubert 				cnt += avp_length;
84639e421e8SCy Schubert 				ptr += avp_length;
84739e421e8SCy Schubert 			}
848b0453382SBill Fenner 		}
849b0453382SBill Fenner 	} else {
850*ee67461eSJoseph Mingrone 		ND_PRINT(" {");
8513c602fabSXin LI 		ppp_print(ndo, ptr, length - cnt);
852*ee67461eSJoseph Mingrone 		ND_PRINT("}");
853b0453382SBill Fenner 	}
854a90e161bSBill Fenner 	return;
855a90e161bSBill Fenner trunc:
856*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
857b0453382SBill Fenner }
858