xref: /freebsd/contrib/tcpdump/print-l2tp.c (revision ee67461e)
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 
28b0453382SBill Fenner #ifdef HAVE_CONFIG_H
29ee67461eSJoseph Mingrone #include <config.h>
30b0453382SBill Fenner #endif
31b0453382SBill Fenner 
32ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
335b0fe478SBruce M Simpson 
343340d773SGleb Smirnoff #include "netdissect.h"
359afd0c29SBill Fenner #include "extract.h"
36b0453382SBill Fenner 
373c602fabSXin LI #define L2TP_FLAG_TYPE		0x8000	/* Type (0=Data, 1=Control) */
383c602fabSXin LI #define L2TP_FLAG_LENGTH	0x4000	/* Length */
393c602fabSXin LI #define L2TP_FLAG_SEQUENCE	0x0800	/* Sequence */
403c602fabSXin LI #define L2TP_FLAG_OFFSET	0x0200	/* Offset */
413c602fabSXin LI #define L2TP_FLAG_PRIORITY	0x0100	/* Priority */
423c602fabSXin LI 
433c602fabSXin LI #define L2TP_VERSION_MASK	0x000f	/* Version Mask */
443c602fabSXin LI #define L2TP_VERSION_L2F	0x0001	/* L2F */
453c602fabSXin LI #define L2TP_VERSION_L2TP	0x0002	/* L2TP */
463c602fabSXin LI 
473c602fabSXin LI #define L2TP_AVP_HDR_FLAG_MANDATORY	0x8000	/* Mandatory Flag */
483c602fabSXin LI #define L2TP_AVP_HDR_FLAG_HIDDEN	0x4000	/* Hidden Flag */
493c602fabSXin LI #define L2TP_AVP_HDR_LEN_MASK		0x03ff	/* Length Mask */
503c602fabSXin LI 
513c602fabSXin LI #define L2TP_FRAMING_CAP_SYNC_MASK	0x00000001	/* Synchronous */
523c602fabSXin LI #define L2TP_FRAMING_CAP_ASYNC_MASK	0x00000002	/* Asynchronous */
533c602fabSXin LI 
543c602fabSXin LI #define L2TP_FRAMING_TYPE_SYNC_MASK	0x00000001	/* Synchronous */
553c602fabSXin LI #define L2TP_FRAMING_TYPE_ASYNC_MASK	0x00000002	/* Asynchronous */
563c602fabSXin LI 
573c602fabSXin LI #define L2TP_BEARER_CAP_DIGITAL_MASK	0x00000001	/* Digital */
583c602fabSXin LI #define L2TP_BEARER_CAP_ANALOG_MASK	0x00000002	/* Analog */
593c602fabSXin LI 
603c602fabSXin LI #define L2TP_BEARER_TYPE_DIGITAL_MASK	0x00000001	/* Digital */
613c602fabSXin LI #define L2TP_BEARER_TYPE_ANALOG_MASK	0x00000002	/* Analog */
623c602fabSXin LI 
633c602fabSXin LI /* Authen Type */
643c602fabSXin LI #define L2TP_AUTHEN_TYPE_RESERVED	0x0000	/* Reserved */
653c602fabSXin LI #define L2TP_AUTHEN_TYPE_TEXTUAL	0x0001	/* Textual username/password exchange */
663c602fabSXin LI #define L2TP_AUTHEN_TYPE_CHAP		0x0002	/* PPP CHAP */
673c602fabSXin LI #define L2TP_AUTHEN_TYPE_PAP		0x0003	/* PPP PAP */
683c602fabSXin LI #define L2TP_AUTHEN_TYPE_NO_AUTH	0x0004	/* No Authentication */
693c602fabSXin LI #define L2TP_AUTHEN_TYPE_MSCHAPv1	0x0005	/* MSCHAPv1 */
703c602fabSXin LI 
713c602fabSXin LI #define L2TP_PROXY_AUTH_ID_MASK		0x00ff
723c602fabSXin LI 
73b0453382SBill Fenner 
74a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
75a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
76a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
77a90e161bSBill Fenner #define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
78a90e161bSBill Fenner #define	L2TP_MSGTYPE_HELLO	6  /* Hello */
79a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
80a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
81a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
82a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
83a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
84a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
85a90e161bSBill Fenner #define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
86a90e161bSBill Fenner #define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
87a90e161bSBill Fenner #define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
88a90e161bSBill Fenner 
893c602fabSXin LI static const struct tok l2tp_msgtype2str[] = {
90a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRQ,	"SCCRQ" },
91a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
92a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
93a90e161bSBill Fenner 	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
94a90e161bSBill Fenner 	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
95a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
96a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
97a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
98a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
99a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
100a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
101a90e161bSBill Fenner 	{ L2TP_MSGTYPE_CDN,	"CDN" },
102a90e161bSBill Fenner 	{ L2TP_MSGTYPE_WEN,	"WEN" },
103a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SLI,	"SLI" },
104a90e161bSBill Fenner 	{ 0,			NULL }
105b0453382SBill Fenner };
106b0453382SBill Fenner 
107a90e161bSBill Fenner #define L2TP_AVP_MSGTYPE		0  /* Message Type */
108a90e161bSBill Fenner #define L2TP_AVP_RESULT_CODE		1  /* Result Code */
109a90e161bSBill Fenner #define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
110a90e161bSBill Fenner #define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
111a90e161bSBill Fenner #define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
112a90e161bSBill Fenner #define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
113a90e161bSBill Fenner #define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
114a90e161bSBill Fenner #define L2TP_AVP_HOST_NAME		7  /* Host Name */
115a90e161bSBill Fenner #define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
116a90e161bSBill Fenner #define L2TP_AVP_ASSND_TUN_ID		9  /* Assigned Tunnel ID */
117a90e161bSBill Fenner #define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
118a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE		11 /* Challenge */
119a90e161bSBill Fenner #define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
120a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
121a90e161bSBill Fenner #define L2TP_AVP_ASSND_SESS_ID		14 /* Assigned Session ID */
122a90e161bSBill Fenner #define L2TP_AVP_CALL_SER_NUM		15 /* Call Serial Number */
123a90e161bSBill Fenner #define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
124a90e161bSBill Fenner #define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
125a90e161bSBill Fenner #define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
126a90e161bSBill Fenner #define L2TP_AVP_FRAMING_TYPE		19 /* Framing Type */
127a90e161bSBill Fenner #define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
128a90e161bSBill Fenner #define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
129a90e161bSBill Fenner #define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
130a90e161bSBill Fenner #define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
131a90e161bSBill Fenner #define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
132a90e161bSBill Fenner #define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
133a90e161bSBill Fenner #define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
134a90e161bSBill Fenner #define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
135a90e161bSBill Fenner #define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
136a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
137a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
138a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
139a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
140a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
141a90e161bSBill Fenner #define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
142a90e161bSBill Fenner #define L2TP_AVP_ACCM			35 /* ACCM */
143a90e161bSBill Fenner #define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
144a90e161bSBill Fenner #define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
145a90e161bSBill Fenner #define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
146a90e161bSBill Fenner #define L2TP_AVP_SEQ_REQUIRED		39 /* Sequencing Required */
14739e421e8SCy Schubert #define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code - RFC 3145 */
148b0453382SBill Fenner 
1493c602fabSXin LI static const struct tok l2tp_avp2str[] = {
150a90e161bSBill Fenner 	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
151a90e161bSBill Fenner 	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
152a90e161bSBill Fenner 	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
153a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
154a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
155a90e161bSBill Fenner 	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
156a90e161bSBill Fenner 	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
157a90e161bSBill Fenner 	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
158a90e161bSBill Fenner 	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
159a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
160a90e161bSBill Fenner 	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
161a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
162a90e161bSBill Fenner 	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
163a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
164a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
165a90e161bSBill Fenner 	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
166a90e161bSBill Fenner 	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
167a90e161bSBill Fenner 	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
168a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
169a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
170a90e161bSBill Fenner 	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
171a90e161bSBill Fenner 	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
172a90e161bSBill Fenner 	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
173a90e161bSBill Fenner 	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
174a90e161bSBill Fenner 	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
175a90e161bSBill Fenner 	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
176a90e161bSBill Fenner 	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
177a90e161bSBill Fenner 	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
178a90e161bSBill Fenner 	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
179a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
180a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
181a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
182a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
183a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
184a90e161bSBill Fenner 	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
185a90e161bSBill Fenner 	{ L2TP_AVP_ACCM,		"ACCM" },
186a90e161bSBill Fenner 	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
187a90e161bSBill Fenner 	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
188a90e161bSBill Fenner 	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
189a90e161bSBill Fenner 	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
190a90e161bSBill Fenner 	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
191a90e161bSBill Fenner 	{ 0,				NULL }
192a90e161bSBill Fenner };
193a90e161bSBill Fenner 
1943c602fabSXin LI static const struct tok l2tp_authentype2str[] = {
195a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
196a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
197a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
198a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
199a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
200a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
201a90e161bSBill Fenner 	{ 0,				NULL }
202a90e161bSBill Fenner };
203a90e161bSBill Fenner 
204a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
205a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
206a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
207a90e161bSBill Fenner 
2083c602fabSXin LI static const struct tok l2tp_cc_direction2str[] = {
209a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
210a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
211a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
212a90e161bSBill Fenner 	{ 0,					NULL }
213b0453382SBill Fenner };
214b0453382SBill Fenner 
215b0453382SBill Fenner #if 0
216b0453382SBill Fenner static char *l2tp_result_code_StopCCN[] = {
217b0453382SBill Fenner          "Reserved",
218b0453382SBill Fenner          "General request to clear control connection",
219b0453382SBill Fenner          "General error--Error Code indicates the problem",
220b0453382SBill Fenner          "Control channel already exists",
221b0453382SBill Fenner          "Requester is not authorized to establish a control channel",
222b0453382SBill Fenner          "The protocol version of the requester is not supported",
223b0453382SBill Fenner          "Requester is being shut down",
224b0453382SBill Fenner          "Finite State Machine error"
225b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
226b0453382SBill Fenner };
227b0453382SBill Fenner #endif
228b0453382SBill Fenner 
229b0453382SBill Fenner #if 0
230b0453382SBill Fenner static char *l2tp_result_code_CDN[] = {
231b0453382SBill Fenner 	"Reserved",
232b0453382SBill Fenner 	"Call disconnected due to loss of carrier",
233b0453382SBill Fenner 	"Call disconnected for the reason indicated in error code",
234b0453382SBill Fenner 	"Call disconnected for administrative reasons",
235ee67461eSJoseph Mingrone 	"Call failed due to lack of appropriate facilities being "
236b0453382SBill Fenner 	"available (temporary condition)",
237ee67461eSJoseph Mingrone 	"Call failed due to lack of appropriate facilities being "
238b0453382SBill Fenner 	"available (permanent condition)",
239b0453382SBill Fenner 	"Invalid destination",
240b0453382SBill Fenner 	"Call failed due to no carrier detected",
241b0453382SBill Fenner 	"Call failed due to detection of a busy signal",
242b0453382SBill Fenner 	"Call failed due to lack of a dial tone",
243b0453382SBill Fenner 	"Call was not established within time allotted by LAC",
244b0453382SBill Fenner 	"Call was connected but no appropriate framing was detected"
245b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
246b0453382SBill Fenner };
247b0453382SBill Fenner #endif
248b0453382SBill Fenner 
249b0453382SBill Fenner #if 0
250b0453382SBill Fenner static char *l2tp_error_code_general[] = {
251b0453382SBill Fenner 	"No general error",
252b0453382SBill Fenner 	"No control connection exists yet for this LAC-LNS pair",
253b0453382SBill Fenner 	"Length is wrong",
254ee67461eSJoseph Mingrone 	"One of the field values was out of range or "
255b0453382SBill Fenner 	"reserved field was non-zero"
256b0453382SBill Fenner 	"Insufficient resources to handle this operation now",
257b0453382SBill Fenner 	"The Session ID is invalid in this context",
258b0453382SBill Fenner 	"A generic vendor-specific error occurred in the LAC",
259b0453382SBill Fenner 	"Try another"
260b0453382SBill Fenner #define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
261b0453382SBill Fenner };
262b0453382SBill Fenner #endif
263b0453382SBill Fenner 
264b0453382SBill Fenner /******************************/
265b0453382SBill Fenner /* generic print out routines */
266b0453382SBill Fenner /******************************/
267b0453382SBill Fenner static void
print_string(netdissect_options * ndo,const u_char * dat,u_int length)2683c602fabSXin LI print_string(netdissect_options *ndo, const u_char *dat, u_int length)
269b0453382SBill Fenner {
2705b0fe478SBruce M Simpson 	u_int i;
271b0453382SBill Fenner 	for (i=0; i<length; i++) {
272ee67461eSJoseph Mingrone 		fn_print_char(ndo, GET_U_1(dat));
273ee67461eSJoseph Mingrone 		dat++;
274b0453382SBill Fenner 	}
275b0453382SBill Fenner }
276b0453382SBill Fenner 
277b0453382SBill Fenner static void
print_octets(netdissect_options * ndo,const u_char * dat,u_int length)2783c602fabSXin LI print_octets(netdissect_options *ndo, const u_char *dat, u_int length)
279b0453382SBill Fenner {
2805b0fe478SBruce M Simpson 	u_int i;
281b0453382SBill Fenner 	for (i=0; i<length; i++) {
282ee67461eSJoseph Mingrone 		ND_PRINT("%02x", GET_U_1(dat));
283ee67461eSJoseph Mingrone 		dat++;
284b0453382SBill Fenner 	}
285b0453382SBill Fenner }
286b0453382SBill Fenner 
287b0453382SBill Fenner static void
print_16bits_val(netdissect_options * ndo,const uint8_t * dat)28839e421e8SCy Schubert print_16bits_val(netdissect_options *ndo, const uint8_t *dat)
289b0453382SBill Fenner {
290ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_2(dat));
291b0453382SBill Fenner }
292b0453382SBill Fenner 
293b0453382SBill Fenner static void
print_32bits_val(netdissect_options * ndo,const uint8_t * dat)29439e421e8SCy Schubert print_32bits_val(netdissect_options *ndo, const uint8_t *dat)
295b0453382SBill Fenner {
296ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_4(dat));
297b0453382SBill Fenner }
298b0453382SBill Fenner 
299a90e161bSBill Fenner /***********************************/
300b0453382SBill Fenner /* AVP-specific print out routines */
301a90e161bSBill Fenner /***********************************/
302b0453382SBill Fenner static void
l2tp_msgtype_print(netdissect_options * ndo,const u_char * dat,u_int length)3030bff6a5aSEd Maste l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length)
304b0453382SBill Fenner {
3050bff6a5aSEd Maste 	if (length < 2) {
306ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3070bff6a5aSEd Maste 		return;
3080bff6a5aSEd Maste 	}
309ee67461eSJoseph Mingrone 	ND_PRINT("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
310ee67461eSJoseph Mingrone 	    GET_BE_U_2(dat)));
311b0453382SBill Fenner }
312b0453382SBill Fenner 
313b0453382SBill Fenner static void
l2tp_result_code_print(netdissect_options * ndo,const u_char * dat,u_int length)3143c602fabSXin LI l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length)
315b0453382SBill Fenner {
3160bff6a5aSEd Maste 	/* Result Code */
3170bff6a5aSEd Maste 	if (length < 2) {
318ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3190bff6a5aSEd Maste 		return;
320a90e161bSBill Fenner 	}
321ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_2(dat));
32239e421e8SCy Schubert 	dat += 2;
3230bff6a5aSEd Maste 	length -= 2;
3240bff6a5aSEd Maste 
3250bff6a5aSEd Maste 	/* Error Code (opt) */
3260bff6a5aSEd Maste 	if (length == 0)
3270bff6a5aSEd Maste 		return;
3280bff6a5aSEd Maste 	if (length < 2) {
329ee67461eSJoseph Mingrone 		ND_PRINT(" AVP too short");
3300bff6a5aSEd Maste 		return;
3310bff6a5aSEd Maste 	}
332ee67461eSJoseph Mingrone 	ND_PRINT("/%u", GET_BE_U_2(dat));
33339e421e8SCy Schubert 	dat += 2;
3340bff6a5aSEd Maste 	length -= 2;
3350bff6a5aSEd Maste 
3360bff6a5aSEd Maste 	/* Error Message (opt) */
3370bff6a5aSEd Maste 	if (length == 0)
3380bff6a5aSEd Maste 		return;
339ee67461eSJoseph Mingrone 	ND_PRINT(" ");
34039e421e8SCy Schubert 	print_string(ndo, dat, length);
341b0453382SBill Fenner }
342b0453382SBill Fenner 
343b0453382SBill Fenner static void
l2tp_proto_ver_print(netdissect_options * ndo,const u_char * dat,u_int length)34439e421e8SCy Schubert l2tp_proto_ver_print(netdissect_options *ndo, const u_char *dat, u_int length)
345b0453382SBill Fenner {
3460bff6a5aSEd Maste 	if (length < 2) {
347ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3480bff6a5aSEd Maste 		return;
3490bff6a5aSEd Maste 	}
350ee67461eSJoseph Mingrone 	ND_PRINT("%u.%u", (GET_BE_U_2(dat) >> 8),
351ee67461eSJoseph Mingrone 		  (GET_BE_U_2(dat) & 0xff));
352b0453382SBill Fenner }
353b0453382SBill Fenner 
354b0453382SBill Fenner static void
l2tp_framing_cap_print(netdissect_options * ndo,const u_char * dat,u_int length)3550bff6a5aSEd Maste l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
356b0453382SBill Fenner {
3570bff6a5aSEd Maste 	if (length < 4) {
358ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3590bff6a5aSEd Maste 		return;
3600bff6a5aSEd Maste 	}
361ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
362ee67461eSJoseph Mingrone 		ND_PRINT("A");
363b0453382SBill Fenner 	}
364ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_CAP_SYNC_MASK) {
365ee67461eSJoseph Mingrone 		ND_PRINT("S");
366b0453382SBill Fenner 	}
367b0453382SBill Fenner }
368b0453382SBill Fenner 
369b0453382SBill Fenner static void
l2tp_bearer_cap_print(netdissect_options * ndo,const u_char * dat,u_int length)3700bff6a5aSEd Maste l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
371b0453382SBill Fenner {
3720bff6a5aSEd Maste 	if (length < 4) {
373ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3740bff6a5aSEd Maste 		return;
3750bff6a5aSEd Maste 	}
376ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_CAP_ANALOG_MASK) {
377ee67461eSJoseph Mingrone 		ND_PRINT("A");
378b0453382SBill Fenner 	}
379ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
380ee67461eSJoseph Mingrone 		ND_PRINT("D");
381b0453382SBill Fenner 	}
382b0453382SBill Fenner }
383b0453382SBill Fenner 
384b0453382SBill Fenner static void
l2tp_q931_cc_print(netdissect_options * ndo,const u_char * dat,u_int length)3853c602fabSXin LI l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
386b0453382SBill Fenner {
3870bff6a5aSEd Maste 	if (length < 3) {
388ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
3890bff6a5aSEd Maste 		return;
3900bff6a5aSEd Maste 	}
39139e421e8SCy Schubert 	print_16bits_val(ndo, dat);
392ee67461eSJoseph Mingrone 	ND_PRINT(", %02x", GET_U_1(dat + 2));
3930bff6a5aSEd Maste 	dat += 3;
3940bff6a5aSEd Maste 	length -= 3;
3950bff6a5aSEd Maste 	if (length != 0) {
396ee67461eSJoseph Mingrone 		ND_PRINT(" ");
3970bff6a5aSEd Maste 		print_string(ndo, dat, length);
398b0453382SBill Fenner 	}
399b0453382SBill Fenner }
400b0453382SBill Fenner 
401b0453382SBill Fenner static void
l2tp_bearer_type_print(netdissect_options * ndo,const u_char * dat,u_int length)4020bff6a5aSEd Maste l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
403b0453382SBill Fenner {
4040bff6a5aSEd Maste 	if (length < 4) {
405ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4060bff6a5aSEd Maste 		return;
4070bff6a5aSEd Maste 	}
408ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
409ee67461eSJoseph Mingrone 		ND_PRINT("A");
410b0453382SBill Fenner 	}
411ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
412ee67461eSJoseph Mingrone 		ND_PRINT("D");
413b0453382SBill Fenner 	}
414b0453382SBill Fenner }
415b0453382SBill Fenner 
416b0453382SBill Fenner static void
l2tp_framing_type_print(netdissect_options * ndo,const u_char * dat,u_int length)4170bff6a5aSEd Maste l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
418b0453382SBill Fenner {
4190bff6a5aSEd Maste 	if (length < 4) {
420ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4210bff6a5aSEd Maste 		return;
4220bff6a5aSEd Maste 	}
423ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
424ee67461eSJoseph Mingrone 		ND_PRINT("A");
425b0453382SBill Fenner 	}
426ee67461eSJoseph Mingrone 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
427ee67461eSJoseph Mingrone 		ND_PRINT("S");
428b0453382SBill Fenner 	}
429b0453382SBill Fenner }
430b0453382SBill Fenner 
431b0453382SBill Fenner static void
l2tp_packet_proc_delay_print(netdissect_options * ndo)4323c602fabSXin LI l2tp_packet_proc_delay_print(netdissect_options *ndo)
433b0453382SBill Fenner {
434ee67461eSJoseph Mingrone 	ND_PRINT("obsolete");
435b0453382SBill Fenner }
436b0453382SBill Fenner 
437b0453382SBill Fenner static void
l2tp_proxy_auth_type_print(netdissect_options * ndo,const u_char * dat,u_int length)4380bff6a5aSEd Maste l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
439b0453382SBill Fenner {
4400bff6a5aSEd Maste 	if (length < 2) {
441ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4420bff6a5aSEd Maste 		return;
4430bff6a5aSEd Maste 	}
444ee67461eSJoseph Mingrone 	ND_PRINT("%s", tok2str(l2tp_authentype2str,
445ee67461eSJoseph Mingrone 			     "AuthType-#%u", GET_BE_U_2(dat)));
446b0453382SBill Fenner }
447b0453382SBill Fenner 
448b0453382SBill Fenner static void
l2tp_proxy_auth_id_print(netdissect_options * ndo,const u_char * dat,u_int length)4490bff6a5aSEd Maste l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length)
450b0453382SBill Fenner {
4510bff6a5aSEd Maste 	if (length < 2) {
452ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4530bff6a5aSEd Maste 		return;
4540bff6a5aSEd Maste 	}
455ee67461eSJoseph Mingrone 	ND_PRINT("%u", GET_BE_U_2(dat) & L2TP_PROXY_AUTH_ID_MASK);
456b0453382SBill Fenner }
457b0453382SBill Fenner 
458b0453382SBill Fenner static void
l2tp_call_errors_print(netdissect_options * ndo,const u_char * dat,u_int length)4590bff6a5aSEd Maste l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length)
460b0453382SBill Fenner {
46139e421e8SCy Schubert 	uint32_t val;
462a90e161bSBill Fenner 
4630bff6a5aSEd Maste 	if (length < 2) {
464ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4650bff6a5aSEd Maste 		return;
4660bff6a5aSEd Maste 	}
46739e421e8SCy Schubert 	dat += 2;	/* skip "Reserved" */
4680bff6a5aSEd Maste 	length -= 2;
469a90e161bSBill Fenner 
4700bff6a5aSEd Maste 	if (length < 4) {
471ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4720bff6a5aSEd Maste 		return;
4730bff6a5aSEd Maste 	}
474ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
475ee67461eSJoseph Mingrone 	ND_PRINT("CRCErr=%u ", val);
476a90e161bSBill Fenner 
4770bff6a5aSEd Maste 	if (length < 4) {
478ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4790bff6a5aSEd Maste 		return;
4800bff6a5aSEd Maste 	}
481ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
482ee67461eSJoseph Mingrone 	ND_PRINT("FrameErr=%u ", val);
483a90e161bSBill Fenner 
4840bff6a5aSEd Maste 	if (length < 4) {
485ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4860bff6a5aSEd Maste 		return;
4870bff6a5aSEd Maste 	}
488ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
489ee67461eSJoseph Mingrone 	ND_PRINT("HardOver=%u ", val);
490a90e161bSBill Fenner 
4910bff6a5aSEd Maste 	if (length < 4) {
492ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
4930bff6a5aSEd Maste 		return;
4940bff6a5aSEd Maste 	}
495ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
496ee67461eSJoseph Mingrone 	ND_PRINT("BufOver=%u ", val);
497a90e161bSBill Fenner 
4980bff6a5aSEd Maste 	if (length < 4) {
499ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5000bff6a5aSEd Maste 		return;
5010bff6a5aSEd Maste 	}
502ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
503ee67461eSJoseph Mingrone 	ND_PRINT("Timeout=%u ", val);
504a90e161bSBill Fenner 
5050bff6a5aSEd Maste 	if (length < 4) {
506ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5070bff6a5aSEd Maste 		return;
5080bff6a5aSEd Maste 	}
509ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
510ee67461eSJoseph Mingrone 	ND_PRINT("AlignErr=%u ", val);
511b0453382SBill Fenner }
512b0453382SBill Fenner 
513b0453382SBill Fenner static void
l2tp_accm_print(netdissect_options * ndo,const u_char * dat,u_int length)5140bff6a5aSEd Maste l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length)
515b0453382SBill Fenner {
51639e421e8SCy Schubert 	uint32_t val;
517b0453382SBill Fenner 
5180bff6a5aSEd Maste 	if (length < 2) {
519ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5200bff6a5aSEd Maste 		return;
5210bff6a5aSEd Maste 	}
52239e421e8SCy Schubert 	dat += 2;	/* skip "Reserved" */
5230bff6a5aSEd Maste 	length -= 2;
524a90e161bSBill Fenner 
5250bff6a5aSEd Maste 	if (length < 4) {
526ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5270bff6a5aSEd Maste 		return;
5280bff6a5aSEd Maste 	}
529ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
530ee67461eSJoseph Mingrone 	ND_PRINT("send=%08x ", val);
531a90e161bSBill Fenner 
5320bff6a5aSEd Maste 	if (length < 4) {
533ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5340bff6a5aSEd Maste 		return;
5350bff6a5aSEd Maste 	}
536ee67461eSJoseph Mingrone 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
537ee67461eSJoseph Mingrone 	ND_PRINT("recv=%08x ", val);
538b0453382SBill Fenner }
539b0453382SBill Fenner 
540b0453382SBill Fenner static void
l2tp_ppp_discon_cc_print(netdissect_options * ndo,const u_char * dat,u_int length)5413c602fabSXin LI l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
542b0453382SBill Fenner {
5430bff6a5aSEd Maste 	if (length < 5) {
544ee67461eSJoseph Mingrone 		ND_PRINT("AVP too short");
5450bff6a5aSEd Maste 		return;
5460bff6a5aSEd Maste 	}
5470bff6a5aSEd Maste 	/* Disconnect Code */
548ee67461eSJoseph Mingrone 	ND_PRINT("%04x, ", GET_BE_U_2(dat));
5490bff6a5aSEd Maste 	dat += 2;
5500bff6a5aSEd Maste 	length -= 2;
5510bff6a5aSEd Maste 	/* Control Protocol Number */
552ee67461eSJoseph Mingrone 	ND_PRINT("%04x ",  GET_BE_U_2(dat));
5530bff6a5aSEd Maste 	dat += 2;
5540bff6a5aSEd Maste 	length -= 2;
5550bff6a5aSEd Maste 	/* Direction */
556ee67461eSJoseph Mingrone 	ND_PRINT("%s", tok2str(l2tp_cc_direction2str,
557ee67461eSJoseph Mingrone 			     "Direction-#%u", GET_U_1(dat)));
55839e421e8SCy Schubert 	dat++;
5590bff6a5aSEd Maste 	length--;
560a90e161bSBill Fenner 
5610bff6a5aSEd Maste 	if (length != 0) {
562ee67461eSJoseph Mingrone 		ND_PRINT(" ");
56339e421e8SCy Schubert 		print_string(ndo, (const u_char *)dat, length);
564a90e161bSBill Fenner 	}
565b0453382SBill Fenner }
566b0453382SBill Fenner 
56739e421e8SCy Schubert static u_int
l2tp_avp_print(netdissect_options * ndo,const u_char * dat,u_int length)56839e421e8SCy Schubert l2tp_avp_print(netdissect_options *ndo, const u_char *dat, u_int length)
569b0453382SBill Fenner {
570a90e161bSBill Fenner 	u_int len;
5713c602fabSXin LI 	uint16_t attr_type;
572a90e161bSBill Fenner 	int hidden = FALSE;
573b0453382SBill Fenner 
574ee67461eSJoseph Mingrone 	ND_PRINT(" ");
575ee67461eSJoseph Mingrone 	/* Flags & Length */
576ee67461eSJoseph Mingrone 	len = GET_BE_U_2(dat) & L2TP_AVP_HDR_LEN_MASK;
577a90e161bSBill Fenner 
578b97c9af5SBill Fenner 	/* If it is not long enough to contain the header, we'll give up. */
579b97c9af5SBill Fenner 	if (len < 6)
580b97c9af5SBill Fenner 		goto trunc;
581b97c9af5SBill Fenner 
582b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the packet,
583b97c9af5SBill Fenner 	   we'll give up. */
584b97c9af5SBill Fenner 	if (len > (u_int)length)
585b97c9af5SBill Fenner 		goto trunc;
586b97c9af5SBill Fenner 
587b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the captured
588b97c9af5SBill Fenner 	   data, we'll give up. */
589ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(dat, len);
5900bff6a5aSEd Maste 
5910bff6a5aSEd Maste 	/*
5920bff6a5aSEd Maste 	 * After this point, we don't need to check whether we go past
5930bff6a5aSEd Maste 	 * the length of the captured data; however, we *do* need to
5940bff6a5aSEd Maste 	 * check whether we go past the end of the AVP.
5950bff6a5aSEd Maste 	 */
596a90e161bSBill Fenner 
597ee67461eSJoseph Mingrone 	if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_MANDATORY) {
598ee67461eSJoseph Mingrone 		ND_PRINT("*");
599b0453382SBill Fenner 	}
600ee67461eSJoseph Mingrone 	if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_HIDDEN) {
601b0453382SBill Fenner 		hidden = TRUE;
602ee67461eSJoseph Mingrone 		ND_PRINT("?");
603b0453382SBill Fenner 	}
60439e421e8SCy Schubert 	dat += 2;
605b0453382SBill Fenner 
606ee67461eSJoseph Mingrone 	if (GET_BE_U_2(dat)) {
607685295f4SBill Fenner 		/* Vendor Specific Attribute */
608ee67461eSJoseph Mingrone 	        ND_PRINT("VENDOR%04x:", GET_BE_U_2(dat)); dat += 2;
609ee67461eSJoseph Mingrone 		ND_PRINT("ATTR%04x", GET_BE_U_2(dat)); dat += 2;
610ee67461eSJoseph Mingrone 		ND_PRINT("(");
61139e421e8SCy Schubert 		print_octets(ndo, dat, len-6);
612ee67461eSJoseph Mingrone 		ND_PRINT(")");
613685295f4SBill Fenner 	} else {
614a90e161bSBill Fenner 		/* IETF-defined Attributes */
61539e421e8SCy Schubert 		dat += 2;
616ee67461eSJoseph Mingrone 		attr_type = GET_BE_U_2(dat); dat += 2;
617ee67461eSJoseph Mingrone 		ND_PRINT("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
618ee67461eSJoseph Mingrone 		ND_PRINT("(");
619a90e161bSBill Fenner 		if (hidden) {
620ee67461eSJoseph Mingrone 			ND_PRINT("???");
621a90e161bSBill Fenner 		} else {
622a90e161bSBill Fenner 			switch (attr_type) {
623a90e161bSBill Fenner 			case L2TP_AVP_MSGTYPE:
62439e421e8SCy Schubert 				l2tp_msgtype_print(ndo, dat, len-6);
625a90e161bSBill Fenner 				break;
626a90e161bSBill Fenner 			case L2TP_AVP_RESULT_CODE:
62739e421e8SCy Schubert 				l2tp_result_code_print(ndo, dat, len-6);
628a90e161bSBill Fenner 				break;
629a90e161bSBill Fenner 			case L2TP_AVP_PROTO_VER:
63039e421e8SCy Schubert 				l2tp_proto_ver_print(ndo, dat, len-6);
631a90e161bSBill Fenner 				break;
632a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_CAP:
63339e421e8SCy Schubert 				l2tp_framing_cap_print(ndo, dat, len-6);
634a90e161bSBill Fenner 				break;
635a90e161bSBill Fenner 			case L2TP_AVP_BEARER_CAP:
63639e421e8SCy Schubert 				l2tp_bearer_cap_print(ndo, dat, len-6);
637a90e161bSBill Fenner 				break;
638a90e161bSBill Fenner 			case L2TP_AVP_TIE_BREAKER:
6390bff6a5aSEd Maste 				if (len-6 < 8) {
640ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6410bff6a5aSEd Maste 					break;
6420bff6a5aSEd Maste 				}
64339e421e8SCy Schubert 				print_octets(ndo, dat, 8);
644a90e161bSBill Fenner 				break;
645a90e161bSBill Fenner 			case L2TP_AVP_FIRM_VER:
646a90e161bSBill Fenner 			case L2TP_AVP_ASSND_TUN_ID:
647a90e161bSBill Fenner 			case L2TP_AVP_RECV_WIN_SIZE:
648a90e161bSBill Fenner 			case L2TP_AVP_ASSND_SESS_ID:
6490bff6a5aSEd Maste 				if (len-6 < 2) {
650ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6510bff6a5aSEd Maste 					break;
6520bff6a5aSEd Maste 				}
65339e421e8SCy Schubert 				print_16bits_val(ndo, dat);
654a90e161bSBill Fenner 				break;
655a90e161bSBill Fenner 			case L2TP_AVP_HOST_NAME:
656a90e161bSBill Fenner 			case L2TP_AVP_VENDOR_NAME:
657a90e161bSBill Fenner 			case L2TP_AVP_CALLING_NUMBER:
658a90e161bSBill Fenner 			case L2TP_AVP_CALLED_NUMBER:
659a90e161bSBill Fenner 			case L2TP_AVP_SUB_ADDRESS:
660a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_NAME:
661a90e161bSBill Fenner 			case L2TP_AVP_PRIVATE_GRP_ID:
66239e421e8SCy Schubert 				print_string(ndo, dat, len-6);
663a90e161bSBill Fenner 				break;
664a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE:
665a90e161bSBill Fenner 			case L2TP_AVP_INI_RECV_LCP:
666a90e161bSBill Fenner 			case L2TP_AVP_LAST_SENT_LCP:
667a90e161bSBill Fenner 			case L2TP_AVP_LAST_RECV_LCP:
668a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_CHAL:
669a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_RESP:
670a90e161bSBill Fenner 			case L2TP_AVP_RANDOM_VECTOR:
67139e421e8SCy Schubert 				print_octets(ndo, dat, len-6);
672a90e161bSBill Fenner 				break;
673a90e161bSBill Fenner 			case L2TP_AVP_Q931_CC:
67439e421e8SCy Schubert 				l2tp_q931_cc_print(ndo, dat, len-6);
675a90e161bSBill Fenner 				break;
676a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE_RESP:
6770bff6a5aSEd Maste 				if (len-6 < 16) {
678ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6790bff6a5aSEd Maste 					break;
6800bff6a5aSEd Maste 				}
68139e421e8SCy Schubert 				print_octets(ndo, dat, 16);
682a90e161bSBill Fenner 				break;
683a90e161bSBill Fenner 			case L2TP_AVP_CALL_SER_NUM:
684a90e161bSBill Fenner 			case L2TP_AVP_MINIMUM_BPS:
685a90e161bSBill Fenner 			case L2TP_AVP_MAXIMUM_BPS:
686a90e161bSBill Fenner 			case L2TP_AVP_TX_CONN_SPEED:
687a90e161bSBill Fenner 			case L2TP_AVP_PHY_CHANNEL_ID:
688a90e161bSBill Fenner 			case L2TP_AVP_RX_CONN_SPEED:
6890bff6a5aSEd Maste 				if (len-6 < 4) {
690ee67461eSJoseph Mingrone 					ND_PRINT("AVP too short");
6910bff6a5aSEd Maste 					break;
6920bff6a5aSEd Maste 				}
69339e421e8SCy Schubert 				print_32bits_val(ndo, dat);
694a90e161bSBill Fenner 				break;
695a90e161bSBill Fenner 			case L2TP_AVP_BEARER_TYPE:
69639e421e8SCy Schubert 				l2tp_bearer_type_print(ndo, dat, len-6);
697a90e161bSBill Fenner 				break;
698a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_TYPE:
69939e421e8SCy Schubert 				l2tp_framing_type_print(ndo, dat, len-6);
700a90e161bSBill Fenner 				break;
701a90e161bSBill Fenner 			case L2TP_AVP_PACKET_PROC_DELAY:
7023c602fabSXin LI 				l2tp_packet_proc_delay_print(ndo);
703a90e161bSBill Fenner 				break;
704a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_TYPE:
70539e421e8SCy Schubert 				l2tp_proxy_auth_type_print(ndo, dat, len-6);
706a90e161bSBill Fenner 				break;
707a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_ID:
70839e421e8SCy Schubert 				l2tp_proxy_auth_id_print(ndo, dat, len-6);
709a90e161bSBill Fenner 				break;
710a90e161bSBill Fenner 			case L2TP_AVP_CALL_ERRORS:
71139e421e8SCy Schubert 				l2tp_call_errors_print(ndo, dat, len-6);
712a90e161bSBill Fenner 				break;
713a90e161bSBill Fenner 			case L2TP_AVP_ACCM:
71439e421e8SCy Schubert 				l2tp_accm_print(ndo, dat, len-6);
715a90e161bSBill Fenner 				break;
716a90e161bSBill Fenner 			case L2TP_AVP_SEQ_REQUIRED:
717a90e161bSBill Fenner 				break;	/* No Attribute Value */
718a90e161bSBill Fenner 			case L2TP_AVP_PPP_DISCON_CC:
71939e421e8SCy Schubert 				l2tp_ppp_discon_cc_print(ndo, dat, len-6);
720a90e161bSBill Fenner 				break;
721a90e161bSBill Fenner 			default:
722a90e161bSBill Fenner 				break;
723a90e161bSBill Fenner 			}
724b0453382SBill Fenner 		}
725ee67461eSJoseph Mingrone 		ND_PRINT(")");
726685295f4SBill Fenner 	}
727b0453382SBill Fenner 
72839e421e8SCy Schubert 	return (len);
729a90e161bSBill Fenner 
730a90e161bSBill Fenner  trunc:
731ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
73239e421e8SCy Schubert 	return (0);
733b0453382SBill Fenner }
734b0453382SBill Fenner 
735b0453382SBill Fenner 
736b0453382SBill Fenner void
l2tp_print(netdissect_options * ndo,const u_char * dat,u_int length)7373c602fabSXin LI l2tp_print(netdissect_options *ndo, const u_char *dat, u_int length)
738b0453382SBill Fenner {
73927df3f5dSRui Paulo 	const u_char *ptr = dat;
740b0453382SBill Fenner 	u_int cnt = 0;			/* total octets consumed */
7413c602fabSXin LI 	uint16_t pad;
742f4d0c64aSSam Leffler 	int flag_t, flag_l, flag_s, flag_o;
7433c602fabSXin LI 	uint16_t l2tp_len;
744b0453382SBill Fenner 
745ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "l2tp";
746f4d0c64aSSam Leffler 	flag_t = flag_l = flag_s = flag_o = FALSE;
747b0453382SBill Fenner 
748ee67461eSJoseph Mingrone 	if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
749ee67461eSJoseph Mingrone 		ND_PRINT(" l2tp:");
750ee67461eSJoseph Mingrone 	} else if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
751ee67461eSJoseph Mingrone 		ND_PRINT(" l2f:");
752b0453382SBill Fenner 		return;		/* nothing to do */
753b0453382SBill Fenner 	} else {
754ee67461eSJoseph Mingrone 		ND_PRINT(" Unknown Version, neither L2F(1) nor L2TP(2)");
755b0453382SBill Fenner 		return;		/* nothing we can do */
756b0453382SBill Fenner 	}
757b0453382SBill Fenner 
758ee67461eSJoseph Mingrone 	ND_PRINT("[");
759ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_TYPE) {
760b0453382SBill Fenner 		flag_t = TRUE;
761ee67461eSJoseph Mingrone 		ND_PRINT("T");
762b0453382SBill Fenner 	}
763ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_LENGTH) {
764b0453382SBill Fenner 		flag_l = TRUE;
765ee67461eSJoseph Mingrone 		ND_PRINT("L");
766b0453382SBill Fenner 	}
767ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_SEQUENCE) {
768b0453382SBill Fenner 		flag_s = TRUE;
769ee67461eSJoseph Mingrone 		ND_PRINT("S");
770b0453382SBill Fenner 	}
771ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_OFFSET) {
772b0453382SBill Fenner 		flag_o = TRUE;
773ee67461eSJoseph Mingrone 		ND_PRINT("O");
774b0453382SBill Fenner 	}
775ee67461eSJoseph Mingrone 	if (GET_BE_U_2(ptr) & L2TP_FLAG_PRIORITY)
776ee67461eSJoseph Mingrone 		ND_PRINT("P");
777ee67461eSJoseph Mingrone 	ND_PRINT("]");
778b0453382SBill Fenner 
77927df3f5dSRui Paulo 	ptr += 2;
780b0453382SBill Fenner 	cnt += 2;
781b0453382SBill Fenner 
782b0453382SBill Fenner 	if (flag_l) {
783ee67461eSJoseph Mingrone 		l2tp_len = GET_BE_U_2(ptr);
78427df3f5dSRui Paulo 		ptr += 2;
785b0453382SBill Fenner 		cnt += 2;
786b0453382SBill Fenner 	} else {
787b0453382SBill Fenner 		l2tp_len = 0;
788b0453382SBill Fenner 	}
789ee67461eSJoseph Mingrone 	/* Tunnel ID */
790ee67461eSJoseph Mingrone 	ND_PRINT("(%u/", GET_BE_U_2(ptr));
79127df3f5dSRui Paulo 	ptr += 2;
792a90e161bSBill Fenner 	cnt += 2;
793ee67461eSJoseph Mingrone 	/* Session ID */
794ee67461eSJoseph Mingrone 	ND_PRINT("%u)",  GET_BE_U_2(ptr));
79527df3f5dSRui Paulo 	ptr += 2;
796a90e161bSBill Fenner 	cnt += 2;
797b0453382SBill Fenner 
798b0453382SBill Fenner 	if (flag_s) {
799ee67461eSJoseph Mingrone 		ND_PRINT("Ns=%u,", GET_BE_U_2(ptr));
80027df3f5dSRui Paulo 		ptr += 2;
801a90e161bSBill Fenner 		cnt += 2;
802ee67461eSJoseph Mingrone 		ND_PRINT("Nr=%u",  GET_BE_U_2(ptr));
80327df3f5dSRui Paulo 		ptr += 2;
804a90e161bSBill Fenner 		cnt += 2;
805b0453382SBill Fenner 	}
806b0453382SBill Fenner 
807ee67461eSJoseph Mingrone 	if (flag_o) {	/* Offset Size */
808ee67461eSJoseph Mingrone 		pad =  GET_BE_U_2(ptr);
809ee67461eSJoseph Mingrone 		/* Offset padding octets in packet buffer? */
810ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(ptr + 2, pad);
81127df3f5dSRui Paulo 		ptr += (2 + pad);
812b0453382SBill Fenner 		cnt += (2 + pad);
813b0453382SBill Fenner 	}
814b0453382SBill Fenner 
815f4d0c64aSSam Leffler 	if (flag_l) {
816f4d0c64aSSam Leffler 		if (length < l2tp_len) {
817ee67461eSJoseph Mingrone 			ND_PRINT(" Length %u larger than packet", l2tp_len);
818f4d0c64aSSam Leffler 			return;
819f4d0c64aSSam Leffler 		}
820f4d0c64aSSam Leffler 		length = l2tp_len;
821f4d0c64aSSam Leffler 	}
822f4d0c64aSSam Leffler 	if (length < cnt) {
823ee67461eSJoseph Mingrone 		ND_PRINT(" Length %u smaller than header length", length);
824f4d0c64aSSam Leffler 		return;
825f4d0c64aSSam Leffler 	}
826b0453382SBill Fenner 	if (flag_t) {
827f4d0c64aSSam Leffler 		if (!flag_l) {
828ee67461eSJoseph Mingrone 			ND_PRINT(" No length");
829f4d0c64aSSam Leffler 			return;
830f4d0c64aSSam Leffler 		}
831b0453382SBill Fenner 		if (length - cnt == 0) {
832ee67461eSJoseph Mingrone 			ND_PRINT(" ZLB");
833b0453382SBill Fenner 		} else {
83439e421e8SCy Schubert 			/*
83539e421e8SCy Schubert 			 * Print AVPs.
83639e421e8SCy Schubert 			 */
83739e421e8SCy Schubert 			while (length - cnt != 0) {
83839e421e8SCy Schubert 				u_int avp_length;
83939e421e8SCy Schubert 
84039e421e8SCy Schubert 				avp_length = l2tp_avp_print(ndo, ptr, length - cnt);
84139e421e8SCy Schubert 				if (avp_length == 0) {
84239e421e8SCy Schubert 					/*
84339e421e8SCy Schubert 					 * Truncated.
84439e421e8SCy Schubert 					 */
84539e421e8SCy Schubert 					break;
84639e421e8SCy Schubert 				}
84739e421e8SCy Schubert 				cnt += avp_length;
84839e421e8SCy Schubert 				ptr += avp_length;
84939e421e8SCy Schubert 			}
850b0453382SBill Fenner 		}
851b0453382SBill Fenner 	} else {
852ee67461eSJoseph Mingrone 		ND_PRINT(" {");
8533c602fabSXin LI 		ppp_print(ndo, ptr, length - cnt);
854ee67461eSJoseph Mingrone 		ND_PRINT("}");
855b0453382SBill Fenner 	}
856a90e161bSBill Fenner 	return;
857a90e161bSBill Fenner trunc:
858ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
859b0453382SBill Fenner }
860