xref: /freebsd/contrib/tcpdump/print-l2tp.c (revision 0bff6a5af8cb6d8e5123f8b667df78cac885dbb7)
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 
26b0453382SBill Fenner #ifdef HAVE_CONFIG_H
27b0453382SBill Fenner #include "config.h"
28b0453382SBill Fenner #endif
29b0453382SBill Fenner 
303340d773SGleb Smirnoff #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 
713c602fabSXin LI static const char tstr[] = " [|l2tp]";
72b0453382SBill Fenner 
73a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
74a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
75a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
76a90e161bSBill Fenner #define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
77a90e161bSBill Fenner #define	L2TP_MSGTYPE_HELLO	6  /* Hello */
78a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
79a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
80a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
81a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
82a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
83a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
84a90e161bSBill Fenner #define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
85a90e161bSBill Fenner #define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
86a90e161bSBill Fenner #define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
87a90e161bSBill Fenner 
883c602fabSXin LI static const struct tok l2tp_msgtype2str[] = {
89a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRQ, 	"SCCRQ" },
90a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
91a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
92a90e161bSBill Fenner 	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
93a90e161bSBill Fenner 	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
94a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
95a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
96a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
97a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
98a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
99a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
100a90e161bSBill Fenner 	{ L2TP_MSGTYPE_CDN,	"CDN" },
101a90e161bSBill Fenner 	{ L2TP_MSGTYPE_WEN,	"WEN" },
102a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SLI,	"SLI" },
103a90e161bSBill Fenner 	{ 0,			NULL }
104b0453382SBill Fenner };
105b0453382SBill Fenner 
106a90e161bSBill Fenner #define L2TP_AVP_MSGTYPE		0  /* Message Type */
107a90e161bSBill Fenner #define L2TP_AVP_RESULT_CODE		1  /* Result Code */
108a90e161bSBill Fenner #define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
109a90e161bSBill Fenner #define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
110a90e161bSBill Fenner #define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
111a90e161bSBill Fenner #define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
112a90e161bSBill Fenner #define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
113a90e161bSBill Fenner #define L2TP_AVP_HOST_NAME		7  /* Host Name */
114a90e161bSBill Fenner #define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
115a90e161bSBill Fenner #define L2TP_AVP_ASSND_TUN_ID 		9  /* Assigned Tunnel ID */
116a90e161bSBill Fenner #define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
117a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE		11 /* Challenge */
118a90e161bSBill Fenner #define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
119a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
120a90e161bSBill Fenner #define L2TP_AVP_ASSND_SESS_ID  	14 /* Assigned Session ID */
121a90e161bSBill Fenner #define L2TP_AVP_CALL_SER_NUM 		15 /* Call Serial Number */
122a90e161bSBill Fenner #define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
123a90e161bSBill Fenner #define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
124a90e161bSBill Fenner #define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
125a90e161bSBill Fenner #define L2TP_AVP_FRAMING_TYPE 		19 /* Framing Type */
126a90e161bSBill Fenner #define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
127a90e161bSBill Fenner #define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
128a90e161bSBill Fenner #define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
129a90e161bSBill Fenner #define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
130a90e161bSBill Fenner #define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
131a90e161bSBill Fenner #define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
132a90e161bSBill Fenner #define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
133a90e161bSBill Fenner #define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
134a90e161bSBill Fenner #define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
135a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
136a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
137a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
138a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
139a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
140a90e161bSBill Fenner #define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
141a90e161bSBill Fenner #define L2TP_AVP_ACCM			35 /* ACCM */
142a90e161bSBill Fenner #define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
143a90e161bSBill Fenner #define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
144a90e161bSBill Fenner #define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
145a90e161bSBill Fenner #define L2TP_AVP_SEQ_REQUIRED 		39 /* Sequencing Required */
146a90e161bSBill Fenner #define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code */
147b0453382SBill Fenner 
1483c602fabSXin LI static const struct tok l2tp_avp2str[] = {
149a90e161bSBill Fenner 	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
150a90e161bSBill Fenner 	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
151a90e161bSBill Fenner 	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
152a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
153a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
154a90e161bSBill Fenner 	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
155a90e161bSBill Fenner 	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
156a90e161bSBill Fenner 	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
157a90e161bSBill Fenner 	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
158a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
159a90e161bSBill Fenner 	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
160a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
161a90e161bSBill Fenner 	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
162a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
163a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
164a90e161bSBill Fenner 	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
165a90e161bSBill Fenner 	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
166a90e161bSBill Fenner 	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
167a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
168a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
169a90e161bSBill Fenner 	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
170a90e161bSBill Fenner 	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
171a90e161bSBill Fenner 	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
172a90e161bSBill Fenner 	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
173a90e161bSBill Fenner 	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
174a90e161bSBill Fenner 	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
175a90e161bSBill Fenner 	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
176a90e161bSBill Fenner 	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
177a90e161bSBill Fenner 	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
178a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
179a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
180a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
181a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
182a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
183a90e161bSBill Fenner 	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
184a90e161bSBill Fenner 	{ L2TP_AVP_ACCM,		"ACCM" },
185a90e161bSBill Fenner 	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
186a90e161bSBill Fenner 	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
187a90e161bSBill Fenner 	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
188a90e161bSBill Fenner 	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
189a90e161bSBill Fenner 	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
190a90e161bSBill Fenner 	{ 0,				NULL }
191a90e161bSBill Fenner };
192a90e161bSBill Fenner 
1933c602fabSXin LI static const struct tok l2tp_authentype2str[] = {
194a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
195a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
196a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
197a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
198a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
199a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
200a90e161bSBill Fenner 	{ 0,				NULL }
201a90e161bSBill Fenner };
202a90e161bSBill Fenner 
203a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
204a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
205a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
206a90e161bSBill Fenner 
2073c602fabSXin LI static const struct tok l2tp_cc_direction2str[] = {
208a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
209a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
210a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
211a90e161bSBill Fenner 	{ 0,					NULL }
212b0453382SBill Fenner };
213b0453382SBill Fenner 
214b0453382SBill Fenner #if 0
215b0453382SBill Fenner static char *l2tp_result_code_StopCCN[] = {
216b0453382SBill Fenner          "Reserved",
217b0453382SBill Fenner          "General request to clear control connection",
218b0453382SBill Fenner          "General error--Error Code indicates the problem",
219b0453382SBill Fenner          "Control channel already exists",
220b0453382SBill Fenner          "Requester is not authorized to establish a control channel",
221b0453382SBill Fenner          "The protocol version of the requester is not supported",
222b0453382SBill Fenner          "Requester is being shut down",
223b0453382SBill Fenner          "Finite State Machine error"
224b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
225b0453382SBill Fenner };
226b0453382SBill Fenner #endif
227b0453382SBill Fenner 
228b0453382SBill Fenner #if 0
229b0453382SBill Fenner static char *l2tp_result_code_CDN[] = {
230b0453382SBill Fenner 	"Reserved",
231b0453382SBill Fenner 	"Call disconnected due to loss of carrier",
232b0453382SBill Fenner 	"Call disconnected for the reason indicated in error code",
233b0453382SBill Fenner 	"Call disconnected for administrative reasons",
234b0453382SBill Fenner 	"Call failed due to lack of appropriate facilities being " \
235b0453382SBill Fenner 	"available (temporary condition)",
236b0453382SBill Fenner 	"Call failed due to lack of appropriate facilities being " \
237b0453382SBill Fenner 	"available (permanent condition)",
238b0453382SBill Fenner 	"Invalid destination",
239b0453382SBill Fenner 	"Call failed due to no carrier detected",
240b0453382SBill Fenner 	"Call failed due to detection of a busy signal",
241b0453382SBill Fenner 	"Call failed due to lack of a dial tone",
242b0453382SBill Fenner 	"Call was not established within time allotted by LAC",
243b0453382SBill Fenner 	"Call was connected but no appropriate framing was detected"
244b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
245b0453382SBill Fenner };
246b0453382SBill Fenner #endif
247b0453382SBill Fenner 
248b0453382SBill Fenner #if 0
249b0453382SBill Fenner static char *l2tp_error_code_general[] = {
250b0453382SBill Fenner 	"No general error",
251b0453382SBill Fenner 	"No control connection exists yet for this LAC-LNS pair",
252b0453382SBill Fenner 	"Length is wrong",
253b0453382SBill Fenner 	"One of the field values was out of range or " \
254b0453382SBill Fenner 	"reserved field was non-zero"
255b0453382SBill Fenner 	"Insufficient resources to handle this operation now",
256b0453382SBill Fenner 	"The Session ID is invalid in this context",
257b0453382SBill Fenner 	"A generic vendor-specific error occurred in the LAC",
258b0453382SBill Fenner 	"Try another"
259b0453382SBill Fenner #define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
260b0453382SBill Fenner };
261b0453382SBill Fenner #endif
262b0453382SBill Fenner 
263b0453382SBill Fenner /******************************/
264b0453382SBill Fenner /* generic print out routines */
265b0453382SBill Fenner /******************************/
266b0453382SBill Fenner static void
2673c602fabSXin LI print_string(netdissect_options *ndo, const u_char *dat, u_int length)
268b0453382SBill Fenner {
2695b0fe478SBruce M Simpson 	u_int i;
270b0453382SBill Fenner 	for (i=0; i<length; i++) {
2713c602fabSXin LI 		ND_PRINT((ndo, "%c", *dat++));
272b0453382SBill Fenner 	}
273b0453382SBill Fenner }
274b0453382SBill Fenner 
275b0453382SBill Fenner static void
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++) {
2803c602fabSXin LI 		ND_PRINT((ndo, "%02x", *dat++));
281b0453382SBill Fenner 	}
282b0453382SBill Fenner }
283b0453382SBill Fenner 
284b0453382SBill Fenner static void
2853c602fabSXin LI print_16bits_val(netdissect_options *ndo, const uint16_t *dat)
286b0453382SBill Fenner {
2873c602fabSXin LI 	ND_PRINT((ndo, "%u", EXTRACT_16BITS(dat)));
288b0453382SBill Fenner }
289b0453382SBill Fenner 
290b0453382SBill Fenner static void
2913c602fabSXin LI print_32bits_val(netdissect_options *ndo, const uint32_t *dat)
292b0453382SBill Fenner {
2933c602fabSXin LI 	ND_PRINT((ndo, "%lu", (u_long)EXTRACT_32BITS(dat)));
294b0453382SBill Fenner }
295b0453382SBill Fenner 
296a90e161bSBill Fenner /***********************************/
297b0453382SBill Fenner /* AVP-specific print out routines */
298a90e161bSBill Fenner /***********************************/
299b0453382SBill Fenner static void
300*0bff6a5aSEd Maste l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length)
301b0453382SBill Fenner {
3023340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
303b0453382SBill Fenner 
304*0bff6a5aSEd Maste 	if (length < 2) {
305*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
306*0bff6a5aSEd Maste 		return;
307*0bff6a5aSEd Maste 	}
3083c602fabSXin LI 	ND_PRINT((ndo, "%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
3093c602fabSXin LI 	    EXTRACT_16BITS(ptr))));
310b0453382SBill Fenner }
311b0453382SBill Fenner 
312b0453382SBill Fenner static void
3133c602fabSXin LI l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length)
314b0453382SBill Fenner {
3153340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
316b0453382SBill Fenner 
317*0bff6a5aSEd Maste 	/* Result Code */
318*0bff6a5aSEd Maste 	if (length < 2) {
319*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
320*0bff6a5aSEd Maste 		return;
321a90e161bSBill Fenner 	}
322*0bff6a5aSEd Maste 	ND_PRINT((ndo, "%u", EXTRACT_16BITS(ptr)));
323*0bff6a5aSEd Maste 	ptr++;
324*0bff6a5aSEd Maste 	length -= 2;
325*0bff6a5aSEd Maste 
326*0bff6a5aSEd Maste 	/* Error Code (opt) */
327*0bff6a5aSEd Maste 	if (length == 0)
328*0bff6a5aSEd Maste 		return;
329*0bff6a5aSEd Maste 	if (length < 2) {
330*0bff6a5aSEd Maste 		ND_PRINT((ndo, " AVP too short"));
331*0bff6a5aSEd Maste 		return;
332*0bff6a5aSEd Maste 	}
333*0bff6a5aSEd Maste 	ND_PRINT((ndo, "/%u", EXTRACT_16BITS(ptr)));
334*0bff6a5aSEd Maste 	ptr++;
335*0bff6a5aSEd Maste 	length -= 2;
336*0bff6a5aSEd Maste 
337*0bff6a5aSEd Maste 	/* Error Message (opt) */
338*0bff6a5aSEd Maste 	if (length == 0)
339*0bff6a5aSEd Maste 		return;
3403c602fabSXin LI 	ND_PRINT((ndo, " "));
341*0bff6a5aSEd Maste 	print_string(ndo, (const u_char *)ptr, length);
342b0453382SBill Fenner }
343b0453382SBill Fenner 
344b0453382SBill Fenner static void
345*0bff6a5aSEd Maste l2tp_proto_ver_print(netdissect_options *ndo, const uint16_t *dat, u_int length)
346b0453382SBill Fenner {
347*0bff6a5aSEd Maste 	if (length < 2) {
348*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
349*0bff6a5aSEd Maste 		return;
350*0bff6a5aSEd Maste 	}
3513c602fabSXin LI 	ND_PRINT((ndo, "%u.%u", (EXTRACT_16BITS(dat) >> 8),
3523c602fabSXin LI 	    (EXTRACT_16BITS(dat) & 0xff)));
353b0453382SBill Fenner }
354b0453382SBill Fenner 
355b0453382SBill Fenner static void
356*0bff6a5aSEd Maste l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
357b0453382SBill Fenner {
3583340d773SGleb Smirnoff 	const uint32_t *ptr = (const uint32_t *)dat;
359b0453382SBill Fenner 
360*0bff6a5aSEd Maste 	if (length < 4) {
361*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
362*0bff6a5aSEd Maste 		return;
363*0bff6a5aSEd Maste 	}
3649afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
3653c602fabSXin LI 		ND_PRINT((ndo, "A"));
366b0453382SBill Fenner 	}
3679afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_SYNC_MASK) {
3683c602fabSXin LI 		ND_PRINT((ndo, "S"));
369b0453382SBill Fenner 	}
370b0453382SBill Fenner }
371b0453382SBill Fenner 
372b0453382SBill Fenner static void
373*0bff6a5aSEd Maste l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
374b0453382SBill Fenner {
3753340d773SGleb Smirnoff 	const uint32_t *ptr = (const uint32_t *)dat;
376b0453382SBill Fenner 
377*0bff6a5aSEd Maste 	if (length < 4) {
378*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
379*0bff6a5aSEd Maste 		return;
380*0bff6a5aSEd Maste 	}
3819afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_ANALOG_MASK) {
3823c602fabSXin LI 		ND_PRINT((ndo, "A"));
383b0453382SBill Fenner 	}
3849afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
3853c602fabSXin LI 		ND_PRINT((ndo, "D"));
386b0453382SBill Fenner 	}
387b0453382SBill Fenner }
388b0453382SBill Fenner 
389b0453382SBill Fenner static void
3903c602fabSXin LI l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
391b0453382SBill Fenner {
392*0bff6a5aSEd Maste 	if (length < 3) {
393*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
394*0bff6a5aSEd Maste 		return;
395*0bff6a5aSEd Maste 	}
3963340d773SGleb Smirnoff 	print_16bits_val(ndo, (const uint16_t *)dat);
3973c602fabSXin LI 	ND_PRINT((ndo, ", %02x", dat[2]));
398*0bff6a5aSEd Maste 	dat += 3;
399*0bff6a5aSEd Maste 	length -= 3;
400*0bff6a5aSEd Maste 	if (length != 0) {
4013c602fabSXin LI 		ND_PRINT((ndo, " "));
402*0bff6a5aSEd Maste 		print_string(ndo, dat, length);
403b0453382SBill Fenner 	}
404b0453382SBill Fenner }
405b0453382SBill Fenner 
406b0453382SBill Fenner static void
407*0bff6a5aSEd Maste l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
408b0453382SBill Fenner {
4093340d773SGleb Smirnoff 	const uint32_t *ptr = (const uint32_t *)dat;
410b0453382SBill Fenner 
411*0bff6a5aSEd Maste 	if (length < 4) {
412*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
413*0bff6a5aSEd Maste 		return;
414*0bff6a5aSEd Maste 	}
4159afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
4163c602fabSXin LI 		ND_PRINT((ndo, "A"));
417b0453382SBill Fenner 	}
4189afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
4193c602fabSXin LI 		ND_PRINT((ndo, "D"));
420b0453382SBill Fenner 	}
421b0453382SBill Fenner }
422b0453382SBill Fenner 
423b0453382SBill Fenner static void
424*0bff6a5aSEd Maste l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
425b0453382SBill Fenner {
4263340d773SGleb Smirnoff 	const uint32_t *ptr = (const uint32_t *)dat;
427b0453382SBill Fenner 
428*0bff6a5aSEd Maste 	if (length < 4) {
429*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
430*0bff6a5aSEd Maste 		return;
431*0bff6a5aSEd Maste 	}
4329afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
4333c602fabSXin LI 		ND_PRINT((ndo, "A"));
434b0453382SBill Fenner 	}
4359afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
4363c602fabSXin LI 		ND_PRINT((ndo, "S"));
437b0453382SBill Fenner 	}
438b0453382SBill Fenner }
439b0453382SBill Fenner 
440b0453382SBill Fenner static void
4413c602fabSXin LI l2tp_packet_proc_delay_print(netdissect_options *ndo)
442b0453382SBill Fenner {
4433c602fabSXin LI 	ND_PRINT((ndo, "obsolete"));
444b0453382SBill Fenner }
445b0453382SBill Fenner 
446b0453382SBill Fenner static void
447*0bff6a5aSEd Maste l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
448b0453382SBill Fenner {
4493340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
450a90e161bSBill Fenner 
451*0bff6a5aSEd Maste 	if (length < 2) {
452*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
453*0bff6a5aSEd Maste 		return;
454*0bff6a5aSEd Maste 	}
4553c602fabSXin LI 	ND_PRINT((ndo, "%s", tok2str(l2tp_authentype2str,
4563c602fabSXin LI 			     "AuthType-#%u", EXTRACT_16BITS(ptr))));
457b0453382SBill Fenner }
458b0453382SBill Fenner 
459b0453382SBill Fenner static void
460*0bff6a5aSEd Maste l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length)
461b0453382SBill Fenner {
4623340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
463b0453382SBill Fenner 
464*0bff6a5aSEd Maste 	if (length < 2) {
465*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
466*0bff6a5aSEd Maste 		return;
467*0bff6a5aSEd Maste 	}
4683c602fabSXin LI 	ND_PRINT((ndo, "%u", EXTRACT_16BITS(ptr) & L2TP_PROXY_AUTH_ID_MASK));
469b0453382SBill Fenner }
470b0453382SBill Fenner 
471b0453382SBill Fenner static void
472*0bff6a5aSEd Maste l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length)
473b0453382SBill Fenner {
4743340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
4753c602fabSXin LI 	uint16_t val_h, val_l;
476a90e161bSBill Fenner 
477*0bff6a5aSEd Maste 	if (length < 2) {
478*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
479*0bff6a5aSEd Maste 		return;
480*0bff6a5aSEd Maste 	}
481a90e161bSBill Fenner 	ptr++;		/* skip "Reserved" */
482*0bff6a5aSEd Maste 	length -= 2;
483a90e161bSBill Fenner 
484*0bff6a5aSEd Maste 	if (length < 4) {
485*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
486*0bff6a5aSEd Maste 		return;
487*0bff6a5aSEd Maste 	}
488*0bff6a5aSEd Maste 	val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2;
489*0bff6a5aSEd Maste 	val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2;
4903c602fabSXin LI 	ND_PRINT((ndo, "CRCErr=%u ", (val_h<<16) + val_l));
491a90e161bSBill Fenner 
492*0bff6a5aSEd Maste 	if (length < 4) {
493*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
494*0bff6a5aSEd Maste 		return;
495*0bff6a5aSEd Maste 	}
496*0bff6a5aSEd Maste 	val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2;
497*0bff6a5aSEd Maste 	val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2;
4983c602fabSXin LI 	ND_PRINT((ndo, "FrameErr=%u ", (val_h<<16) + val_l));
499a90e161bSBill Fenner 
500*0bff6a5aSEd Maste 	if (length < 4) {
501*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
502*0bff6a5aSEd Maste 		return;
503*0bff6a5aSEd Maste 	}
504*0bff6a5aSEd Maste 	val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2;
505*0bff6a5aSEd Maste 	val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2;
5063c602fabSXin LI 	ND_PRINT((ndo, "HardOver=%u ", (val_h<<16) + val_l));
507a90e161bSBill Fenner 
508*0bff6a5aSEd Maste 	if (length < 4) {
509*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
510*0bff6a5aSEd Maste 		return;
511*0bff6a5aSEd Maste 	}
512*0bff6a5aSEd Maste 	val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2;
513*0bff6a5aSEd Maste 	val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2;
5143c602fabSXin LI 	ND_PRINT((ndo, "BufOver=%u ", (val_h<<16) + val_l));
515a90e161bSBill Fenner 
516*0bff6a5aSEd Maste 	if (length < 4) {
517*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
518*0bff6a5aSEd Maste 		return;
519*0bff6a5aSEd Maste 	}
520*0bff6a5aSEd Maste 	val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2;
521*0bff6a5aSEd Maste 	val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2;
5223c602fabSXin LI 	ND_PRINT((ndo, "Timeout=%u ", (val_h<<16) + val_l));
523a90e161bSBill Fenner 
524*0bff6a5aSEd Maste 	if (length < 4) {
525*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
526*0bff6a5aSEd Maste 		return;
527*0bff6a5aSEd Maste 	}
5289afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
5299afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
5303c602fabSXin LI 	ND_PRINT((ndo, "AlignErr=%u ", (val_h<<16) + val_l));
531b0453382SBill Fenner }
532b0453382SBill Fenner 
533b0453382SBill Fenner static void
534*0bff6a5aSEd Maste l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length)
535b0453382SBill Fenner {
5363340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
5373c602fabSXin LI 	uint16_t val_h, val_l;
538b0453382SBill Fenner 
539*0bff6a5aSEd Maste 	if (length < 2) {
540*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
541*0bff6a5aSEd Maste 		return;
542*0bff6a5aSEd Maste 	}
543a90e161bSBill Fenner 	ptr++;		/* skip "Reserved" */
544*0bff6a5aSEd Maste 	length -= 2;
545a90e161bSBill Fenner 
546*0bff6a5aSEd Maste 	if (length < 4) {
547*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
548*0bff6a5aSEd Maste 		return;
549*0bff6a5aSEd Maste 	}
550*0bff6a5aSEd Maste 	val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2;
551*0bff6a5aSEd Maste 	val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2;
5523c602fabSXin LI 	ND_PRINT((ndo, "send=%08x ", (val_h<<16) + val_l));
553a90e161bSBill Fenner 
554*0bff6a5aSEd Maste 	if (length < 4) {
555*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
556*0bff6a5aSEd Maste 		return;
557*0bff6a5aSEd Maste 	}
5589afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
5599afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
5603c602fabSXin LI 	ND_PRINT((ndo, "recv=%08x ", (val_h<<16) + val_l));
561b0453382SBill Fenner }
562b0453382SBill Fenner 
563b0453382SBill Fenner static void
5643c602fabSXin LI l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
565b0453382SBill Fenner {
5663340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
567b0453382SBill Fenner 
568*0bff6a5aSEd Maste 	if (length < 5) {
569*0bff6a5aSEd Maste 		ND_PRINT((ndo, "AVP too short"));
570*0bff6a5aSEd Maste 		return;
571*0bff6a5aSEd Maste 	}
572*0bff6a5aSEd Maste 	/* Disconnect Code */
573*0bff6a5aSEd Maste 	ND_PRINT((ndo, "%04x, ", EXTRACT_16BITS(dat)));
574*0bff6a5aSEd Maste 	dat += 2;
575*0bff6a5aSEd Maste 	length -= 2;
576*0bff6a5aSEd Maste 	/* Control Protocol Number */
577*0bff6a5aSEd Maste 	ND_PRINT((ndo, "%04x ",  EXTRACT_16BITS(dat)));
578*0bff6a5aSEd Maste 	dat += 2;
579*0bff6a5aSEd Maste 	length -= 2;
580*0bff6a5aSEd Maste 	/* Direction */
5813c602fabSXin LI 	ND_PRINT((ndo, "%s", tok2str(l2tp_cc_direction2str,
582*0bff6a5aSEd Maste 			     "Direction-#%u", EXTRACT_8BITS(ptr))));
583*0bff6a5aSEd Maste 	ptr++;
584*0bff6a5aSEd Maste 	length--;
585a90e161bSBill Fenner 
586*0bff6a5aSEd Maste 	if (length != 0) {
5873c602fabSXin LI 		ND_PRINT((ndo, " "));
588*0bff6a5aSEd Maste 		print_string(ndo, (const u_char *)ptr, length);
589a90e161bSBill Fenner 	}
590b0453382SBill Fenner }
591b0453382SBill Fenner 
592b0453382SBill Fenner static void
5933c602fabSXin LI l2tp_avp_print(netdissect_options *ndo, const u_char *dat, int length)
594b0453382SBill Fenner {
595a90e161bSBill Fenner 	u_int len;
5963340d773SGleb Smirnoff 	const uint16_t *ptr = (const uint16_t *)dat;
5973c602fabSXin LI 	uint16_t attr_type;
598a90e161bSBill Fenner 	int hidden = FALSE;
599b0453382SBill Fenner 
600a90e161bSBill Fenner 	if (length <= 0) {
601b0453382SBill Fenner 		return;
602b0453382SBill Fenner 	}
603b0453382SBill Fenner 
6043c602fabSXin LI 	ND_PRINT((ndo, " "));
605a90e161bSBill Fenner 
6063c602fabSXin LI 	ND_TCHECK(*ptr);	/* Flags & Length */
6079afd0c29SBill Fenner 	len = EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_LEN_MASK;
608a90e161bSBill Fenner 
609b97c9af5SBill Fenner 	/* If it is not long enough to contain the header, we'll give up. */
610b97c9af5SBill Fenner 	if (len < 6)
611b97c9af5SBill Fenner 		goto trunc;
612b97c9af5SBill Fenner 
613b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the packet,
614b97c9af5SBill Fenner 	   we'll give up. */
615b97c9af5SBill Fenner 	if (len > (u_int)length)
616b97c9af5SBill Fenner 		goto trunc;
617b97c9af5SBill Fenner 
618b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the captured
619b97c9af5SBill Fenner 	   data, we'll give up. */
6203c602fabSXin LI 	ND_TCHECK2(*ptr, len);
621*0bff6a5aSEd Maste 
622*0bff6a5aSEd Maste 	/*
623*0bff6a5aSEd Maste 	 * After this point, we don't need to check whether we go past
624*0bff6a5aSEd Maste 	 * the length of the captured data; however, we *do* need to
625*0bff6a5aSEd Maste 	 * check whether we go past the end of the AVP.
626*0bff6a5aSEd Maste 	 */
627a90e161bSBill Fenner 
6289afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
6293c602fabSXin LI 		ND_PRINT((ndo, "*"));
630b0453382SBill Fenner 	}
6319afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
632b0453382SBill Fenner 		hidden = TRUE;
6333c602fabSXin LI 		ND_PRINT((ndo, "?"));
634b0453382SBill Fenner 	}
635b0453382SBill Fenner 	ptr++;
636b0453382SBill Fenner 
6379afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr)) {
638685295f4SBill Fenner 		/* Vendor Specific Attribute */
6393c602fabSXin LI 	        ND_PRINT((ndo, "VENDOR%04x:", EXTRACT_16BITS(ptr))); ptr++;
6403c602fabSXin LI 		ND_PRINT((ndo, "ATTR%04x", EXTRACT_16BITS(ptr))); ptr++;
6413c602fabSXin LI 		ND_PRINT((ndo, "("));
6423340d773SGleb Smirnoff 		print_octets(ndo, (const u_char *)ptr, len-6);
6433c602fabSXin LI 		ND_PRINT((ndo, ")"));
644685295f4SBill Fenner 	} else {
645a90e161bSBill Fenner 		/* IETF-defined Attributes */
646685295f4SBill Fenner 		ptr++;
6479afd0c29SBill Fenner 		attr_type = EXTRACT_16BITS(ptr); ptr++;
6483c602fabSXin LI 		ND_PRINT((ndo, "%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type)));
6493c602fabSXin LI 		ND_PRINT((ndo, "("));
650a90e161bSBill Fenner 		if (hidden) {
6513c602fabSXin LI 			ND_PRINT((ndo, "???"));
652a90e161bSBill Fenner 		} else {
653a90e161bSBill Fenner 			switch (attr_type) {
654a90e161bSBill Fenner 			case L2TP_AVP_MSGTYPE:
655*0bff6a5aSEd Maste 				l2tp_msgtype_print(ndo, (const u_char *)ptr, len-6);
656a90e161bSBill Fenner 				break;
657a90e161bSBill Fenner 			case L2TP_AVP_RESULT_CODE:
6583340d773SGleb Smirnoff 				l2tp_result_code_print(ndo, (const u_char *)ptr, len-6);
659a90e161bSBill Fenner 				break;
660a90e161bSBill Fenner 			case L2TP_AVP_PROTO_VER:
661*0bff6a5aSEd Maste 				l2tp_proto_ver_print(ndo, ptr, len-6);
662a90e161bSBill Fenner 				break;
663a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_CAP:
664*0bff6a5aSEd Maste 				l2tp_framing_cap_print(ndo, (const u_char *)ptr, len-6);
665a90e161bSBill Fenner 				break;
666a90e161bSBill Fenner 			case L2TP_AVP_BEARER_CAP:
667*0bff6a5aSEd Maste 				l2tp_bearer_cap_print(ndo, (const u_char *)ptr, len-6);
668a90e161bSBill Fenner 				break;
669a90e161bSBill Fenner 			case L2TP_AVP_TIE_BREAKER:
670*0bff6a5aSEd Maste 				if (len-6 < 8) {
671*0bff6a5aSEd Maste 					ND_PRINT((ndo, "AVP too short"));
672*0bff6a5aSEd Maste 					break;
673*0bff6a5aSEd Maste 				}
6743340d773SGleb Smirnoff 				print_octets(ndo, (const u_char *)ptr, 8);
675a90e161bSBill Fenner 				break;
676a90e161bSBill Fenner 			case L2TP_AVP_FIRM_VER:
677a90e161bSBill Fenner 			case L2TP_AVP_ASSND_TUN_ID:
678a90e161bSBill Fenner 			case L2TP_AVP_RECV_WIN_SIZE:
679a90e161bSBill Fenner 			case L2TP_AVP_ASSND_SESS_ID:
680*0bff6a5aSEd Maste 				if (len-6 < 2) {
681*0bff6a5aSEd Maste 					ND_PRINT((ndo, "AVP too short"));
682*0bff6a5aSEd Maste 					break;
683*0bff6a5aSEd Maste 				}
6843c602fabSXin LI 				print_16bits_val(ndo, ptr);
685a90e161bSBill Fenner 				break;
686a90e161bSBill Fenner 			case L2TP_AVP_HOST_NAME:
687a90e161bSBill Fenner 			case L2TP_AVP_VENDOR_NAME:
688a90e161bSBill Fenner 			case L2TP_AVP_CALLING_NUMBER:
689a90e161bSBill Fenner 			case L2TP_AVP_CALLED_NUMBER:
690a90e161bSBill Fenner 			case L2TP_AVP_SUB_ADDRESS:
691a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_NAME:
692a90e161bSBill Fenner 			case L2TP_AVP_PRIVATE_GRP_ID:
6933340d773SGleb Smirnoff 				print_string(ndo, (const u_char *)ptr, len-6);
694a90e161bSBill Fenner 				break;
695a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE:
696a90e161bSBill Fenner 			case L2TP_AVP_INI_RECV_LCP:
697a90e161bSBill Fenner 			case L2TP_AVP_LAST_SENT_LCP:
698a90e161bSBill Fenner 			case L2TP_AVP_LAST_RECV_LCP:
699a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_CHAL:
700a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_RESP:
701a90e161bSBill Fenner 			case L2TP_AVP_RANDOM_VECTOR:
7023340d773SGleb Smirnoff 				print_octets(ndo, (const u_char *)ptr, len-6);
703a90e161bSBill Fenner 				break;
704a90e161bSBill Fenner 			case L2TP_AVP_Q931_CC:
7053340d773SGleb Smirnoff 				l2tp_q931_cc_print(ndo, (const u_char *)ptr, len-6);
706a90e161bSBill Fenner 				break;
707a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE_RESP:
708*0bff6a5aSEd Maste 				if (len-6 < 16) {
709*0bff6a5aSEd Maste 					ND_PRINT((ndo, "AVP too short"));
710*0bff6a5aSEd Maste 					break;
711*0bff6a5aSEd Maste 				}
7123340d773SGleb Smirnoff 				print_octets(ndo, (const u_char *)ptr, 16);
713a90e161bSBill Fenner 				break;
714a90e161bSBill Fenner 			case L2TP_AVP_CALL_SER_NUM:
715a90e161bSBill Fenner 			case L2TP_AVP_MINIMUM_BPS:
716a90e161bSBill Fenner 			case L2TP_AVP_MAXIMUM_BPS:
717a90e161bSBill Fenner 			case L2TP_AVP_TX_CONN_SPEED:
718a90e161bSBill Fenner 			case L2TP_AVP_PHY_CHANNEL_ID:
719a90e161bSBill Fenner 			case L2TP_AVP_RX_CONN_SPEED:
720*0bff6a5aSEd Maste 				if (len-6 < 4) {
721*0bff6a5aSEd Maste 					ND_PRINT((ndo, "AVP too short"));
722*0bff6a5aSEd Maste 					break;
723*0bff6a5aSEd Maste 				}
7243340d773SGleb Smirnoff 				print_32bits_val(ndo, (const uint32_t *)ptr);
725a90e161bSBill Fenner 				break;
726a90e161bSBill Fenner 			case L2TP_AVP_BEARER_TYPE:
727*0bff6a5aSEd Maste 				l2tp_bearer_type_print(ndo, (const u_char *)ptr, len-6);
728a90e161bSBill Fenner 				break;
729a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_TYPE:
730*0bff6a5aSEd Maste 				l2tp_framing_type_print(ndo, (const u_char *)ptr, len-6);
731a90e161bSBill Fenner 				break;
732a90e161bSBill Fenner 			case L2TP_AVP_PACKET_PROC_DELAY:
7333c602fabSXin LI 				l2tp_packet_proc_delay_print(ndo);
734a90e161bSBill Fenner 				break;
735a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_TYPE:
736*0bff6a5aSEd Maste 				l2tp_proxy_auth_type_print(ndo, (const u_char *)ptr, len-6);
737a90e161bSBill Fenner 				break;
738a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_ID:
739*0bff6a5aSEd Maste 				l2tp_proxy_auth_id_print(ndo, (const u_char *)ptr, len-6);
740a90e161bSBill Fenner 				break;
741a90e161bSBill Fenner 			case L2TP_AVP_CALL_ERRORS:
742*0bff6a5aSEd Maste 				l2tp_call_errors_print(ndo, (const u_char *)ptr, len-6);
743a90e161bSBill Fenner 				break;
744a90e161bSBill Fenner 			case L2TP_AVP_ACCM:
745*0bff6a5aSEd Maste 				l2tp_accm_print(ndo, (const u_char *)ptr, len-6);
746a90e161bSBill Fenner 				break;
747a90e161bSBill Fenner 			case L2TP_AVP_SEQ_REQUIRED:
748a90e161bSBill Fenner 				break;	/* No Attribute Value */
749a90e161bSBill Fenner 			case L2TP_AVP_PPP_DISCON_CC:
7503340d773SGleb Smirnoff 				l2tp_ppp_discon_cc_print(ndo, (const u_char *)ptr, len-6);
751a90e161bSBill Fenner 				break;
752a90e161bSBill Fenner 			default:
753a90e161bSBill Fenner 				break;
754a90e161bSBill Fenner 			}
755b0453382SBill Fenner 		}
7563c602fabSXin LI 		ND_PRINT((ndo, ")"));
757685295f4SBill Fenner 	}
758b0453382SBill Fenner 
7593c602fabSXin LI 	l2tp_avp_print(ndo, dat+len, length-len);
760b0453382SBill Fenner 	return;
761a90e161bSBill Fenner 
762a90e161bSBill Fenner  trunc:
7633c602fabSXin LI 	ND_PRINT((ndo, "|..."));
764b0453382SBill Fenner }
765b0453382SBill Fenner 
766b0453382SBill Fenner 
767b0453382SBill Fenner void
7683c602fabSXin LI l2tp_print(netdissect_options *ndo, const u_char *dat, u_int length)
769b0453382SBill Fenner {
77027df3f5dSRui Paulo 	const u_char *ptr = dat;
771b0453382SBill Fenner 	u_int cnt = 0;			/* total octets consumed */
7723c602fabSXin LI 	uint16_t pad;
773f4d0c64aSSam Leffler 	int flag_t, flag_l, flag_s, flag_o;
7743c602fabSXin LI 	uint16_t l2tp_len;
775b0453382SBill Fenner 
776f4d0c64aSSam Leffler 	flag_t = flag_l = flag_s = flag_o = FALSE;
777b0453382SBill Fenner 
7783c602fabSXin LI 	ND_TCHECK2(*ptr, 2);	/* Flags & Version */
7799afd0c29SBill Fenner 	if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
7803c602fabSXin LI 		ND_PRINT((ndo, " l2tp:"));
7819afd0c29SBill Fenner 	} else if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
7823c602fabSXin LI 		ND_PRINT((ndo, " l2f:"));
783b0453382SBill Fenner 		return;		/* nothing to do */
784b0453382SBill Fenner 	} else {
7853c602fabSXin LI 		ND_PRINT((ndo, " Unknown Version, neither L2F(1) nor L2TP(2)"));
786b0453382SBill Fenner 		return;		/* nothing we can do */
787b0453382SBill Fenner 	}
788b0453382SBill Fenner 
7893c602fabSXin LI 	ND_PRINT((ndo, "["));
7909afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_TYPE) {
791b0453382SBill Fenner 		flag_t = TRUE;
7923c602fabSXin LI 		ND_PRINT((ndo, "T"));
793b0453382SBill Fenner 	}
7949afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_LENGTH) {
795b0453382SBill Fenner 		flag_l = TRUE;
7963c602fabSXin LI 		ND_PRINT((ndo, "L"));
797b0453382SBill Fenner 	}
7989afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_SEQUENCE) {
799b0453382SBill Fenner 		flag_s = TRUE;
8003c602fabSXin LI 		ND_PRINT((ndo, "S"));
801b0453382SBill Fenner 	}
8029afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_OFFSET) {
803b0453382SBill Fenner 		flag_o = TRUE;
8043c602fabSXin LI 		ND_PRINT((ndo, "O"));
805b0453382SBill Fenner 	}
806f4d0c64aSSam Leffler 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_PRIORITY)
8073c602fabSXin LI 		ND_PRINT((ndo, "P"));
8083c602fabSXin LI 	ND_PRINT((ndo, "]"));
809b0453382SBill Fenner 
81027df3f5dSRui Paulo 	ptr += 2;
811b0453382SBill Fenner 	cnt += 2;
812b0453382SBill Fenner 
813b0453382SBill Fenner 	if (flag_l) {
8143c602fabSXin LI 		ND_TCHECK2(*ptr, 2);	/* Length */
81527df3f5dSRui Paulo 		l2tp_len = EXTRACT_16BITS(ptr);
81627df3f5dSRui Paulo 		ptr += 2;
817b0453382SBill Fenner 		cnt += 2;
818b0453382SBill Fenner 	} else {
819b0453382SBill Fenner 		l2tp_len = 0;
820b0453382SBill Fenner 	}
821b0453382SBill Fenner 
8223c602fabSXin LI 	ND_TCHECK2(*ptr, 2);		/* Tunnel ID */
8233c602fabSXin LI 	ND_PRINT((ndo, "(%u/", EXTRACT_16BITS(ptr)));
82427df3f5dSRui Paulo 	ptr += 2;
825a90e161bSBill Fenner 	cnt += 2;
8263c602fabSXin LI 	ND_TCHECK2(*ptr, 2);		/* Session ID */
8273c602fabSXin LI 	ND_PRINT((ndo, "%u)",  EXTRACT_16BITS(ptr)));
82827df3f5dSRui Paulo 	ptr += 2;
829a90e161bSBill Fenner 	cnt += 2;
830b0453382SBill Fenner 
831b0453382SBill Fenner 	if (flag_s) {
8323c602fabSXin LI 		ND_TCHECK2(*ptr, 2);	/* Ns */
8333c602fabSXin LI 		ND_PRINT((ndo, "Ns=%u,", EXTRACT_16BITS(ptr)));
83427df3f5dSRui Paulo 		ptr += 2;
835a90e161bSBill Fenner 		cnt += 2;
8363c602fabSXin LI 		ND_TCHECK2(*ptr, 2);	/* Nr */
8373c602fabSXin LI 		ND_PRINT((ndo, "Nr=%u",  EXTRACT_16BITS(ptr)));
83827df3f5dSRui Paulo 		ptr += 2;
839a90e161bSBill Fenner 		cnt += 2;
840b0453382SBill Fenner 	}
841b0453382SBill Fenner 
842b0453382SBill Fenner 	if (flag_o) {
8433c602fabSXin LI 		ND_TCHECK2(*ptr, 2);	/* Offset Size */
84427df3f5dSRui Paulo 		pad =  EXTRACT_16BITS(ptr);
84527df3f5dSRui Paulo 		ptr += (2 + pad);
846b0453382SBill Fenner 		cnt += (2 + pad);
847b0453382SBill Fenner 	}
848b0453382SBill Fenner 
849f4d0c64aSSam Leffler 	if (flag_l) {
850f4d0c64aSSam Leffler 		if (length < l2tp_len) {
8513c602fabSXin LI 			ND_PRINT((ndo, " Length %u larger than packet", l2tp_len));
852f4d0c64aSSam Leffler 			return;
853f4d0c64aSSam Leffler 		}
854f4d0c64aSSam Leffler 		length = l2tp_len;
855f4d0c64aSSam Leffler 	}
856f4d0c64aSSam Leffler 	if (length < cnt) {
8573c602fabSXin LI 		ND_PRINT((ndo, " Length %u smaller than header length", length));
858f4d0c64aSSam Leffler 		return;
859f4d0c64aSSam Leffler 	}
860b0453382SBill Fenner 	if (flag_t) {
861f4d0c64aSSam Leffler 		if (!flag_l) {
8623c602fabSXin LI 			ND_PRINT((ndo, " No length"));
863f4d0c64aSSam Leffler 			return;
864f4d0c64aSSam Leffler 		}
865b0453382SBill Fenner 		if (length - cnt == 0) {
8663c602fabSXin LI 			ND_PRINT((ndo, " ZLB"));
867b0453382SBill Fenner 		} else {
8683c602fabSXin LI 			l2tp_avp_print(ndo, ptr, length - cnt);
869b0453382SBill Fenner 		}
870b0453382SBill Fenner 	} else {
8713c602fabSXin LI 		ND_PRINT((ndo, " {"));
8723c602fabSXin LI 		ppp_print(ndo, ptr, length - cnt);
8733c602fabSXin LI 		ND_PRINT((ndo, "}"));
874b0453382SBill Fenner 	}
875a90e161bSBill Fenner 
876a90e161bSBill Fenner 	return;
877a90e161bSBill Fenner 
878a90e161bSBill Fenner  trunc:
8793c602fabSXin LI 	ND_PRINT((ndo, "%s", tstr));
880b0453382SBill Fenner }
881