xref: /freebsd/contrib/tcpdump/print-l2tp.c (revision 27df3f5dddcc52e19be97c5e876161208987d4f1)
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 
24b0453382SBill Fenner #ifndef lint
255b0fe478SBruce M Simpson static const char rcsid[] _U_ =
26a5779b6eSRui Paulo     "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.20 2006-06-23 02:03:09 hannes Exp $";
27b0453382SBill Fenner #endif
28b0453382SBill Fenner 
29b0453382SBill Fenner #ifdef HAVE_CONFIG_H
30b0453382SBill Fenner #include "config.h"
31b0453382SBill Fenner #endif
32b0453382SBill Fenner 
335b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
345b0fe478SBruce M Simpson 
35b0453382SBill Fenner #include <stdio.h>
36b0453382SBill Fenner 
37b0453382SBill Fenner #include "l2tp.h"
38b0453382SBill Fenner #include "interface.h"
399afd0c29SBill Fenner #include "extract.h"
40b0453382SBill Fenner 
41b0453382SBill Fenner static char tstr[] = " [|l2tp]";
42b0453382SBill Fenner 
43a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
44a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
45a90e161bSBill Fenner #define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
46a90e161bSBill Fenner #define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
47a90e161bSBill Fenner #define	L2TP_MSGTYPE_HELLO	6  /* Hello */
48a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
49a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
50a90e161bSBill Fenner #define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
51a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
52a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
53a90e161bSBill Fenner #define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
54a90e161bSBill Fenner #define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
55a90e161bSBill Fenner #define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
56a90e161bSBill Fenner #define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
57a90e161bSBill Fenner 
58a90e161bSBill Fenner static struct tok l2tp_msgtype2str[] = {
59a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRQ, 	"SCCRQ" },
60a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
61a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
62a90e161bSBill Fenner 	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
63a90e161bSBill Fenner 	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
64a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
65a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
66a90e161bSBill Fenner 	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
67a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
68a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
69a90e161bSBill Fenner 	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
70a90e161bSBill Fenner 	{ L2TP_MSGTYPE_CDN,	"CDN" },
71a90e161bSBill Fenner 	{ L2TP_MSGTYPE_WEN,	"WEN" },
72a90e161bSBill Fenner 	{ L2TP_MSGTYPE_SLI,	"SLI" },
73a90e161bSBill Fenner 	{ 0,			NULL }
74b0453382SBill Fenner };
75b0453382SBill Fenner 
76a90e161bSBill Fenner #define L2TP_AVP_MSGTYPE		0  /* Message Type */
77a90e161bSBill Fenner #define L2TP_AVP_RESULT_CODE		1  /* Result Code */
78a90e161bSBill Fenner #define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
79a90e161bSBill Fenner #define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
80a90e161bSBill Fenner #define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
81a90e161bSBill Fenner #define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
82a90e161bSBill Fenner #define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
83a90e161bSBill Fenner #define L2TP_AVP_HOST_NAME		7  /* Host Name */
84a90e161bSBill Fenner #define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
85a90e161bSBill Fenner #define L2TP_AVP_ASSND_TUN_ID 		9  /* Assigned Tunnel ID */
86a90e161bSBill Fenner #define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
87a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE		11 /* Challenge */
88a90e161bSBill Fenner #define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
89a90e161bSBill Fenner #define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
90a90e161bSBill Fenner #define L2TP_AVP_ASSND_SESS_ID  	14 /* Assigned Session ID */
91a90e161bSBill Fenner #define L2TP_AVP_CALL_SER_NUM 		15 /* Call Serial Number */
92a90e161bSBill Fenner #define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
93a90e161bSBill Fenner #define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
94a90e161bSBill Fenner #define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
95a90e161bSBill Fenner #define L2TP_AVP_FRAMING_TYPE 		19 /* Framing Type */
96a90e161bSBill Fenner #define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
97a90e161bSBill Fenner #define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
98a90e161bSBill Fenner #define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
99a90e161bSBill Fenner #define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
100a90e161bSBill Fenner #define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
101a90e161bSBill Fenner #define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
102a90e161bSBill Fenner #define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
103a90e161bSBill Fenner #define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
104a90e161bSBill Fenner #define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
105a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
106a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
107a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
108a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
109a90e161bSBill Fenner #define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
110a90e161bSBill Fenner #define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
111a90e161bSBill Fenner #define L2TP_AVP_ACCM			35 /* ACCM */
112a90e161bSBill Fenner #define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
113a90e161bSBill Fenner #define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
114a90e161bSBill Fenner #define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
115a90e161bSBill Fenner #define L2TP_AVP_SEQ_REQUIRED 		39 /* Sequencing Required */
116a90e161bSBill Fenner #define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code */
117b0453382SBill Fenner 
118a90e161bSBill Fenner static struct tok l2tp_avp2str[] = {
119a90e161bSBill Fenner 	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
120a90e161bSBill Fenner 	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
121a90e161bSBill Fenner 	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
122a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
123a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
124a90e161bSBill Fenner 	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
125a90e161bSBill Fenner 	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
126a90e161bSBill Fenner 	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
127a90e161bSBill Fenner 	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
128a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
129a90e161bSBill Fenner 	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
130a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
131a90e161bSBill Fenner 	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
132a90e161bSBill Fenner 	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
133a90e161bSBill Fenner 	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
134a90e161bSBill Fenner 	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
135a90e161bSBill Fenner 	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
136a90e161bSBill Fenner 	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
137a90e161bSBill Fenner 	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
138a90e161bSBill Fenner 	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
139a90e161bSBill Fenner 	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
140a90e161bSBill Fenner 	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
141a90e161bSBill Fenner 	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
142a90e161bSBill Fenner 	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
143a90e161bSBill Fenner 	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
144a90e161bSBill Fenner 	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
145a90e161bSBill Fenner 	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
146a90e161bSBill Fenner 	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
147a90e161bSBill Fenner 	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
148a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
149a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
150a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
151a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
152a90e161bSBill Fenner 	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
153a90e161bSBill Fenner 	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
154a90e161bSBill Fenner 	{ L2TP_AVP_ACCM,		"ACCM" },
155a90e161bSBill Fenner 	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
156a90e161bSBill Fenner 	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
157a90e161bSBill Fenner 	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
158a90e161bSBill Fenner 	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
159a90e161bSBill Fenner 	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
160a90e161bSBill Fenner 	{ 0,				NULL }
161a90e161bSBill Fenner };
162a90e161bSBill Fenner 
163a90e161bSBill Fenner static struct tok l2tp_authentype2str[] = {
164a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
165a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
166a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
167a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
168a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
169a90e161bSBill Fenner 	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
170a90e161bSBill Fenner 	{ 0,				NULL }
171a90e161bSBill Fenner };
172a90e161bSBill Fenner 
173a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
174a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
175a90e161bSBill Fenner #define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
176a90e161bSBill Fenner 
177a90e161bSBill Fenner static struct tok l2tp_cc_direction2str[] = {
178a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
179a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
180a90e161bSBill Fenner 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
181a90e161bSBill Fenner 	{ 0,					NULL }
182b0453382SBill Fenner };
183b0453382SBill Fenner 
184b0453382SBill Fenner #if 0
185b0453382SBill Fenner static char *l2tp_result_code_StopCCN[] = {
186b0453382SBill Fenner          "Reserved",
187b0453382SBill Fenner          "General request to clear control connection",
188b0453382SBill Fenner          "General error--Error Code indicates the problem",
189b0453382SBill Fenner          "Control channel already exists",
190b0453382SBill Fenner          "Requester is not authorized to establish a control channel",
191b0453382SBill Fenner          "The protocol version of the requester is not supported",
192b0453382SBill Fenner          "Requester is being shut down",
193b0453382SBill Fenner          "Finite State Machine error"
194b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
195b0453382SBill Fenner };
196b0453382SBill Fenner #endif
197b0453382SBill Fenner 
198b0453382SBill Fenner #if 0
199b0453382SBill Fenner static char *l2tp_result_code_CDN[] = {
200b0453382SBill Fenner 	"Reserved",
201b0453382SBill Fenner 	"Call disconnected due to loss of carrier",
202b0453382SBill Fenner 	"Call disconnected for the reason indicated in error code",
203b0453382SBill Fenner 	"Call disconnected for administrative reasons",
204b0453382SBill Fenner 	"Call failed due to lack of appropriate facilities being " \
205b0453382SBill Fenner 	"available (temporary condition)",
206b0453382SBill Fenner 	"Call failed due to lack of appropriate facilities being " \
207b0453382SBill Fenner 	"available (permanent condition)",
208b0453382SBill Fenner 	"Invalid destination",
209b0453382SBill Fenner 	"Call failed due to no carrier detected",
210b0453382SBill Fenner 	"Call failed due to detection of a busy signal",
211b0453382SBill Fenner 	"Call failed due to lack of a dial tone",
212b0453382SBill Fenner 	"Call was not established within time allotted by LAC",
213b0453382SBill Fenner 	"Call was connected but no appropriate framing was detected"
214b0453382SBill Fenner #define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
215b0453382SBill Fenner };
216b0453382SBill Fenner #endif
217b0453382SBill Fenner 
218b0453382SBill Fenner #if 0
219b0453382SBill Fenner static char *l2tp_error_code_general[] = {
220b0453382SBill Fenner 	"No general error",
221b0453382SBill Fenner 	"No control connection exists yet for this LAC-LNS pair",
222b0453382SBill Fenner 	"Length is wrong",
223b0453382SBill Fenner 	"One of the field values was out of range or " \
224b0453382SBill Fenner 	"reserved field was non-zero"
225b0453382SBill Fenner 	"Insufficient resources to handle this operation now",
226b0453382SBill Fenner 	"The Session ID is invalid in this context",
227b0453382SBill Fenner 	"A generic vendor-specific error occurred in the LAC",
228b0453382SBill Fenner 	"Try another"
229b0453382SBill Fenner #define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
230b0453382SBill Fenner };
231b0453382SBill Fenner #endif
232b0453382SBill Fenner 
233b0453382SBill Fenner /******************************/
234b0453382SBill Fenner /* generic print out routines */
235b0453382SBill Fenner /******************************/
236b0453382SBill Fenner static void
237b0453382SBill Fenner print_string(const u_char *dat, u_int length)
238b0453382SBill Fenner {
2395b0fe478SBruce M Simpson 	u_int i;
240b0453382SBill Fenner 	for (i=0; i<length; i++) {
241b0453382SBill Fenner 		printf("%c", *dat++);
242b0453382SBill Fenner 	}
243b0453382SBill Fenner }
244b0453382SBill Fenner 
245b0453382SBill Fenner static void
246b0453382SBill Fenner print_octets(const u_char *dat, u_int length)
247b0453382SBill Fenner {
2485b0fe478SBruce M Simpson 	u_int i;
249b0453382SBill Fenner 	for (i=0; i<length; i++) {
250b0453382SBill Fenner 		printf("%02x", *dat++);
251b0453382SBill Fenner 	}
252b0453382SBill Fenner }
253b0453382SBill Fenner 
254b0453382SBill Fenner static void
255a90e161bSBill Fenner print_16bits_val(const u_int16_t *dat)
256b0453382SBill Fenner {
2579afd0c29SBill Fenner 	printf("%u", EXTRACT_16BITS(dat));
258b0453382SBill Fenner }
259b0453382SBill Fenner 
260b0453382SBill Fenner static void
261a90e161bSBill Fenner print_32bits_val(const u_int32_t *dat)
262b0453382SBill Fenner {
2639afd0c29SBill Fenner 	printf("%lu", (u_long)EXTRACT_32BITS(dat));
264b0453382SBill Fenner }
265b0453382SBill Fenner 
266a90e161bSBill Fenner /***********************************/
267b0453382SBill Fenner /* AVP-specific print out routines */
268a90e161bSBill Fenner /***********************************/
269b0453382SBill Fenner static void
270a90e161bSBill Fenner l2tp_msgtype_print(const u_char *dat)
271b0453382SBill Fenner {
272a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t*)dat;
273b0453382SBill Fenner 
2749afd0c29SBill Fenner 	printf("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
2759afd0c29SBill Fenner 	    EXTRACT_16BITS(ptr)));
276b0453382SBill Fenner }
277b0453382SBill Fenner 
278b0453382SBill Fenner static void
279b0453382SBill Fenner l2tp_result_code_print(const u_char *dat, u_int length)
280b0453382SBill Fenner {
281a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t *)dat;
282b0453382SBill Fenner 
2839afd0c29SBill Fenner 	printf("%u", EXTRACT_16BITS(ptr)); ptr++;	/* Result Code */
284a90e161bSBill Fenner 	if (length > 2) {				/* Error Code (opt) */
2859afd0c29SBill Fenner 	        printf("/%u", EXTRACT_16BITS(ptr)); ptr++;
286a90e161bSBill Fenner 	}
287a90e161bSBill Fenner 	if (length > 4) {				/* Error Message (opt) */
288a90e161bSBill Fenner 		printf(" ");
289a90e161bSBill Fenner 		print_string((u_char *)ptr, length - 4);
290b0453382SBill Fenner 	}
291b0453382SBill Fenner }
292b0453382SBill Fenner 
293b0453382SBill Fenner static void
294a90e161bSBill Fenner l2tp_proto_ver_print(const u_int16_t *dat)
295b0453382SBill Fenner {
2969afd0c29SBill Fenner 	printf("%u.%u", (EXTRACT_16BITS(dat) >> 8),
2979afd0c29SBill Fenner 	    (EXTRACT_16BITS(dat) & 0xff));
298b0453382SBill Fenner }
299b0453382SBill Fenner 
300b0453382SBill Fenner static void
301a90e161bSBill Fenner l2tp_framing_cap_print(const u_char *dat)
302b0453382SBill Fenner {
303a90e161bSBill Fenner 	u_int32_t *ptr = (u_int32_t *)dat;
304b0453382SBill Fenner 
3059afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
306b0453382SBill Fenner 		printf("A");
307b0453382SBill Fenner 	}
3089afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_SYNC_MASK) {
309b0453382SBill Fenner 		printf("S");
310b0453382SBill Fenner 	}
311b0453382SBill Fenner }
312b0453382SBill Fenner 
313b0453382SBill Fenner static void
314a90e161bSBill Fenner l2tp_bearer_cap_print(const u_char *dat)
315b0453382SBill Fenner {
316a90e161bSBill Fenner 	u_int32_t *ptr = (u_int32_t *)dat;
317b0453382SBill Fenner 
3189afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_ANALOG_MASK) {
319b0453382SBill Fenner 		printf("A");
320b0453382SBill Fenner 	}
3219afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
322b0453382SBill Fenner 		printf("D");
323b0453382SBill Fenner 	}
324b0453382SBill Fenner }
325b0453382SBill Fenner 
326b0453382SBill Fenner static void
327b0453382SBill Fenner l2tp_q931_cc_print(const u_char *dat, u_int length)
328b0453382SBill Fenner {
329a90e161bSBill Fenner 	print_16bits_val((u_int16_t *)dat);
330b0453382SBill Fenner 	printf(", %02x", dat[2]);
331b0453382SBill Fenner 	if (length > 3) {
332b0453382SBill Fenner 		printf(" ");
333b0453382SBill Fenner 		print_string(dat+3, length-3);
334b0453382SBill Fenner 	}
335b0453382SBill Fenner }
336b0453382SBill Fenner 
337b0453382SBill Fenner static void
338a90e161bSBill Fenner l2tp_bearer_type_print(const u_char *dat)
339b0453382SBill Fenner {
340a90e161bSBill Fenner 	u_int32_t *ptr = (u_int32_t *)dat;
341b0453382SBill Fenner 
3429afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
343b0453382SBill Fenner 		printf("A");
344b0453382SBill Fenner 	}
3459afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
346b0453382SBill Fenner 		printf("D");
347b0453382SBill Fenner 	}
348b0453382SBill Fenner }
349b0453382SBill Fenner 
350b0453382SBill Fenner static void
351a90e161bSBill Fenner l2tp_framing_type_print(const u_char *dat)
352b0453382SBill Fenner {
353a90e161bSBill Fenner 	u_int32_t *ptr = (u_int32_t *)dat;
354b0453382SBill Fenner 
3559afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
356b0453382SBill Fenner 		printf("A");
357b0453382SBill Fenner 	}
3589afd0c29SBill Fenner 	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
359b0453382SBill Fenner 		printf("S");
360b0453382SBill Fenner 	}
361b0453382SBill Fenner }
362b0453382SBill Fenner 
363b0453382SBill Fenner static void
364a90e161bSBill Fenner l2tp_packet_proc_delay_print(void)
365b0453382SBill Fenner {
366b0453382SBill Fenner 	printf("obsolete");
367b0453382SBill Fenner }
368b0453382SBill Fenner 
369b0453382SBill Fenner static void
370a90e161bSBill Fenner l2tp_proxy_auth_type_print(const u_char *dat)
371b0453382SBill Fenner {
372a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t *)dat;
373a90e161bSBill Fenner 
374a90e161bSBill Fenner 	printf("%s", tok2str(l2tp_authentype2str,
3759afd0c29SBill Fenner 			     "AuthType-#%u", EXTRACT_16BITS(ptr)));
376b0453382SBill Fenner }
377b0453382SBill Fenner 
378b0453382SBill Fenner static void
379a90e161bSBill Fenner l2tp_proxy_auth_id_print(const u_char *dat)
380b0453382SBill Fenner {
381a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t *)dat;
382b0453382SBill Fenner 
3839afd0c29SBill Fenner 	printf("%u", EXTRACT_16BITS(ptr) & L2TP_PROXY_AUTH_ID_MASK);
384b0453382SBill Fenner }
385b0453382SBill Fenner 
386b0453382SBill Fenner static void
387a90e161bSBill Fenner l2tp_call_errors_print(const u_char *dat)
388b0453382SBill Fenner {
389a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t *)dat;
390a90e161bSBill Fenner 	u_int16_t val_h, val_l;
391a90e161bSBill Fenner 
392a90e161bSBill Fenner 	ptr++;		/* skip "Reserved" */
393a90e161bSBill Fenner 
3949afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
3959afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
396a90e161bSBill Fenner 	printf("CRCErr=%u ", (val_h<<16) + val_l);
397a90e161bSBill Fenner 
3989afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
3999afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
400a90e161bSBill Fenner 	printf("FrameErr=%u ", (val_h<<16) + val_l);
401a90e161bSBill Fenner 
4029afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
4039afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
404a90e161bSBill Fenner 	printf("HardOver=%u ", (val_h<<16) + val_l);
405a90e161bSBill Fenner 
4069afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
4079afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
408a90e161bSBill Fenner 	printf("BufOver=%u ", (val_h<<16) + val_l);
409a90e161bSBill Fenner 
4109afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
4119afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
412a90e161bSBill Fenner 	printf("Timeout=%u ", (val_h<<16) + val_l);
413a90e161bSBill Fenner 
4149afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
4159afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
416a90e161bSBill Fenner 	printf("AlignErr=%u ", (val_h<<16) + val_l);
417b0453382SBill Fenner }
418b0453382SBill Fenner 
419b0453382SBill Fenner static void
420a90e161bSBill Fenner l2tp_accm_print(const u_char *dat)
421b0453382SBill Fenner {
422a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t *)dat;
423a90e161bSBill Fenner 	u_int16_t val_h, val_l;
424b0453382SBill Fenner 
425a90e161bSBill Fenner 	ptr++;		/* skip "Reserved" */
426a90e161bSBill Fenner 
4279afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
4289afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
429a90e161bSBill Fenner 	printf("send=%08x ", (val_h<<16) + val_l);
430a90e161bSBill Fenner 
4319afd0c29SBill Fenner 	val_h = EXTRACT_16BITS(ptr); ptr++;
4329afd0c29SBill Fenner 	val_l = EXTRACT_16BITS(ptr); ptr++;
433a90e161bSBill Fenner 	printf("recv=%08x ", (val_h<<16) + val_l);
434b0453382SBill Fenner }
435b0453382SBill Fenner 
436b0453382SBill Fenner static void
437a90e161bSBill Fenner l2tp_ppp_discon_cc_print(const u_char *dat, u_int length)
438b0453382SBill Fenner {
439a90e161bSBill Fenner 	u_int16_t *ptr = (u_int16_t *)dat;
440b0453382SBill Fenner 
4419afd0c29SBill Fenner 	printf("%04x, ", EXTRACT_16BITS(ptr)); ptr++;	/* Disconnect Code */
4429afd0c29SBill Fenner 	printf("%04x ",  EXTRACT_16BITS(ptr)); ptr++;	/* Control Protocol Number */
443a90e161bSBill Fenner 	printf("%s", tok2str(l2tp_cc_direction2str,
444a90e161bSBill Fenner 			     "Direction-#%u", *((u_char *)ptr++)));
445a90e161bSBill Fenner 
446a90e161bSBill Fenner 	if (length > 5) {
447a90e161bSBill Fenner 		printf(" ");
448a90e161bSBill Fenner 		print_string((const u_char *)ptr, length-5);
449a90e161bSBill Fenner 	}
450b0453382SBill Fenner }
451b0453382SBill Fenner 
452b0453382SBill Fenner static void
453a90e161bSBill Fenner l2tp_avp_print(const u_char *dat, int length)
454b0453382SBill Fenner {
455a90e161bSBill Fenner 	u_int len;
456a90e161bSBill Fenner 	const u_int16_t *ptr = (u_int16_t *)dat;
457a90e161bSBill Fenner 	u_int16_t attr_type;
458a90e161bSBill Fenner 	int hidden = FALSE;
459b0453382SBill Fenner 
460a90e161bSBill Fenner 	if (length <= 0) {
461b0453382SBill Fenner 		return;
462b0453382SBill Fenner 	}
463b0453382SBill Fenner 
464b0453382SBill Fenner 	printf(" ");
465a90e161bSBill Fenner 
466a90e161bSBill Fenner 	TCHECK(*ptr);	/* Flags & Length */
4679afd0c29SBill Fenner 	len = EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_LEN_MASK;
468a90e161bSBill Fenner 
469b97c9af5SBill Fenner 	/* If it is not long enough to contain the header, we'll give up. */
470b97c9af5SBill Fenner 	if (len < 6)
471b97c9af5SBill Fenner 		goto trunc;
472b97c9af5SBill Fenner 
473b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the packet,
474b97c9af5SBill Fenner 	   we'll give up. */
475b97c9af5SBill Fenner 	if (len > (u_int)length)
476b97c9af5SBill Fenner 		goto trunc;
477b97c9af5SBill Fenner 
478b97c9af5SBill Fenner 	/* If it goes past the end of the remaining length of the captured
479b97c9af5SBill Fenner 	   data, we'll give up. */
480a90e161bSBill Fenner 	TCHECK2(*ptr, len);
481a90e161bSBill Fenner 	/* After this point, no need to worry about truncation */
482a90e161bSBill Fenner 
4839afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
484b0453382SBill Fenner 		printf("*");
485b0453382SBill Fenner 	}
4869afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
487b0453382SBill Fenner 		hidden = TRUE;
488b0453382SBill Fenner 		printf("?");
489b0453382SBill Fenner 	}
490b0453382SBill Fenner 	ptr++;
491b0453382SBill Fenner 
4929afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr)) {
493685295f4SBill Fenner 		/* Vendor Specific Attribute */
4949afd0c29SBill Fenner 	        printf("VENDOR%04x:", EXTRACT_16BITS(ptr)); ptr++;
4959afd0c29SBill Fenner 		printf("ATTR%04x", EXTRACT_16BITS(ptr)); ptr++;
496685295f4SBill Fenner 		printf("(");
497a90e161bSBill Fenner 		print_octets((u_char *)ptr, len-6);
498685295f4SBill Fenner 		printf(")");
499685295f4SBill Fenner 	} else {
500a90e161bSBill Fenner 		/* IETF-defined Attributes */
501685295f4SBill Fenner 		ptr++;
5029afd0c29SBill Fenner 		attr_type = EXTRACT_16BITS(ptr); ptr++;
503a90e161bSBill Fenner 		printf("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
504b0453382SBill Fenner 		printf("(");
505a90e161bSBill Fenner 		if (hidden) {
506b0453382SBill Fenner 			printf("???");
507a90e161bSBill Fenner 		} else {
508a90e161bSBill Fenner 			switch (attr_type) {
509a90e161bSBill Fenner 			case L2TP_AVP_MSGTYPE:
510a90e161bSBill Fenner 				l2tp_msgtype_print((u_char *)ptr);
511a90e161bSBill Fenner 				break;
512a90e161bSBill Fenner 			case L2TP_AVP_RESULT_CODE:
513a90e161bSBill Fenner 				l2tp_result_code_print((u_char *)ptr, len-6);
514a90e161bSBill Fenner 				break;
515a90e161bSBill Fenner 			case L2TP_AVP_PROTO_VER:
516a90e161bSBill Fenner 				l2tp_proto_ver_print(ptr);
517a90e161bSBill Fenner 				break;
518a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_CAP:
519a90e161bSBill Fenner 				l2tp_framing_cap_print((u_char *)ptr);
520a90e161bSBill Fenner 				break;
521a90e161bSBill Fenner 			case L2TP_AVP_BEARER_CAP:
522a90e161bSBill Fenner 				l2tp_bearer_cap_print((u_char *)ptr);
523a90e161bSBill Fenner 				break;
524a90e161bSBill Fenner 			case L2TP_AVP_TIE_BREAKER:
525a90e161bSBill Fenner 				print_octets((u_char *)ptr, 8);
526a90e161bSBill Fenner 				break;
527a90e161bSBill Fenner 			case L2TP_AVP_FIRM_VER:
528a90e161bSBill Fenner 			case L2TP_AVP_ASSND_TUN_ID:
529a90e161bSBill Fenner 			case L2TP_AVP_RECV_WIN_SIZE:
530a90e161bSBill Fenner 			case L2TP_AVP_ASSND_SESS_ID:
531a90e161bSBill Fenner 				print_16bits_val(ptr);
532a90e161bSBill Fenner 				break;
533a90e161bSBill Fenner 			case L2TP_AVP_HOST_NAME:
534a90e161bSBill Fenner 			case L2TP_AVP_VENDOR_NAME:
535a90e161bSBill Fenner 			case L2TP_AVP_CALLING_NUMBER:
536a90e161bSBill Fenner 			case L2TP_AVP_CALLED_NUMBER:
537a90e161bSBill Fenner 			case L2TP_AVP_SUB_ADDRESS:
538a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_NAME:
539a90e161bSBill Fenner 			case L2TP_AVP_PRIVATE_GRP_ID:
540a90e161bSBill Fenner 				print_string((u_char *)ptr, len-6);
541a90e161bSBill Fenner 				break;
542a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE:
543a90e161bSBill Fenner 			case L2TP_AVP_INI_RECV_LCP:
544a90e161bSBill Fenner 			case L2TP_AVP_LAST_SENT_LCP:
545a90e161bSBill Fenner 			case L2TP_AVP_LAST_RECV_LCP:
546a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_CHAL:
547a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_RESP:
548a90e161bSBill Fenner 			case L2TP_AVP_RANDOM_VECTOR:
549a90e161bSBill Fenner 				print_octets((u_char *)ptr, len-6);
550a90e161bSBill Fenner 				break;
551a90e161bSBill Fenner 			case L2TP_AVP_Q931_CC:
552a90e161bSBill Fenner 				l2tp_q931_cc_print((u_char *)ptr, len-6);
553a90e161bSBill Fenner 				break;
554a90e161bSBill Fenner 			case L2TP_AVP_CHALLENGE_RESP:
555a90e161bSBill Fenner 				print_octets((u_char *)ptr, 16);
556a90e161bSBill Fenner 				break;
557a90e161bSBill Fenner 			case L2TP_AVP_CALL_SER_NUM:
558a90e161bSBill Fenner 			case L2TP_AVP_MINIMUM_BPS:
559a90e161bSBill Fenner 			case L2TP_AVP_MAXIMUM_BPS:
560a90e161bSBill Fenner 			case L2TP_AVP_TX_CONN_SPEED:
561a90e161bSBill Fenner 			case L2TP_AVP_PHY_CHANNEL_ID:
562a90e161bSBill Fenner 			case L2TP_AVP_RX_CONN_SPEED:
563a90e161bSBill Fenner 				print_32bits_val((u_int32_t *)ptr);
564a90e161bSBill Fenner 				break;
565a90e161bSBill Fenner 			case L2TP_AVP_BEARER_TYPE:
566a90e161bSBill Fenner 				l2tp_bearer_type_print((u_char *)ptr);
567a90e161bSBill Fenner 				break;
568a90e161bSBill Fenner 			case L2TP_AVP_FRAMING_TYPE:
569a90e161bSBill Fenner 				l2tp_framing_type_print((u_char *)ptr);
570a90e161bSBill Fenner 				break;
571a90e161bSBill Fenner 			case L2TP_AVP_PACKET_PROC_DELAY:
572a90e161bSBill Fenner 				l2tp_packet_proc_delay_print();
573a90e161bSBill Fenner 				break;
574a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_TYPE:
575a90e161bSBill Fenner 				l2tp_proxy_auth_type_print((u_char *)ptr);
576a90e161bSBill Fenner 				break;
577a90e161bSBill Fenner 			case L2TP_AVP_PROXY_AUTH_ID:
578a90e161bSBill Fenner 				l2tp_proxy_auth_id_print((u_char *)ptr);
579a90e161bSBill Fenner 				break;
580a90e161bSBill Fenner 			case L2TP_AVP_CALL_ERRORS:
581a90e161bSBill Fenner 				l2tp_call_errors_print((u_char *)ptr);
582a90e161bSBill Fenner 				break;
583a90e161bSBill Fenner 			case L2TP_AVP_ACCM:
584a90e161bSBill Fenner 				l2tp_accm_print((u_char *)ptr);
585a90e161bSBill Fenner 				break;
586a90e161bSBill Fenner 			case L2TP_AVP_SEQ_REQUIRED:
587a90e161bSBill Fenner 				break;	/* No Attribute Value */
588a90e161bSBill Fenner 			case L2TP_AVP_PPP_DISCON_CC:
589a90e161bSBill Fenner 				l2tp_ppp_discon_cc_print((u_char *)ptr, len-6);
590a90e161bSBill Fenner 				break;
591a90e161bSBill Fenner 			default:
592a90e161bSBill Fenner 				break;
593a90e161bSBill Fenner 			}
594b0453382SBill Fenner 		}
595b0453382SBill Fenner 		printf(")");
596685295f4SBill Fenner 	}
597b0453382SBill Fenner 
598b0453382SBill Fenner 	l2tp_avp_print(dat+len, length-len);
599b0453382SBill Fenner 	return;
600a90e161bSBill Fenner 
601a90e161bSBill Fenner  trunc:
602b0453382SBill Fenner 	printf("|...");
603b0453382SBill Fenner }
604b0453382SBill Fenner 
605b0453382SBill Fenner 
606b0453382SBill Fenner void
607b0453382SBill Fenner l2tp_print(const u_char *dat, u_int length)
608b0453382SBill Fenner {
609*27df3f5dSRui Paulo 	const u_char *ptr = dat;
610b0453382SBill Fenner 	u_int cnt = 0;			/* total octets consumed */
611a90e161bSBill Fenner 	u_int16_t pad;
612f4d0c64aSSam Leffler 	int flag_t, flag_l, flag_s, flag_o;
613a90e161bSBill Fenner 	u_int16_t l2tp_len;
614b0453382SBill Fenner 
615f4d0c64aSSam Leffler 	flag_t = flag_l = flag_s = flag_o = FALSE;
616b0453382SBill Fenner 
617*27df3f5dSRui Paulo 	TCHECK2(*ptr, 2);	/* Flags & Version */
6189afd0c29SBill Fenner 	if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
619b0453382SBill Fenner 		printf(" l2tp:");
6209afd0c29SBill Fenner 	} else if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
621b0453382SBill Fenner 		printf(" l2f:");
622b0453382SBill Fenner 		return;		/* nothing to do */
623b0453382SBill Fenner 	} else {
624b0453382SBill Fenner 		printf(" Unknown Version, neither L2F(1) nor L2TP(2)");
625b0453382SBill Fenner 		return;		/* nothing we can do */
626b0453382SBill Fenner 	}
627b0453382SBill Fenner 
628b0453382SBill Fenner 	printf("[");
6299afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_TYPE) {
630b0453382SBill Fenner 		flag_t = TRUE;
631b0453382SBill Fenner 		printf("T");
632b0453382SBill Fenner 	}
6339afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_LENGTH) {
634b0453382SBill Fenner 		flag_l = TRUE;
635b0453382SBill Fenner 		printf("L");
636b0453382SBill Fenner 	}
6379afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_SEQUENCE) {
638b0453382SBill Fenner 		flag_s = TRUE;
639b0453382SBill Fenner 		printf("S");
640b0453382SBill Fenner 	}
6419afd0c29SBill Fenner 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_OFFSET) {
642b0453382SBill Fenner 		flag_o = TRUE;
643b0453382SBill Fenner 		printf("O");
644b0453382SBill Fenner 	}
645f4d0c64aSSam Leffler 	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_PRIORITY)
646b0453382SBill Fenner 		printf("P");
647b0453382SBill Fenner 	printf("]");
648b0453382SBill Fenner 
649*27df3f5dSRui Paulo 	ptr += 2;
650b0453382SBill Fenner 	cnt += 2;
651b0453382SBill Fenner 
652b0453382SBill Fenner 	if (flag_l) {
653*27df3f5dSRui Paulo 		TCHECK2(*ptr, 2);	/* Length */
654*27df3f5dSRui Paulo 		l2tp_len = EXTRACT_16BITS(ptr);
655*27df3f5dSRui Paulo 		ptr += 2;
656b0453382SBill Fenner 		cnt += 2;
657b0453382SBill Fenner 	} else {
658b0453382SBill Fenner 		l2tp_len = 0;
659b0453382SBill Fenner 	}
660b0453382SBill Fenner 
661*27df3f5dSRui Paulo 	TCHECK2(*ptr, 2);		/* Tunnel ID */
662*27df3f5dSRui Paulo 	printf("(%u/", EXTRACT_16BITS(ptr));
663*27df3f5dSRui Paulo 	ptr += 2;
664a90e161bSBill Fenner 	cnt += 2;
665*27df3f5dSRui Paulo 	TCHECK2(*ptr, 2);		/* Session ID */
666*27df3f5dSRui Paulo 	printf("%u)",  EXTRACT_16BITS(ptr));
667*27df3f5dSRui Paulo 	ptr += 2;
668a90e161bSBill Fenner 	cnt += 2;
669b0453382SBill Fenner 
670b0453382SBill Fenner 	if (flag_s) {
671*27df3f5dSRui Paulo 		TCHECK2(*ptr, 2);	/* Ns */
672*27df3f5dSRui Paulo 		printf("Ns=%u,", EXTRACT_16BITS(ptr));
673*27df3f5dSRui Paulo 		ptr += 2;
674a90e161bSBill Fenner 		cnt += 2;
675*27df3f5dSRui Paulo 		TCHECK2(*ptr, 2);	/* Nr */
676*27df3f5dSRui Paulo 		printf("Nr=%u",  EXTRACT_16BITS(ptr));
677*27df3f5dSRui Paulo 		ptr += 2;
678a90e161bSBill Fenner 		cnt += 2;
679b0453382SBill Fenner 	}
680b0453382SBill Fenner 
681b0453382SBill Fenner 	if (flag_o) {
682*27df3f5dSRui Paulo 		TCHECK2(*ptr, 2);	/* Offset Size */
683*27df3f5dSRui Paulo 		pad =  EXTRACT_16BITS(ptr);
684*27df3f5dSRui Paulo 		ptr += (2 + pad);
685b0453382SBill Fenner 		cnt += (2 + pad);
686b0453382SBill Fenner 	}
687b0453382SBill Fenner 
688f4d0c64aSSam Leffler 	if (flag_l) {
689f4d0c64aSSam Leffler 		if (length < l2tp_len) {
690f4d0c64aSSam Leffler 			printf(" Length %u larger than packet", l2tp_len);
691f4d0c64aSSam Leffler 			return;
692f4d0c64aSSam Leffler 		}
693f4d0c64aSSam Leffler 		length = l2tp_len;
694f4d0c64aSSam Leffler 	}
695f4d0c64aSSam Leffler 	if (length < cnt) {
696f4d0c64aSSam Leffler 		printf(" Length %u smaller than header length", length);
697f4d0c64aSSam Leffler 		return;
698f4d0c64aSSam Leffler 	}
699b0453382SBill Fenner 	if (flag_t) {
700f4d0c64aSSam Leffler 		if (!flag_l) {
701f4d0c64aSSam Leffler 			printf(" No length");
702f4d0c64aSSam Leffler 			return;
703f4d0c64aSSam Leffler 		}
704b0453382SBill Fenner 		if (length - cnt == 0) {
705b0453382SBill Fenner 			printf(" ZLB");
706b0453382SBill Fenner 		} else {
707*27df3f5dSRui Paulo 			l2tp_avp_print(ptr, length - cnt);
708b0453382SBill Fenner 		}
709b0453382SBill Fenner 	} else {
710b0453382SBill Fenner 		printf(" {");
711*27df3f5dSRui Paulo 		ppp_print(ptr, length - cnt);
712b0453382SBill Fenner 		printf("}");
713b0453382SBill Fenner 	}
714a90e161bSBill Fenner 
715a90e161bSBill Fenner 	return;
716a90e161bSBill Fenner 
717a90e161bSBill Fenner  trunc:
718a90e161bSBill Fenner 	printf("%s", tstr);
719b0453382SBill Fenner }
720