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