xref: /netbsd-src/external/bsd/tcpdump/dist/print-l2tp.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
30f74e101Schristos  *      The Regents of the University of California.  All rights reserved.
40f74e101Schristos  *
50f74e101Schristos  * Redistribution and use in source and binary forms, with or without
60f74e101Schristos  * modification, are permitted provided that: (1) source code distributions
70f74e101Schristos  * retain the above copyright notice and this paragraph in its entirety, (2)
80f74e101Schristos  * distributions including binary code include the above copyright notice and
90f74e101Schristos  * this paragraph in its entirety in the documentation or other materials
100f74e101Schristos  * provided with the distribution, and (3) all advertising materials mentioning
110f74e101Schristos  * features or use of this software display the following acknowledgement:
120f74e101Schristos  * ``This product includes software developed by the University of California,
130f74e101Schristos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
140f74e101Schristos  * the University nor the names of its contributors may be used to endorse
150f74e101Schristos  * or promote products derived from this software without specific prior
160f74e101Schristos  * written permission.
170f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
180f74e101Schristos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
190f74e101Schristos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
200f74e101Schristos  *
210f74e101Schristos  * L2TP support contributed by Motonori Shindo (mshindo@mshindo.net)
220f74e101Schristos  */
230f74e101Schristos 
2411b3aaa1Schristos #include <sys/cdefs.h>
250f74e101Schristos #ifndef lint
26*26ba0b50Schristos __RCSID("$NetBSD: print-l2tp.c,v 1.11 2024/09/02 16:15:31 christos Exp $");
270f74e101Schristos #endif
280f74e101Schristos 
29dc860a36Sspz /* \summary: Layer Two Tunneling Protocol (L2TP) printer */
30dc860a36Sspz 
31817e9a7eSchristos /* specification: RFC 2661 */
32817e9a7eSchristos 
33c74ad251Schristos #include <config.h>
340f74e101Schristos 
35c74ad251Schristos #include "netdissect-stdinc.h"
360f74e101Schristos 
37fdccd7e4Schristos #include "netdissect.h"
380f74e101Schristos #include "extract.h"
390f74e101Schristos 
40b3a00663Schristos #define L2TP_FLAG_TYPE		0x8000	/* Type (0=Data, 1=Control) */
41b3a00663Schristos #define L2TP_FLAG_LENGTH	0x4000	/* Length */
42b3a00663Schristos #define L2TP_FLAG_SEQUENCE	0x0800	/* Sequence */
43b3a00663Schristos #define L2TP_FLAG_OFFSET	0x0200	/* Offset */
44b3a00663Schristos #define L2TP_FLAG_PRIORITY	0x0100	/* Priority */
45b3a00663Schristos 
46b3a00663Schristos #define L2TP_VERSION_MASK	0x000f	/* Version Mask */
47b3a00663Schristos #define L2TP_VERSION_L2F	0x0001	/* L2F */
48b3a00663Schristos #define L2TP_VERSION_L2TP	0x0002	/* L2TP */
49b3a00663Schristos 
50b3a00663Schristos #define L2TP_AVP_HDR_FLAG_MANDATORY	0x8000	/* Mandatory Flag */
51b3a00663Schristos #define L2TP_AVP_HDR_FLAG_HIDDEN	0x4000	/* Hidden Flag */
52b3a00663Schristos #define L2TP_AVP_HDR_LEN_MASK		0x03ff	/* Length Mask */
53b3a00663Schristos 
54b3a00663Schristos #define L2TP_FRAMING_CAP_SYNC_MASK	0x00000001	/* Synchronous */
55b3a00663Schristos #define L2TP_FRAMING_CAP_ASYNC_MASK	0x00000002	/* Asynchronous */
56b3a00663Schristos 
57b3a00663Schristos #define L2TP_FRAMING_TYPE_SYNC_MASK	0x00000001	/* Synchronous */
58b3a00663Schristos #define L2TP_FRAMING_TYPE_ASYNC_MASK	0x00000002	/* Asynchronous */
59b3a00663Schristos 
60b3a00663Schristos #define L2TP_BEARER_CAP_DIGITAL_MASK	0x00000001	/* Digital */
61b3a00663Schristos #define L2TP_BEARER_CAP_ANALOG_MASK	0x00000002	/* Analog */
62b3a00663Schristos 
63b3a00663Schristos #define L2TP_BEARER_TYPE_DIGITAL_MASK	0x00000001	/* Digital */
64b3a00663Schristos #define L2TP_BEARER_TYPE_ANALOG_MASK	0x00000002	/* Analog */
65b3a00663Schristos 
66b3a00663Schristos /* Authen Type */
67b3a00663Schristos #define L2TP_AUTHEN_TYPE_RESERVED	0x0000	/* Reserved */
68b3a00663Schristos #define L2TP_AUTHEN_TYPE_TEXTUAL	0x0001	/* Textual username/password exchange */
69b3a00663Schristos #define L2TP_AUTHEN_TYPE_CHAP		0x0002	/* PPP CHAP */
70b3a00663Schristos #define L2TP_AUTHEN_TYPE_PAP		0x0003	/* PPP PAP */
71b3a00663Schristos #define L2TP_AUTHEN_TYPE_NO_AUTH	0x0004	/* No Authentication */
72b3a00663Schristos #define L2TP_AUTHEN_TYPE_MSCHAPv1	0x0005	/* MSCHAPv1 */
73b3a00663Schristos 
74b3a00663Schristos #define L2TP_PROXY_AUTH_ID_MASK		0x00ff
75b3a00663Schristos 
760f74e101Schristos 
770f74e101Schristos #define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
780f74e101Schristos #define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
790f74e101Schristos #define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
800f74e101Schristos #define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
810f74e101Schristos #define	L2TP_MSGTYPE_HELLO	6  /* Hello */
820f74e101Schristos #define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
830f74e101Schristos #define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
840f74e101Schristos #define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
850f74e101Schristos #define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
860f74e101Schristos #define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
870f74e101Schristos #define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
880f74e101Schristos #define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
890f74e101Schristos #define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
900f74e101Schristos #define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
910f74e101Schristos 
92870189d2Schristos static const struct tok l2tp_msgtype2str[] = {
930f74e101Schristos 	{ L2TP_MSGTYPE_SCCRQ,	"SCCRQ" },
940f74e101Schristos 	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
950f74e101Schristos 	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
960f74e101Schristos 	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
970f74e101Schristos 	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
980f74e101Schristos 	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
990f74e101Schristos 	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
1000f74e101Schristos 	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
1010f74e101Schristos 	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
1020f74e101Schristos 	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
1030f74e101Schristos 	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
1040f74e101Schristos 	{ L2TP_MSGTYPE_CDN,	"CDN" },
1050f74e101Schristos 	{ L2TP_MSGTYPE_WEN,	"WEN" },
1060f74e101Schristos 	{ L2TP_MSGTYPE_SLI,	"SLI" },
1070f74e101Schristos 	{ 0,			NULL }
1080f74e101Schristos };
1090f74e101Schristos 
1100f74e101Schristos #define L2TP_AVP_MSGTYPE		0  /* Message Type */
1110f74e101Schristos #define L2TP_AVP_RESULT_CODE		1  /* Result Code */
1120f74e101Schristos #define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
1130f74e101Schristos #define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
1140f74e101Schristos #define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
1150f74e101Schristos #define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
1160f74e101Schristos #define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
1170f74e101Schristos #define L2TP_AVP_HOST_NAME		7  /* Host Name */
1180f74e101Schristos #define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
1190f74e101Schristos #define L2TP_AVP_ASSND_TUN_ID		9  /* Assigned Tunnel ID */
1200f74e101Schristos #define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
1210f74e101Schristos #define L2TP_AVP_CHALLENGE		11 /* Challenge */
1220f74e101Schristos #define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
1230f74e101Schristos #define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
1240f74e101Schristos #define L2TP_AVP_ASSND_SESS_ID		14 /* Assigned Session ID */
1250f74e101Schristos #define L2TP_AVP_CALL_SER_NUM		15 /* Call Serial Number */
1260f74e101Schristos #define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
1270f74e101Schristos #define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
1280f74e101Schristos #define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
1290f74e101Schristos #define L2TP_AVP_FRAMING_TYPE		19 /* Framing Type */
1300f74e101Schristos #define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
1310f74e101Schristos #define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
1320f74e101Schristos #define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
1330f74e101Schristos #define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
1340f74e101Schristos #define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
1350f74e101Schristos #define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
1360f74e101Schristos #define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
1370f74e101Schristos #define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
1380f74e101Schristos #define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
1390f74e101Schristos #define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
1400f74e101Schristos #define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
1410f74e101Schristos #define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
1420f74e101Schristos #define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
1430f74e101Schristos #define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
1440f74e101Schristos #define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
1450f74e101Schristos #define L2TP_AVP_ACCM			35 /* ACCM */
1460f74e101Schristos #define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
1470f74e101Schristos #define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
1480f74e101Schristos #define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
1490f74e101Schristos #define L2TP_AVP_SEQ_REQUIRED		39 /* Sequencing Required */
150817e9a7eSchristos #define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code - RFC 3145 */
1510f74e101Schristos 
152870189d2Schristos static const struct tok l2tp_avp2str[] = {
1530f74e101Schristos 	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
1540f74e101Schristos 	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
1550f74e101Schristos 	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
1560f74e101Schristos 	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
1570f74e101Schristos 	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
1580f74e101Schristos 	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
1590f74e101Schristos 	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
1600f74e101Schristos 	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
1610f74e101Schristos 	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
1620f74e101Schristos 	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
1630f74e101Schristos 	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
1640f74e101Schristos 	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
1650f74e101Schristos 	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
1660f74e101Schristos 	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
1670f74e101Schristos 	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
1680f74e101Schristos 	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
1690f74e101Schristos 	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
1700f74e101Schristos 	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
1710f74e101Schristos 	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
1720f74e101Schristos 	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
1730f74e101Schristos 	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
1740f74e101Schristos 	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
1750f74e101Schristos 	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
1760f74e101Schristos 	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
1770f74e101Schristos 	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
1780f74e101Schristos 	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
1790f74e101Schristos 	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
1800f74e101Schristos 	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
1810f74e101Schristos 	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
1820f74e101Schristos 	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
1830f74e101Schristos 	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
1840f74e101Schristos 	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
1850f74e101Schristos 	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
1860f74e101Schristos 	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
1870f74e101Schristos 	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
1880f74e101Schristos 	{ L2TP_AVP_ACCM,		"ACCM" },
1890f74e101Schristos 	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
1900f74e101Schristos 	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
1910f74e101Schristos 	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
1920f74e101Schristos 	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
1930f74e101Schristos 	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
1940f74e101Schristos 	{ 0,				NULL }
1950f74e101Schristos };
1960f74e101Schristos 
197870189d2Schristos static const struct tok l2tp_authentype2str[] = {
1980f74e101Schristos 	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
1990f74e101Schristos 	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
2000f74e101Schristos 	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
2010f74e101Schristos 	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
2020f74e101Schristos 	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
2030f74e101Schristos 	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
2040f74e101Schristos 	{ 0,				NULL }
2050f74e101Schristos };
2060f74e101Schristos 
2070f74e101Schristos #define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
2080f74e101Schristos #define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
2090f74e101Schristos #define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
2100f74e101Schristos 
211870189d2Schristos static const struct tok l2tp_cc_direction2str[] = {
2120f74e101Schristos 	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
2130f74e101Schristos 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
2140f74e101Schristos 	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
2150f74e101Schristos 	{ 0,					NULL }
2160f74e101Schristos };
2170f74e101Schristos 
2180f74e101Schristos #if 0
2190f74e101Schristos static char *l2tp_result_code_StopCCN[] = {
2200f74e101Schristos          "Reserved",
2210f74e101Schristos          "General request to clear control connection",
2220f74e101Schristos          "General error--Error Code indicates the problem",
2230f74e101Schristos          "Control channel already exists",
2240f74e101Schristos          "Requester is not authorized to establish a control channel",
2250f74e101Schristos          "The protocol version of the requester is not supported",
2260f74e101Schristos          "Requester is being shut down",
2270f74e101Schristos          "Finite State Machine error"
2280f74e101Schristos #define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
2290f74e101Schristos };
2300f74e101Schristos #endif
2310f74e101Schristos 
2320f74e101Schristos #if 0
2330f74e101Schristos static char *l2tp_result_code_CDN[] = {
2340f74e101Schristos 	"Reserved",
2350f74e101Schristos 	"Call disconnected due to loss of carrier",
2360f74e101Schristos 	"Call disconnected for the reason indicated in error code",
2370f74e101Schristos 	"Call disconnected for administrative reasons",
238c74ad251Schristos 	"Call failed due to lack of appropriate facilities being "
2390f74e101Schristos 	"available (temporary condition)",
240c74ad251Schristos 	"Call failed due to lack of appropriate facilities being "
2410f74e101Schristos 	"available (permanent condition)",
2420f74e101Schristos 	"Invalid destination",
2430f74e101Schristos 	"Call failed due to no carrier detected",
2440f74e101Schristos 	"Call failed due to detection of a busy signal",
2450f74e101Schristos 	"Call failed due to lack of a dial tone",
2460f74e101Schristos 	"Call was not established within time allotted by LAC",
2470f74e101Schristos 	"Call was connected but no appropriate framing was detected"
2480f74e101Schristos #define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
2490f74e101Schristos };
2500f74e101Schristos #endif
2510f74e101Schristos 
2520f74e101Schristos #if 0
2530f74e101Schristos static char *l2tp_error_code_general[] = {
2540f74e101Schristos 	"No general error",
2550f74e101Schristos 	"No control connection exists yet for this LAC-LNS pair",
2560f74e101Schristos 	"Length is wrong",
257c74ad251Schristos 	"One of the field values was out of range or "
2580f74e101Schristos 	"reserved field was non-zero"
2590f74e101Schristos 	"Insufficient resources to handle this operation now",
2600f74e101Schristos 	"The Session ID is invalid in this context",
2610f74e101Schristos 	"A generic vendor-specific error occurred in the LAC",
2620f74e101Schristos 	"Try another"
2630f74e101Schristos #define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
2640f74e101Schristos };
2650f74e101Schristos #endif
2660f74e101Schristos 
2670f74e101Schristos /******************************/
2680f74e101Schristos /* generic print out routines */
2690f74e101Schristos /******************************/
2700f74e101Schristos static void
271b3a00663Schristos print_string(netdissect_options *ndo, const u_char *dat, u_int length)
2720f74e101Schristos {
2730f74e101Schristos 	u_int i;
2740f74e101Schristos 	for (i=0; i<length; i++) {
275c74ad251Schristos 		fn_print_char(ndo, GET_U_1(dat));
276c74ad251Schristos 		dat++;
2770f74e101Schristos 	}
2780f74e101Schristos }
2790f74e101Schristos 
2800f74e101Schristos static void
281b3a00663Schristos print_octets(netdissect_options *ndo, const u_char *dat, u_int length)
2820f74e101Schristos {
2830f74e101Schristos 	u_int i;
2840f74e101Schristos 	for (i=0; i<length; i++) {
285c74ad251Schristos 		ND_PRINT("%02x", GET_U_1(dat));
286c74ad251Schristos 		dat++;
2870f74e101Schristos 	}
2880f74e101Schristos }
2890f74e101Schristos 
2900f74e101Schristos static void
291817e9a7eSchristos print_16bits_val(netdissect_options *ndo, const uint8_t *dat)
2920f74e101Schristos {
293c74ad251Schristos 	ND_PRINT("%u", GET_BE_U_2(dat));
2940f74e101Schristos }
2950f74e101Schristos 
2960f74e101Schristos static void
297817e9a7eSchristos print_32bits_val(netdissect_options *ndo, const uint8_t *dat)
2980f74e101Schristos {
299c74ad251Schristos 	ND_PRINT("%u", GET_BE_U_4(dat));
3000f74e101Schristos }
3010f74e101Schristos 
3020f74e101Schristos /***********************************/
3030f74e101Schristos /* AVP-specific print out routines */
3040f74e101Schristos /***********************************/
3050f74e101Schristos static void
30672c96ff3Schristos l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length)
3070f74e101Schristos {
30872c96ff3Schristos 	if (length < 2) {
309c74ad251Schristos 		ND_PRINT("AVP too short");
31072c96ff3Schristos 		return;
31172c96ff3Schristos 	}
312c74ad251Schristos 	ND_PRINT("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
313c74ad251Schristos 	    GET_BE_U_2(dat)));
3140f74e101Schristos }
3150f74e101Schristos 
3160f74e101Schristos static void
317b3a00663Schristos l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length)
3180f74e101Schristos {
31972c96ff3Schristos 	/* Result Code */
32072c96ff3Schristos 	if (length < 2) {
321c74ad251Schristos 		ND_PRINT("AVP too short");
32272c96ff3Schristos 		return;
3230f74e101Schristos 	}
324c74ad251Schristos 	ND_PRINT("%u", GET_BE_U_2(dat));
325817e9a7eSchristos 	dat += 2;
32672c96ff3Schristos 	length -= 2;
32772c96ff3Schristos 
32872c96ff3Schristos 	/* Error Code (opt) */
32972c96ff3Schristos 	if (length == 0)
33072c96ff3Schristos 		return;
33172c96ff3Schristos 	if (length < 2) {
332c74ad251Schristos 		ND_PRINT(" AVP too short");
33372c96ff3Schristos 		return;
33472c96ff3Schristos 	}
335c74ad251Schristos 	ND_PRINT("/%u", GET_BE_U_2(dat));
336817e9a7eSchristos 	dat += 2;
33772c96ff3Schristos 	length -= 2;
33872c96ff3Schristos 
33972c96ff3Schristos 	/* Error Message (opt) */
34072c96ff3Schristos 	if (length == 0)
34172c96ff3Schristos 		return;
342c74ad251Schristos 	ND_PRINT(" ");
343817e9a7eSchristos 	print_string(ndo, dat, length);
3440f74e101Schristos }
3450f74e101Schristos 
3460f74e101Schristos static void
347817e9a7eSchristos l2tp_proto_ver_print(netdissect_options *ndo, const u_char *dat, u_int length)
3480f74e101Schristos {
34972c96ff3Schristos 	if (length < 2) {
350c74ad251Schristos 		ND_PRINT("AVP too short");
35172c96ff3Schristos 		return;
35272c96ff3Schristos 	}
353c74ad251Schristos 	ND_PRINT("%u.%u", (GET_BE_U_2(dat) >> 8),
354c74ad251Schristos 		  (GET_BE_U_2(dat) & 0xff));
3550f74e101Schristos }
3560f74e101Schristos 
3570f74e101Schristos static void
35872c96ff3Schristos l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
3590f74e101Schristos {
36072c96ff3Schristos 	if (length < 4) {
361c74ad251Schristos 		ND_PRINT("AVP too short");
36272c96ff3Schristos 		return;
36372c96ff3Schristos 	}
364c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
365c74ad251Schristos 		ND_PRINT("A");
3660f74e101Schristos 	}
367c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_CAP_SYNC_MASK) {
368c74ad251Schristos 		ND_PRINT("S");
3690f74e101Schristos 	}
3700f74e101Schristos }
3710f74e101Schristos 
3720f74e101Schristos static void
37372c96ff3Schristos l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
3740f74e101Schristos {
37572c96ff3Schristos 	if (length < 4) {
376c74ad251Schristos 		ND_PRINT("AVP too short");
37772c96ff3Schristos 		return;
37872c96ff3Schristos 	}
379c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_BEARER_CAP_ANALOG_MASK) {
380c74ad251Schristos 		ND_PRINT("A");
3810f74e101Schristos 	}
382c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
383c74ad251Schristos 		ND_PRINT("D");
3840f74e101Schristos 	}
3850f74e101Schristos }
3860f74e101Schristos 
3870f74e101Schristos static void
388b3a00663Schristos l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
3890f74e101Schristos {
39072c96ff3Schristos 	if (length < 3) {
391c74ad251Schristos 		ND_PRINT("AVP too short");
39272c96ff3Schristos 		return;
39372c96ff3Schristos 	}
394817e9a7eSchristos 	print_16bits_val(ndo, dat);
395c74ad251Schristos 	ND_PRINT(", %02x", GET_U_1(dat + 2));
39672c96ff3Schristos 	dat += 3;
39772c96ff3Schristos 	length -= 3;
39872c96ff3Schristos 	if (length != 0) {
399c74ad251Schristos 		ND_PRINT(" ");
40072c96ff3Schristos 		print_string(ndo, dat, length);
4010f74e101Schristos 	}
4020f74e101Schristos }
4030f74e101Schristos 
4040f74e101Schristos static void
40572c96ff3Schristos l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
4060f74e101Schristos {
40772c96ff3Schristos 	if (length < 4) {
408c74ad251Schristos 		ND_PRINT("AVP too short");
40972c96ff3Schristos 		return;
41072c96ff3Schristos 	}
411c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
412c74ad251Schristos 		ND_PRINT("A");
4130f74e101Schristos 	}
414c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
415c74ad251Schristos 		ND_PRINT("D");
4160f74e101Schristos 	}
4170f74e101Schristos }
4180f74e101Schristos 
4190f74e101Schristos static void
42072c96ff3Schristos l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
4210f74e101Schristos {
42272c96ff3Schristos 	if (length < 4) {
423c74ad251Schristos 		ND_PRINT("AVP too short");
42472c96ff3Schristos 		return;
42572c96ff3Schristos 	}
426c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
427c74ad251Schristos 		ND_PRINT("A");
4280f74e101Schristos 	}
429c74ad251Schristos 	if (GET_BE_U_4(dat) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
430c74ad251Schristos 		ND_PRINT("S");
4310f74e101Schristos 	}
4320f74e101Schristos }
4330f74e101Schristos 
4340f74e101Schristos static void
435b3a00663Schristos l2tp_packet_proc_delay_print(netdissect_options *ndo)
4360f74e101Schristos {
437c74ad251Schristos 	ND_PRINT("obsolete");
4380f74e101Schristos }
4390f74e101Schristos 
4400f74e101Schristos static void
44172c96ff3Schristos l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
4420f74e101Schristos {
44372c96ff3Schristos 	if (length < 2) {
444c74ad251Schristos 		ND_PRINT("AVP too short");
44572c96ff3Schristos 		return;
44672c96ff3Schristos 	}
447c74ad251Schristos 	ND_PRINT("%s", tok2str(l2tp_authentype2str,
448c74ad251Schristos 			     "AuthType-#%u", GET_BE_U_2(dat)));
4490f74e101Schristos }
4500f74e101Schristos 
4510f74e101Schristos static void
45272c96ff3Schristos l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length)
4530f74e101Schristos {
45472c96ff3Schristos 	if (length < 2) {
455c74ad251Schristos 		ND_PRINT("AVP too short");
45672c96ff3Schristos 		return;
45772c96ff3Schristos 	}
458c74ad251Schristos 	ND_PRINT("%u", GET_BE_U_2(dat) & L2TP_PROXY_AUTH_ID_MASK);
4590f74e101Schristos }
4600f74e101Schristos 
4610f74e101Schristos static void
46272c96ff3Schristos l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length)
4630f74e101Schristos {
464817e9a7eSchristos 	uint32_t val;
4650f74e101Schristos 
46672c96ff3Schristos 	if (length < 2) {
467c74ad251Schristos 		ND_PRINT("AVP too short");
46872c96ff3Schristos 		return;
46972c96ff3Schristos 	}
470817e9a7eSchristos 	dat += 2;	/* skip "Reserved" */
47172c96ff3Schristos 	length -= 2;
4720f74e101Schristos 
47372c96ff3Schristos 	if (length < 4) {
474c74ad251Schristos 		ND_PRINT("AVP too short");
47572c96ff3Schristos 		return;
47672c96ff3Schristos 	}
477c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
478c74ad251Schristos 	ND_PRINT("CRCErr=%u ", val);
4790f74e101Schristos 
48072c96ff3Schristos 	if (length < 4) {
481c74ad251Schristos 		ND_PRINT("AVP too short");
48272c96ff3Schristos 		return;
48372c96ff3Schristos 	}
484c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
485c74ad251Schristos 	ND_PRINT("FrameErr=%u ", val);
4860f74e101Schristos 
48772c96ff3Schristos 	if (length < 4) {
488c74ad251Schristos 		ND_PRINT("AVP too short");
48972c96ff3Schristos 		return;
49072c96ff3Schristos 	}
491c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
492c74ad251Schristos 	ND_PRINT("HardOver=%u ", val);
4930f74e101Schristos 
49472c96ff3Schristos 	if (length < 4) {
495c74ad251Schristos 		ND_PRINT("AVP too short");
49672c96ff3Schristos 		return;
49772c96ff3Schristos 	}
498c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
499c74ad251Schristos 	ND_PRINT("BufOver=%u ", val);
5000f74e101Schristos 
50172c96ff3Schristos 	if (length < 4) {
502c74ad251Schristos 		ND_PRINT("AVP too short");
50372c96ff3Schristos 		return;
50472c96ff3Schristos 	}
505c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
506c74ad251Schristos 	ND_PRINT("Timeout=%u ", val);
5070f74e101Schristos 
50872c96ff3Schristos 	if (length < 4) {
509c74ad251Schristos 		ND_PRINT("AVP too short");
51072c96ff3Schristos 		return;
51172c96ff3Schristos 	}
512c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
513c74ad251Schristos 	ND_PRINT("AlignErr=%u ", val);
5140f74e101Schristos }
5150f74e101Schristos 
5160f74e101Schristos static void
51772c96ff3Schristos l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length)
5180f74e101Schristos {
519817e9a7eSchristos 	uint32_t val;
5200f74e101Schristos 
52172c96ff3Schristos 	if (length < 2) {
522c74ad251Schristos 		ND_PRINT("AVP too short");
52372c96ff3Schristos 		return;
52472c96ff3Schristos 	}
525817e9a7eSchristos 	dat += 2;	/* skip "Reserved" */
52672c96ff3Schristos 	length -= 2;
5270f74e101Schristos 
52872c96ff3Schristos 	if (length < 4) {
529c74ad251Schristos 		ND_PRINT("AVP too short");
53072c96ff3Schristos 		return;
53172c96ff3Schristos 	}
532c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
533c74ad251Schristos 	ND_PRINT("send=%08x ", val);
5340f74e101Schristos 
53572c96ff3Schristos 	if (length < 4) {
536c74ad251Schristos 		ND_PRINT("AVP too short");
53772c96ff3Schristos 		return;
53872c96ff3Schristos 	}
539c74ad251Schristos 	val = GET_BE_U_4(dat); dat += 4; length -= 4;
540c74ad251Schristos 	ND_PRINT("recv=%08x ", val);
5410f74e101Schristos }
5420f74e101Schristos 
5430f74e101Schristos static void
544b3a00663Schristos l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
5450f74e101Schristos {
54672c96ff3Schristos 	if (length < 5) {
547c74ad251Schristos 		ND_PRINT("AVP too short");
54872c96ff3Schristos 		return;
54972c96ff3Schristos 	}
55072c96ff3Schristos 	/* Disconnect Code */
551c74ad251Schristos 	ND_PRINT("%04x, ", GET_BE_U_2(dat));
55272c96ff3Schristos 	dat += 2;
55372c96ff3Schristos 	length -= 2;
55472c96ff3Schristos 	/* Control Protocol Number */
555c74ad251Schristos 	ND_PRINT("%04x ",  GET_BE_U_2(dat));
55672c96ff3Schristos 	dat += 2;
55772c96ff3Schristos 	length -= 2;
55872c96ff3Schristos 	/* Direction */
559c74ad251Schristos 	ND_PRINT("%s", tok2str(l2tp_cc_direction2str,
560c74ad251Schristos 			     "Direction-#%u", GET_U_1(dat)));
561817e9a7eSchristos 	dat++;
56272c96ff3Schristos 	length--;
5630f74e101Schristos 
56472c96ff3Schristos 	if (length != 0) {
565c74ad251Schristos 		ND_PRINT(" ");
566817e9a7eSchristos 		print_string(ndo, (const u_char *)dat, length);
5670f74e101Schristos 	}
5680f74e101Schristos }
5690f74e101Schristos 
570817e9a7eSchristos static u_int
571817e9a7eSchristos l2tp_avp_print(netdissect_options *ndo, const u_char *dat, u_int length)
5720f74e101Schristos {
5730f74e101Schristos 	u_int len;
574b3a00663Schristos 	uint16_t attr_type;
5750f74e101Schristos 	int hidden = FALSE;
5760f74e101Schristos 
577c74ad251Schristos 	ND_PRINT(" ");
578c74ad251Schristos 	/* Flags & Length */
579c74ad251Schristos 	len = GET_BE_U_2(dat) & L2TP_AVP_HDR_LEN_MASK;
5800f74e101Schristos 
5810f74e101Schristos 	/* If it is not long enough to contain the header, we'll give up. */
5820f74e101Schristos 	if (len < 6)
5830f74e101Schristos 		goto trunc;
5840f74e101Schristos 
5850f74e101Schristos 	/* If it goes past the end of the remaining length of the packet,
5860f74e101Schristos 	   we'll give up. */
5870f74e101Schristos 	if (len > (u_int)length)
5880f74e101Schristos 		goto trunc;
5890f74e101Schristos 
5900f74e101Schristos 	/* If it goes past the end of the remaining length of the captured
5910f74e101Schristos 	   data, we'll give up. */
592c74ad251Schristos 	ND_TCHECK_LEN(dat, len);
59372c96ff3Schristos 
59472c96ff3Schristos 	/*
59572c96ff3Schristos 	 * After this point, we don't need to check whether we go past
59672c96ff3Schristos 	 * the length of the captured data; however, we *do* need to
59772c96ff3Schristos 	 * check whether we go past the end of the AVP.
59872c96ff3Schristos 	 */
5990f74e101Schristos 
600c74ad251Schristos 	if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_MANDATORY) {
601c74ad251Schristos 		ND_PRINT("*");
6020f74e101Schristos 	}
603c74ad251Schristos 	if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_HIDDEN) {
6040f74e101Schristos 		hidden = TRUE;
605c74ad251Schristos 		ND_PRINT("?");
6060f74e101Schristos 	}
607817e9a7eSchristos 	dat += 2;
6080f74e101Schristos 
609c74ad251Schristos 	if (GET_BE_U_2(dat)) {
6100f74e101Schristos 		/* Vendor Specific Attribute */
611c74ad251Schristos 	        ND_PRINT("VENDOR%04x:", GET_BE_U_2(dat)); dat += 2;
612c74ad251Schristos 		ND_PRINT("ATTR%04x", GET_BE_U_2(dat)); dat += 2;
613c74ad251Schristos 		ND_PRINT("(");
614817e9a7eSchristos 		print_octets(ndo, dat, len-6);
615c74ad251Schristos 		ND_PRINT(")");
6160f74e101Schristos 	} else {
6170f74e101Schristos 		/* IETF-defined Attributes */
618817e9a7eSchristos 		dat += 2;
619c74ad251Schristos 		attr_type = GET_BE_U_2(dat); dat += 2;
620c74ad251Schristos 		ND_PRINT("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
621c74ad251Schristos 		ND_PRINT("(");
6220f74e101Schristos 		if (hidden) {
623c74ad251Schristos 			ND_PRINT("???");
6240f74e101Schristos 		} else {
6250f74e101Schristos 			switch (attr_type) {
6260f74e101Schristos 			case L2TP_AVP_MSGTYPE:
627817e9a7eSchristos 				l2tp_msgtype_print(ndo, dat, len-6);
6280f74e101Schristos 				break;
6290f74e101Schristos 			case L2TP_AVP_RESULT_CODE:
630817e9a7eSchristos 				l2tp_result_code_print(ndo, dat, len-6);
6310f74e101Schristos 				break;
6320f74e101Schristos 			case L2TP_AVP_PROTO_VER:
633817e9a7eSchristos 				l2tp_proto_ver_print(ndo, dat, len-6);
6340f74e101Schristos 				break;
6350f74e101Schristos 			case L2TP_AVP_FRAMING_CAP:
636817e9a7eSchristos 				l2tp_framing_cap_print(ndo, dat, len-6);
6370f74e101Schristos 				break;
6380f74e101Schristos 			case L2TP_AVP_BEARER_CAP:
639817e9a7eSchristos 				l2tp_bearer_cap_print(ndo, dat, len-6);
6400f74e101Schristos 				break;
6410f74e101Schristos 			case L2TP_AVP_TIE_BREAKER:
64272c96ff3Schristos 				if (len-6 < 8) {
643c74ad251Schristos 					ND_PRINT("AVP too short");
64472c96ff3Schristos 					break;
64572c96ff3Schristos 				}
646817e9a7eSchristos 				print_octets(ndo, dat, 8);
6470f74e101Schristos 				break;
6480f74e101Schristos 			case L2TP_AVP_FIRM_VER:
6490f74e101Schristos 			case L2TP_AVP_ASSND_TUN_ID:
6500f74e101Schristos 			case L2TP_AVP_RECV_WIN_SIZE:
6510f74e101Schristos 			case L2TP_AVP_ASSND_SESS_ID:
65272c96ff3Schristos 				if (len-6 < 2) {
653c74ad251Schristos 					ND_PRINT("AVP too short");
65472c96ff3Schristos 					break;
65572c96ff3Schristos 				}
656817e9a7eSchristos 				print_16bits_val(ndo, dat);
6570f74e101Schristos 				break;
6580f74e101Schristos 			case L2TP_AVP_HOST_NAME:
6590f74e101Schristos 			case L2TP_AVP_VENDOR_NAME:
6600f74e101Schristos 			case L2TP_AVP_CALLING_NUMBER:
6610f74e101Schristos 			case L2TP_AVP_CALLED_NUMBER:
6620f74e101Schristos 			case L2TP_AVP_SUB_ADDRESS:
6630f74e101Schristos 			case L2TP_AVP_PROXY_AUTH_NAME:
6640f74e101Schristos 			case L2TP_AVP_PRIVATE_GRP_ID:
665817e9a7eSchristos 				print_string(ndo, dat, len-6);
6660f74e101Schristos 				break;
6670f74e101Schristos 			case L2TP_AVP_CHALLENGE:
6680f74e101Schristos 			case L2TP_AVP_INI_RECV_LCP:
6690f74e101Schristos 			case L2TP_AVP_LAST_SENT_LCP:
6700f74e101Schristos 			case L2TP_AVP_LAST_RECV_LCP:
6710f74e101Schristos 			case L2TP_AVP_PROXY_AUTH_CHAL:
6720f74e101Schristos 			case L2TP_AVP_PROXY_AUTH_RESP:
6730f74e101Schristos 			case L2TP_AVP_RANDOM_VECTOR:
674817e9a7eSchristos 				print_octets(ndo, dat, len-6);
6750f74e101Schristos 				break;
6760f74e101Schristos 			case L2TP_AVP_Q931_CC:
677817e9a7eSchristos 				l2tp_q931_cc_print(ndo, dat, len-6);
6780f74e101Schristos 				break;
6790f74e101Schristos 			case L2TP_AVP_CHALLENGE_RESP:
68072c96ff3Schristos 				if (len-6 < 16) {
681c74ad251Schristos 					ND_PRINT("AVP too short");
68272c96ff3Schristos 					break;
68372c96ff3Schristos 				}
684817e9a7eSchristos 				print_octets(ndo, dat, 16);
6850f74e101Schristos 				break;
6860f74e101Schristos 			case L2TP_AVP_CALL_SER_NUM:
6870f74e101Schristos 			case L2TP_AVP_MINIMUM_BPS:
6880f74e101Schristos 			case L2TP_AVP_MAXIMUM_BPS:
6890f74e101Schristos 			case L2TP_AVP_TX_CONN_SPEED:
6900f74e101Schristos 			case L2TP_AVP_PHY_CHANNEL_ID:
6910f74e101Schristos 			case L2TP_AVP_RX_CONN_SPEED:
69272c96ff3Schristos 				if (len-6 < 4) {
693c74ad251Schristos 					ND_PRINT("AVP too short");
69472c96ff3Schristos 					break;
69572c96ff3Schristos 				}
696817e9a7eSchristos 				print_32bits_val(ndo, dat);
6970f74e101Schristos 				break;
6980f74e101Schristos 			case L2TP_AVP_BEARER_TYPE:
699817e9a7eSchristos 				l2tp_bearer_type_print(ndo, dat, len-6);
7000f74e101Schristos 				break;
7010f74e101Schristos 			case L2TP_AVP_FRAMING_TYPE:
702817e9a7eSchristos 				l2tp_framing_type_print(ndo, dat, len-6);
7030f74e101Schristos 				break;
7040f74e101Schristos 			case L2TP_AVP_PACKET_PROC_DELAY:
705b3a00663Schristos 				l2tp_packet_proc_delay_print(ndo);
7060f74e101Schristos 				break;
7070f74e101Schristos 			case L2TP_AVP_PROXY_AUTH_TYPE:
708817e9a7eSchristos 				l2tp_proxy_auth_type_print(ndo, dat, len-6);
7090f74e101Schristos 				break;
7100f74e101Schristos 			case L2TP_AVP_PROXY_AUTH_ID:
711817e9a7eSchristos 				l2tp_proxy_auth_id_print(ndo, dat, len-6);
7120f74e101Schristos 				break;
7130f74e101Schristos 			case L2TP_AVP_CALL_ERRORS:
714817e9a7eSchristos 				l2tp_call_errors_print(ndo, dat, len-6);
7150f74e101Schristos 				break;
7160f74e101Schristos 			case L2TP_AVP_ACCM:
717817e9a7eSchristos 				l2tp_accm_print(ndo, dat, len-6);
7180f74e101Schristos 				break;
7190f74e101Schristos 			case L2TP_AVP_SEQ_REQUIRED:
7200f74e101Schristos 				break;	/* No Attribute Value */
7210f74e101Schristos 			case L2TP_AVP_PPP_DISCON_CC:
722817e9a7eSchristos 				l2tp_ppp_discon_cc_print(ndo, dat, len-6);
7230f74e101Schristos 				break;
7240f74e101Schristos 			default:
7250f74e101Schristos 				break;
7260f74e101Schristos 			}
7270f74e101Schristos 		}
728c74ad251Schristos 		ND_PRINT(")");
7290f74e101Schristos 	}
7300f74e101Schristos 
731817e9a7eSchristos 	return (len);
7320f74e101Schristos 
7330f74e101Schristos  trunc:
734c74ad251Schristos 	nd_print_trunc(ndo);
735817e9a7eSchristos 	return (0);
7360f74e101Schristos }
7370f74e101Schristos 
7380f74e101Schristos 
7390f74e101Schristos void
740b3a00663Schristos l2tp_print(netdissect_options *ndo, const u_char *dat, u_int length)
7410f74e101Schristos {
7420f74e101Schristos 	const u_char *ptr = dat;
7430f74e101Schristos 	u_int cnt = 0;			/* total octets consumed */
744b3a00663Schristos 	uint16_t pad;
7450f74e101Schristos 	int flag_t, flag_l, flag_s, flag_o;
746b3a00663Schristos 	uint16_t l2tp_len;
7470f74e101Schristos 
748c74ad251Schristos 	ndo->ndo_protocol = "l2tp";
7490f74e101Schristos 	flag_t = flag_l = flag_s = flag_o = FALSE;
7500f74e101Schristos 
751c74ad251Schristos 	if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
752c74ad251Schristos 		ND_PRINT(" l2tp:");
753c74ad251Schristos 	} else if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
754c74ad251Schristos 		ND_PRINT(" l2f:");
7550f74e101Schristos 		return;		/* nothing to do */
7560f74e101Schristos 	} else {
757c74ad251Schristos 		ND_PRINT(" Unknown Version, neither L2F(1) nor L2TP(2)");
7580f74e101Schristos 		return;		/* nothing we can do */
7590f74e101Schristos 	}
7600f74e101Schristos 
761c74ad251Schristos 	ND_PRINT("[");
762c74ad251Schristos 	if (GET_BE_U_2(ptr) & L2TP_FLAG_TYPE) {
7630f74e101Schristos 		flag_t = TRUE;
764c74ad251Schristos 		ND_PRINT("T");
7650f74e101Schristos 	}
766c74ad251Schristos 	if (GET_BE_U_2(ptr) & L2TP_FLAG_LENGTH) {
7670f74e101Schristos 		flag_l = TRUE;
768c74ad251Schristos 		ND_PRINT("L");
7690f74e101Schristos 	}
770c74ad251Schristos 	if (GET_BE_U_2(ptr) & L2TP_FLAG_SEQUENCE) {
7710f74e101Schristos 		flag_s = TRUE;
772c74ad251Schristos 		ND_PRINT("S");
7730f74e101Schristos 	}
774c74ad251Schristos 	if (GET_BE_U_2(ptr) & L2TP_FLAG_OFFSET) {
7750f74e101Schristos 		flag_o = TRUE;
776c74ad251Schristos 		ND_PRINT("O");
7770f74e101Schristos 	}
778c74ad251Schristos 	if (GET_BE_U_2(ptr) & L2TP_FLAG_PRIORITY)
779c74ad251Schristos 		ND_PRINT("P");
780c74ad251Schristos 	ND_PRINT("]");
7810f74e101Schristos 
7820f74e101Schristos 	ptr += 2;
7830f74e101Schristos 	cnt += 2;
7840f74e101Schristos 
7850f74e101Schristos 	if (flag_l) {
786c74ad251Schristos 		l2tp_len = GET_BE_U_2(ptr);
7870f74e101Schristos 		ptr += 2;
7880f74e101Schristos 		cnt += 2;
7890f74e101Schristos 	} else {
7900f74e101Schristos 		l2tp_len = 0;
7910f74e101Schristos 	}
792c74ad251Schristos 	/* Tunnel ID */
793c74ad251Schristos 	ND_PRINT("(%u/", GET_BE_U_2(ptr));
7940f74e101Schristos 	ptr += 2;
7950f74e101Schristos 	cnt += 2;
796c74ad251Schristos 	/* Session ID */
797c74ad251Schristos 	ND_PRINT("%u)",  GET_BE_U_2(ptr));
7980f74e101Schristos 	ptr += 2;
7990f74e101Schristos 	cnt += 2;
8000f74e101Schristos 
8010f74e101Schristos 	if (flag_s) {
802c74ad251Schristos 		ND_PRINT("Ns=%u,", GET_BE_U_2(ptr));
8030f74e101Schristos 		ptr += 2;
8040f74e101Schristos 		cnt += 2;
805c74ad251Schristos 		ND_PRINT("Nr=%u",  GET_BE_U_2(ptr));
8060f74e101Schristos 		ptr += 2;
8070f74e101Schristos 		cnt += 2;
8080f74e101Schristos 	}
8090f74e101Schristos 
810c74ad251Schristos 	if (flag_o) {	/* Offset Size */
811c74ad251Schristos 		pad =  GET_BE_U_2(ptr);
812c74ad251Schristos 		/* Offset padding octets in packet buffer? */
813c74ad251Schristos 		ND_TCHECK_LEN(ptr + 2, pad);
8140f74e101Schristos 		ptr += (2 + pad);
8150f74e101Schristos 		cnt += (2 + pad);
8160f74e101Schristos 	}
8170f74e101Schristos 
8180f74e101Schristos 	if (flag_l) {
8190f74e101Schristos 		if (length < l2tp_len) {
820c74ad251Schristos 			ND_PRINT(" Length %u larger than packet", l2tp_len);
8210f74e101Schristos 			return;
8220f74e101Schristos 		}
8230f74e101Schristos 		length = l2tp_len;
8240f74e101Schristos 	}
8250f74e101Schristos 	if (length < cnt) {
826c74ad251Schristos 		ND_PRINT(" Length %u smaller than header length", length);
8270f74e101Schristos 		return;
8280f74e101Schristos 	}
8290f74e101Schristos 	if (flag_t) {
8300f74e101Schristos 		if (!flag_l) {
831c74ad251Schristos 			ND_PRINT(" No length");
8320f74e101Schristos 			return;
8330f74e101Schristos 		}
8340f74e101Schristos 		if (length - cnt == 0) {
835c74ad251Schristos 			ND_PRINT(" ZLB");
8360f74e101Schristos 		} else {
837817e9a7eSchristos 			/*
838817e9a7eSchristos 			 * Print AVPs.
839817e9a7eSchristos 			 */
840817e9a7eSchristos 			while (length - cnt != 0) {
841817e9a7eSchristos 				u_int avp_length;
842817e9a7eSchristos 
843817e9a7eSchristos 				avp_length = l2tp_avp_print(ndo, ptr, length - cnt);
844817e9a7eSchristos 				if (avp_length == 0) {
845817e9a7eSchristos 					/*
846817e9a7eSchristos 					 * Truncated.
847817e9a7eSchristos 					 */
848817e9a7eSchristos 					break;
849817e9a7eSchristos 				}
850817e9a7eSchristos 				cnt += avp_length;
851817e9a7eSchristos 				ptr += avp_length;
852817e9a7eSchristos 			}
8530f74e101Schristos 		}
8540f74e101Schristos 	} else {
855c74ad251Schristos 		ND_PRINT(" {");
856b3a00663Schristos 		ppp_print(ndo, ptr, length - cnt);
857c74ad251Schristos 		ND_PRINT("}");
8580f74e101Schristos 	}
8590f74e101Schristos 	return;
8600f74e101Schristos trunc:
861c74ad251Schristos 	nd_print_trunc(ndo);
8620f74e101Schristos }
863