print-l2tp.c revision 147899
156893Sfenner/*
256893Sfenner * Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
356893Sfenner *      The Regents of the University of California.  All rights reserved.
456893Sfenner *
556893Sfenner * Redistribution and use in source and binary forms, with or without
656893Sfenner * modification, are permitted provided that: (1) source code distributions
756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2)
856893Sfenner * distributions including binary code include the above copyright notice and
956893Sfenner * this paragraph in its entirety in the documentation or other materials
1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning
1156893Sfenner * features or use of this software display the following acknowledgement:
1256893Sfenner * ``This product includes software developed by the University of California,
1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1456893Sfenner * the University nor the names of its contributors may be used to endorse
1556893Sfenner * or promote products derived from this software without specific prior
1656893Sfenner * written permission.
1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2056893Sfenner *
2175115Sfenner * L2TP support contributed by Motonori Shindo (mshindo@mshindo.net)
2256893Sfenner */
2356893Sfenner
2456893Sfenner#ifndef lint
25127668Sbmsstatic const char rcsid[] _U_ =
26147899Ssam    "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.17.2.2 2005/04/20 21:50:16 guy Exp $";
2756893Sfenner#endif
2856893Sfenner
2956893Sfenner#ifdef HAVE_CONFIG_H
3056893Sfenner#include "config.h"
3156893Sfenner#endif
3256893Sfenner
33127668Sbms#include <tcpdump-stdinc.h>
34127668Sbms
3556893Sfenner#include <stdio.h>
3656893Sfenner
3756893Sfenner#include "l2tp.h"
3856893Sfenner#include "interface.h"
39111726Sfenner#include "extract.h"
4056893Sfenner
4156893Sfennerstatic char tstr[] = " [|l2tp]";
4256893Sfenner
4356893Sfenner#ifndef TRUE
4456893Sfenner#define TRUE 1
4556893Sfenner#endif
4656893Sfenner
4756893Sfenner#ifndef FALSE
4856893Sfenner#define FALSE 0
4956893Sfenner#endif
5056893Sfenner
5198524Sfenner#define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
5298524Sfenner#define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
5398524Sfenner#define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
5498524Sfenner#define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
5598524Sfenner#define	L2TP_MSGTYPE_HELLO	6  /* Hello */
5698524Sfenner#define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
5798524Sfenner#define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
5898524Sfenner#define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
5998524Sfenner#define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
6098524Sfenner#define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
6198524Sfenner#define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
6298524Sfenner#define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
6398524Sfenner#define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
6498524Sfenner#define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
6598524Sfenner
6698524Sfennerstatic struct tok l2tp_msgtype2str[] = {
6798524Sfenner	{ L2TP_MSGTYPE_SCCRQ, 	"SCCRQ" },
6898524Sfenner	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
6998524Sfenner	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
7098524Sfenner	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
7198524Sfenner	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
7298524Sfenner	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
7398524Sfenner	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
7498524Sfenner	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
7598524Sfenner	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
7698524Sfenner	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
7798524Sfenner	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
7898524Sfenner	{ L2TP_MSGTYPE_CDN,	"CDN" },
7998524Sfenner	{ L2TP_MSGTYPE_WEN,	"WEN" },
8098524Sfenner	{ L2TP_MSGTYPE_SLI,	"SLI" },
8198524Sfenner	{ 0,			NULL }
8256893Sfenner};
8356893Sfenner
8498524Sfenner#define L2TP_AVP_MSGTYPE		0  /* Message Type */
8598524Sfenner#define L2TP_AVP_RESULT_CODE		1  /* Result Code */
8698524Sfenner#define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
8798524Sfenner#define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
8898524Sfenner#define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
8998524Sfenner#define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
9098524Sfenner#define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
9198524Sfenner#define L2TP_AVP_HOST_NAME		7  /* Host Name */
9298524Sfenner#define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
9398524Sfenner#define L2TP_AVP_ASSND_TUN_ID 		9  /* Assigned Tunnel ID */
9498524Sfenner#define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
9598524Sfenner#define L2TP_AVP_CHALLENGE		11 /* Challenge */
9698524Sfenner#define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
9798524Sfenner#define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
9898524Sfenner#define L2TP_AVP_ASSND_SESS_ID  	14 /* Assigned Session ID */
9998524Sfenner#define L2TP_AVP_CALL_SER_NUM 		15 /* Call Serial Number */
10098524Sfenner#define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
10198524Sfenner#define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
10298524Sfenner#define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
10398524Sfenner#define L2TP_AVP_FRAMING_TYPE 		19 /* Framing Type */
10498524Sfenner#define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
10598524Sfenner#define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
10698524Sfenner#define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
10798524Sfenner#define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
10898524Sfenner#define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
10998524Sfenner#define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
11098524Sfenner#define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
11198524Sfenner#define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
11298524Sfenner#define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
11398524Sfenner#define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
11498524Sfenner#define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
11598524Sfenner#define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
11698524Sfenner#define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
11798524Sfenner#define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
11898524Sfenner#define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
11998524Sfenner#define L2TP_AVP_ACCM			35 /* ACCM */
12098524Sfenner#define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
12198524Sfenner#define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
12298524Sfenner#define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
12398524Sfenner#define L2TP_AVP_SEQ_REQUIRED 		39 /* Sequencing Required */
12498524Sfenner#define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code */
12556893Sfenner
12698524Sfennerstatic struct tok l2tp_avp2str[] = {
12798524Sfenner	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
12898524Sfenner	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
12998524Sfenner	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
13098524Sfenner	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
13198524Sfenner	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
13298524Sfenner	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
13398524Sfenner	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
13498524Sfenner	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
13598524Sfenner	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
13698524Sfenner	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
13798524Sfenner	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
13898524Sfenner	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
13998524Sfenner	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
14098524Sfenner	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
14198524Sfenner	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
14298524Sfenner	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
14398524Sfenner	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
14498524Sfenner	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
14598524Sfenner	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
14698524Sfenner	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
147127668Sbms	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
14898524Sfenner	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
14998524Sfenner	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
15098524Sfenner	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
15198524Sfenner	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
15298524Sfenner	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
15398524Sfenner	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
154127668Sbms	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
155127668Sbms	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
156127668Sbms	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
15798524Sfenner	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
158127668Sbms	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
15998524Sfenner	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
16098524Sfenner	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
16198524Sfenner	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
162127668Sbms	{ L2TP_AVP_ACCM,		"ACCM" },
163127668Sbms	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
16498524Sfenner	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
165127668Sbms	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
166127668Sbms	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
167127668Sbms	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
16898524Sfenner	{ 0,				NULL }
16956893Sfenner};
17056893Sfenner
17198524Sfennerstatic struct tok l2tp_authentype2str[] = {
17298524Sfenner	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
17398524Sfenner	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
17498524Sfenner	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
17598524Sfenner	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
17698524Sfenner	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
17798524Sfenner	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
17898524Sfenner	{ 0,				NULL }
17998524Sfenner};
18098524Sfenner
18198524Sfenner#define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
18298524Sfenner#define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
18398524Sfenner#define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
18498524Sfenner
18598524Sfennerstatic struct tok l2tp_cc_direction2str[] = {
18698524Sfenner	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
18798524Sfenner	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
18898524Sfenner	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
18998524Sfenner	{ 0,					NULL }
19098524Sfenner};
19198524Sfenner
19256893Sfenner#if 0
19356893Sfennerstatic char *l2tp_result_code_StopCCN[] = {
19456893Sfenner         "Reserved",
19556893Sfenner         "General request to clear control connection",
19656893Sfenner         "General error--Error Code indicates the problem",
19756893Sfenner         "Control channel already exists",
19856893Sfenner         "Requester is not authorized to establish a control channel",
19956893Sfenner         "The protocol version of the requester is not supported",
20056893Sfenner         "Requester is being shut down",
20156893Sfenner         "Finite State Machine error"
20256893Sfenner#define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
20356893Sfenner};
20456893Sfenner#endif
20556893Sfenner
20656893Sfenner#if 0
20756893Sfennerstatic char *l2tp_result_code_CDN[] = {
20856893Sfenner	"Reserved",
20956893Sfenner	"Call disconnected due to loss of carrier",
21056893Sfenner	"Call disconnected for the reason indicated in error code",
21156893Sfenner	"Call disconnected for administrative reasons",
21256893Sfenner	"Call failed due to lack of appropriate facilities being " \
21356893Sfenner	"available (temporary condition)",
21456893Sfenner	"Call failed due to lack of appropriate facilities being " \
21556893Sfenner	"available (permanent condition)",
21656893Sfenner	"Invalid destination",
21756893Sfenner	"Call failed due to no carrier detected",
21856893Sfenner	"Call failed due to detection of a busy signal",
21956893Sfenner	"Call failed due to lack of a dial tone",
22056893Sfenner	"Call was not established within time allotted by LAC",
22156893Sfenner	"Call was connected but no appropriate framing was detected"
22256893Sfenner#define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
22356893Sfenner};
22456893Sfenner#endif
22556893Sfenner
22656893Sfenner#if 0
22756893Sfennerstatic char *l2tp_error_code_general[] = {
22856893Sfenner	"No general error",
22956893Sfenner	"No control connection exists yet for this LAC-LNS pair",
23056893Sfenner	"Length is wrong",
23156893Sfenner	"One of the field values was out of range or " \
23256893Sfenner	"reserved field was non-zero"
23356893Sfenner	"Insufficient resources to handle this operation now",
23456893Sfenner	"The Session ID is invalid in this context",
23556893Sfenner	"A generic vendor-specific error occurred in the LAC",
23656893Sfenner	"Try another"
23756893Sfenner#define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
23856893Sfenner};
23956893Sfenner#endif
24056893Sfenner
24156893Sfenner/******************************/
24256893Sfenner/* generic print out routines */
24356893Sfenner/******************************/
244127668Sbmsstatic void
24556893Sfennerprint_string(const u_char *dat, u_int length)
24656893Sfenner{
247127668Sbms	u_int i;
24856893Sfenner	for (i=0; i<length; i++) {
24956893Sfenner		printf("%c", *dat++);
25056893Sfenner	}
25156893Sfenner}
25256893Sfenner
253127668Sbmsstatic void
25456893Sfennerprint_octets(const u_char *dat, u_int length)
25556893Sfenner{
256127668Sbms	u_int i;
25756893Sfenner	for (i=0; i<length; i++) {
25856893Sfenner		printf("%02x", *dat++);
25956893Sfenner	}
26056893Sfenner}
26156893Sfenner
26256893Sfennerstatic void
26398524Sfennerprint_16bits_val(const u_int16_t *dat)
26456893Sfenner{
265111726Sfenner	printf("%u", EXTRACT_16BITS(dat));
26656893Sfenner}
26756893Sfenner
26856893Sfennerstatic void
26998524Sfennerprint_32bits_val(const u_int32_t *dat)
27056893Sfenner{
271111726Sfenner	printf("%lu", (u_long)EXTRACT_32BITS(dat));
27256893Sfenner}
27356893Sfenner
27498524Sfenner/***********************************/
27598524Sfenner/* AVP-specific print out routines */
27698524Sfenner/***********************************/
27756893Sfennerstatic void
27898524Sfennerl2tp_msgtype_print(const u_char *dat)
27956893Sfenner{
28098524Sfenner	u_int16_t *ptr = (u_int16_t*)dat;
28156893Sfenner
282111726Sfenner	printf("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
283111726Sfenner	    EXTRACT_16BITS(ptr)));
28456893Sfenner}
28556893Sfenner
28656893Sfennerstatic void
28756893Sfennerl2tp_result_code_print(const u_char *dat, u_int length)
28856893Sfenner{
28998524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
290127668Sbms
291111726Sfenner	printf("%u", EXTRACT_16BITS(ptr)); ptr++;	/* Result Code */
292111726Sfenner	if (length > 2) {				/* Error Code (opt) */
293111726Sfenner	        printf("/%u", EXTRACT_16BITS(ptr)); ptr++;
29456893Sfenner	}
295111726Sfenner	if (length > 4) {				/* Error Message (opt) */
29698524Sfenner		printf(" ");
29798524Sfenner		print_string((u_char *)ptr, length - 4);
29898524Sfenner	}
29956893Sfenner}
30056893Sfenner
30156893Sfennerstatic void
30298524Sfennerl2tp_proto_ver_print(const u_int16_t *dat)
30356893Sfenner{
304111726Sfenner	printf("%u.%u", (EXTRACT_16BITS(dat) >> 8),
305111726Sfenner	    (EXTRACT_16BITS(dat) & 0xff));
30656893Sfenner}
30756893Sfenner
30856893Sfennerstatic void
30998524Sfennerl2tp_framing_cap_print(const u_char *dat)
31056893Sfenner{
31198524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
31256893Sfenner
313111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
31456893Sfenner		printf("A");
31556893Sfenner	}
316111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_SYNC_MASK) {
31756893Sfenner		printf("S");
31856893Sfenner	}
31956893Sfenner}
32056893Sfenner
32156893Sfennerstatic void
32298524Sfennerl2tp_bearer_cap_print(const u_char *dat)
32356893Sfenner{
32498524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
32556893Sfenner
326111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_ANALOG_MASK) {
32756893Sfenner		printf("A");
32856893Sfenner	}
329111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
33056893Sfenner		printf("D");
33156893Sfenner	}
33256893Sfenner}
33356893Sfenner
33456893Sfennerstatic void
33556893Sfennerl2tp_q931_cc_print(const u_char *dat, u_int length)
33656893Sfenner{
33798524Sfenner	print_16bits_val((u_int16_t *)dat);
33856893Sfenner	printf(", %02x", dat[2]);
33956893Sfenner	if (length > 3) {
34056893Sfenner		printf(" ");
34156893Sfenner		print_string(dat+3, length-3);
342127668Sbms	}
34356893Sfenner}
34456893Sfenner
34556893Sfennerstatic void
34698524Sfennerl2tp_bearer_type_print(const u_char *dat)
34756893Sfenner{
34898524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
34956893Sfenner
350111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
35156893Sfenner		printf("A");
35256893Sfenner	}
353111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
35456893Sfenner		printf("D");
35556893Sfenner	}
35656893Sfenner}
35756893Sfenner
35856893Sfennerstatic void
35998524Sfennerl2tp_framing_type_print(const u_char *dat)
36056893Sfenner{
36198524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
36256893Sfenner
363111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
36456893Sfenner		printf("A");
36556893Sfenner	}
366111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
36756893Sfenner		printf("S");
36856893Sfenner	}
36956893Sfenner}
37056893Sfenner
37156893Sfennerstatic void
37298524Sfennerl2tp_packet_proc_delay_print(void)
37356893Sfenner{
37456893Sfenner	printf("obsolete");
37556893Sfenner}
37656893Sfenner
37756893Sfennerstatic void
37898524Sfennerl2tp_proxy_auth_type_print(const u_char *dat)
37956893Sfenner{
38098524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
38156893Sfenner
382127668Sbms	printf("%s", tok2str(l2tp_authentype2str,
383111726Sfenner			     "AuthType-#%u", EXTRACT_16BITS(ptr)));
38456893Sfenner}
38556893Sfenner
38656893Sfennerstatic void
38798524Sfennerl2tp_proxy_auth_id_print(const u_char *dat)
38856893Sfenner{
38998524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
39056893Sfenner
391111726Sfenner	printf("%u", EXTRACT_16BITS(ptr) & L2TP_PROXY_AUTH_ID_MASK);
39256893Sfenner}
39356893Sfenner
39456893Sfennerstatic void
39598524Sfennerl2tp_call_errors_print(const u_char *dat)
39656893Sfenner{
39798524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
39898524Sfenner	u_int16_t val_h, val_l;
399127668Sbms
40098524Sfenner	ptr++;		/* skip "Reserved" */
40156893Sfenner
402111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
403111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
40498524Sfenner	printf("CRCErr=%u ", (val_h<<16) + val_l);
40556893Sfenner
406111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
407111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
40898524Sfenner	printf("FrameErr=%u ", (val_h<<16) + val_l);
40956893Sfenner
410111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
411111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
41298524Sfenner	printf("HardOver=%u ", (val_h<<16) + val_l);
41356893Sfenner
414111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
415111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
41698524Sfenner	printf("BufOver=%u ", (val_h<<16) + val_l);
41756893Sfenner
418111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
419111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
42098524Sfenner	printf("Timeout=%u ", (val_h<<16) + val_l);
42156893Sfenner
422111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
423111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
42498524Sfenner	printf("AlignErr=%u ", (val_h<<16) + val_l);
42556893Sfenner}
42656893Sfenner
42756893Sfennerstatic void
42898524Sfennerl2tp_accm_print(const u_char *dat)
42956893Sfenner{
43098524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
43198524Sfenner	u_int16_t val_h, val_l;
43256893Sfenner
43398524Sfenner	ptr++;		/* skip "Reserved" */
43456893Sfenner
435111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
436111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
43798524Sfenner	printf("send=%08x ", (val_h<<16) + val_l);
438127668Sbms
439111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
440111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
44198524Sfenner	printf("recv=%08x ", (val_h<<16) + val_l);
44256893Sfenner}
44356893Sfenner
44456893Sfennerstatic void
44598524Sfennerl2tp_ppp_discon_cc_print(const u_char *dat, u_int length)
44656893Sfenner{
44798524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
448127668Sbms
449111726Sfenner	printf("%04x, ", EXTRACT_16BITS(ptr)); ptr++;	/* Disconnect Code */
450111726Sfenner	printf("%04x ",  EXTRACT_16BITS(ptr)); ptr++;	/* Control Protocol Number */
451127668Sbms	printf("%s", tok2str(l2tp_cc_direction2str,
45298524Sfenner			     "Direction-#%u", *((u_char *)ptr++)));
45356893Sfenner
45498524Sfenner	if (length > 5) {
45598524Sfenner		printf(" ");
45698524Sfenner		print_string((const u_char *)ptr, length-5);
45798524Sfenner	}
45856893Sfenner}
45956893Sfenner
46056893Sfennerstatic void
46198524Sfennerl2tp_avp_print(const u_char *dat, int length)
46256893Sfenner{
46398524Sfenner	u_int len;
46498524Sfenner	const u_int16_t *ptr = (u_int16_t *)dat;
46598524Sfenner	u_int16_t attr_type;
46698524Sfenner	int hidden = FALSE;
46756893Sfenner
46898524Sfenner	if (length <= 0) {
46998524Sfenner		return;
47098524Sfenner	}
47156893Sfenner
47298524Sfenner	printf(" ");
47356893Sfenner
47498524Sfenner	TCHECK(*ptr);	/* Flags & Length */
475111726Sfenner	len = EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_LEN_MASK;
47656893Sfenner
477124486Sfenner	/* If it is not long enough to contain the header, we'll give up. */
478124486Sfenner	if (len < 6)
479124486Sfenner		goto trunc;
480124486Sfenner
481124486Sfenner	/* If it goes past the end of the remaining length of the packet,
482124486Sfenner	   we'll give up. */
483124486Sfenner	if (len > (u_int)length)
484124486Sfenner		goto trunc;
485124486Sfenner
486124486Sfenner	/* If it goes past the end of the remaining length of the captured
487124486Sfenner	   data, we'll give up. */
48898524Sfenner	TCHECK2(*ptr, len);
48998524Sfenner	/* After this point, no need to worry about truncation */
49056893Sfenner
491111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
49298524Sfenner		printf("*");
49398524Sfenner	}
494111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
49598524Sfenner		hidden = TRUE;
49698524Sfenner		printf("?");
49798524Sfenner	}
49898524Sfenner	ptr++;
49956893Sfenner
500111726Sfenner	if (EXTRACT_16BITS(ptr)) {
50198524Sfenner		/* Vendor Specific Attribute */
502111726Sfenner	        printf("VENDOR%04x:", EXTRACT_16BITS(ptr)); ptr++;
503111726Sfenner		printf("ATTR%04x", EXTRACT_16BITS(ptr)); ptr++;
50498524Sfenner		printf("(");
50598524Sfenner		print_octets((u_char *)ptr, len-6);
50698524Sfenner		printf(")");
50798524Sfenner	} else {
508127668Sbms		/* IETF-defined Attributes */
50956893Sfenner		ptr++;
510111726Sfenner		attr_type = EXTRACT_16BITS(ptr); ptr++;
51198524Sfenner		printf("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
51298524Sfenner		printf("(");
51398524Sfenner		if (hidden) {
51498524Sfenner			printf("???");
51575115Sfenner		} else {
51698524Sfenner			switch (attr_type) {
51798524Sfenner			case L2TP_AVP_MSGTYPE:
51898524Sfenner				l2tp_msgtype_print((u_char *)ptr);
51998524Sfenner				break;
52098524Sfenner			case L2TP_AVP_RESULT_CODE:
52198524Sfenner				l2tp_result_code_print((u_char *)ptr, len-6);
52298524Sfenner				break;
52398524Sfenner			case L2TP_AVP_PROTO_VER:
52498524Sfenner				l2tp_proto_ver_print(ptr);
52598524Sfenner				break;
52698524Sfenner			case L2TP_AVP_FRAMING_CAP:
52798524Sfenner				l2tp_framing_cap_print((u_char *)ptr);
52898524Sfenner				break;
52998524Sfenner			case L2TP_AVP_BEARER_CAP:
53098524Sfenner				l2tp_bearer_cap_print((u_char *)ptr);
53198524Sfenner				break;
53298524Sfenner			case L2TP_AVP_TIE_BREAKER:
53398524Sfenner				print_octets((u_char *)ptr, 8);
53498524Sfenner				break;
53598524Sfenner			case L2TP_AVP_FIRM_VER:
53698524Sfenner			case L2TP_AVP_ASSND_TUN_ID:
53798524Sfenner			case L2TP_AVP_RECV_WIN_SIZE:
53898524Sfenner			case L2TP_AVP_ASSND_SESS_ID:
53998524Sfenner				print_16bits_val(ptr);
54098524Sfenner				break;
54198524Sfenner			case L2TP_AVP_HOST_NAME:
54298524Sfenner			case L2TP_AVP_VENDOR_NAME:
54398524Sfenner			case L2TP_AVP_CALLING_NUMBER:
54498524Sfenner			case L2TP_AVP_CALLED_NUMBER:
54598524Sfenner			case L2TP_AVP_SUB_ADDRESS:
54698524Sfenner			case L2TP_AVP_PROXY_AUTH_NAME:
547127668Sbms			case L2TP_AVP_PRIVATE_GRP_ID:
54898524Sfenner				print_string((u_char *)ptr, len-6);
54998524Sfenner				break;
55098524Sfenner			case L2TP_AVP_CHALLENGE:
55198524Sfenner			case L2TP_AVP_INI_RECV_LCP:
55298524Sfenner			case L2TP_AVP_LAST_SENT_LCP:
55398524Sfenner			case L2TP_AVP_LAST_RECV_LCP:
55498524Sfenner			case L2TP_AVP_PROXY_AUTH_CHAL:
55598524Sfenner			case L2TP_AVP_PROXY_AUTH_RESP:
55698524Sfenner			case L2TP_AVP_RANDOM_VECTOR:
55798524Sfenner				print_octets((u_char *)ptr, len-6);
55898524Sfenner				break;
55998524Sfenner			case L2TP_AVP_Q931_CC:
56098524Sfenner				l2tp_q931_cc_print((u_char *)ptr, len-6);
56198524Sfenner				break;
56298524Sfenner			case L2TP_AVP_CHALLENGE_RESP:
56398524Sfenner				print_octets((u_char *)ptr, 16);
56498524Sfenner				break;
56598524Sfenner			case L2TP_AVP_CALL_SER_NUM:
56698524Sfenner			case L2TP_AVP_MINIMUM_BPS:
56798524Sfenner			case L2TP_AVP_MAXIMUM_BPS:
56898524Sfenner			case L2TP_AVP_TX_CONN_SPEED:
56998524Sfenner			case L2TP_AVP_PHY_CHANNEL_ID:
57098524Sfenner			case L2TP_AVP_RX_CONN_SPEED:
57198524Sfenner				print_32bits_val((u_int32_t *)ptr);
57298524Sfenner				break;
57398524Sfenner			case L2TP_AVP_BEARER_TYPE:
57498524Sfenner				l2tp_bearer_type_print((u_char *)ptr);
57598524Sfenner				break;
57698524Sfenner			case L2TP_AVP_FRAMING_TYPE:
57798524Sfenner				l2tp_framing_type_print((u_char *)ptr);
57898524Sfenner				break;
57998524Sfenner			case L2TP_AVP_PACKET_PROC_DELAY:
58098524Sfenner				l2tp_packet_proc_delay_print();
58198524Sfenner				break;
58298524Sfenner			case L2TP_AVP_PROXY_AUTH_TYPE:
58398524Sfenner				l2tp_proxy_auth_type_print((u_char *)ptr);
58498524Sfenner				break;
58598524Sfenner			case L2TP_AVP_PROXY_AUTH_ID:
58698524Sfenner				l2tp_proxy_auth_id_print((u_char *)ptr);
58798524Sfenner				break;
58898524Sfenner			case L2TP_AVP_CALL_ERRORS:
58998524Sfenner				l2tp_call_errors_print((u_char *)ptr);
59098524Sfenner				break;
59198524Sfenner			case L2TP_AVP_ACCM:
59298524Sfenner				l2tp_accm_print((u_char *)ptr);
59398524Sfenner				break;
59498524Sfenner			case L2TP_AVP_SEQ_REQUIRED:
59598524Sfenner				break;	/* No Attribute Value */
59698524Sfenner			case L2TP_AVP_PPP_DISCON_CC:
59798524Sfenner				l2tp_ppp_discon_cc_print((u_char *)ptr, len-6);
59898524Sfenner				break;
59998524Sfenner			default:
60098524Sfenner				break;
60156893Sfenner			}
60256893Sfenner		}
60398524Sfenner		printf(")");
60498524Sfenner	}
60556893Sfenner
60698524Sfenner	l2tp_avp_print(dat+len, length-len);
60798524Sfenner	return;
60898524Sfenner
60998524Sfenner trunc:
61098524Sfenner	printf("|...");
61156893Sfenner}
61256893Sfenner
61356893Sfenner
61456893Sfennervoid
61556893Sfennerl2tp_print(const u_char *dat, u_int length)
61656893Sfenner{
61798524Sfenner	const u_int16_t *ptr = (u_int16_t *)dat;
61856893Sfenner	u_int cnt = 0;			/* total octets consumed */
61998524Sfenner	u_int16_t pad;
620147899Ssam	int flag_t, flag_l, flag_s, flag_o;
62198524Sfenner	u_int16_t l2tp_len;
62256893Sfenner
623147899Ssam	flag_t = flag_l = flag_s = flag_o = FALSE;
62456893Sfenner
62598524Sfenner	TCHECK(*ptr);	/* Flags & Version */
626111726Sfenner	if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
62756893Sfenner		printf(" l2tp:");
628111726Sfenner	} else if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
62956893Sfenner		printf(" l2f:");
63056893Sfenner		return;		/* nothing to do */
63156893Sfenner	} else {
63256893Sfenner		printf(" Unknown Version, neither L2F(1) nor L2TP(2)");
63356893Sfenner		return;		/* nothing we can do */
63456893Sfenner	}
63556893Sfenner
63656893Sfenner	printf("[");
637111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_TYPE) {
63856893Sfenner		flag_t = TRUE;
63956893Sfenner		printf("T");
64056893Sfenner	}
641111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_LENGTH) {
64256893Sfenner		flag_l = TRUE;
64356893Sfenner		printf("L");
64456893Sfenner	}
645111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_SEQUENCE) {
64656893Sfenner		flag_s = TRUE;
64756893Sfenner		printf("S");
64856893Sfenner	}
649111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_OFFSET) {
65056893Sfenner		flag_o = TRUE;
65156893Sfenner		printf("O");
65256893Sfenner	}
653147899Ssam	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_PRIORITY)
65456893Sfenner		printf("P");
65556893Sfenner	printf("]");
65656893Sfenner
65756893Sfenner	ptr++;
65856893Sfenner	cnt += 2;
659127668Sbms
66056893Sfenner	if (flag_l) {
66198524Sfenner		TCHECK(*ptr);	/* Length */
662111726Sfenner		l2tp_len = EXTRACT_16BITS(ptr); ptr++;
66356893Sfenner		cnt += 2;
66456893Sfenner	} else {
66556893Sfenner		l2tp_len = 0;
66656893Sfenner	}
66756893Sfenner
66898524Sfenner	TCHECK(*ptr);		/* Tunnel ID */
669111726Sfenner	printf("(%u/", EXTRACT_16BITS(ptr)); ptr++;
67098524Sfenner	cnt += 2;
67198524Sfenner	TCHECK(*ptr);		/* Session ID */
672111726Sfenner	printf("%u)",  EXTRACT_16BITS(ptr)); ptr++;
67398524Sfenner	cnt += 2;
67456893Sfenner
67556893Sfenner	if (flag_s) {
67698524Sfenner		TCHECK(*ptr);	/* Ns */
677111726Sfenner		printf("Ns=%u,", EXTRACT_16BITS(ptr)); ptr++;
67898524Sfenner		cnt += 2;
67998524Sfenner		TCHECK(*ptr);	/* Nr */
680111726Sfenner		printf("Nr=%u",  EXTRACT_16BITS(ptr)); ptr++;
68198524Sfenner		cnt += 2;
68256893Sfenner	}
68356893Sfenner
68456893Sfenner	if (flag_o) {
68598524Sfenner		TCHECK(*ptr);	/* Offset Size */
686111726Sfenner		pad =  EXTRACT_16BITS(ptr); ptr++;
68756893Sfenner		ptr += pad / sizeof(*ptr);
68856893Sfenner		cnt += (2 + pad);
68956893Sfenner	}
69056893Sfenner
691147899Ssam	if (flag_l) {
692147899Ssam		if (length < l2tp_len) {
693147899Ssam			printf(" Length %u larger than packet", l2tp_len);
694147899Ssam			return;
695147899Ssam		}
696147899Ssam		length = l2tp_len;
697147899Ssam	}
698147899Ssam	if (length < cnt) {
699147899Ssam		printf(" Length %u smaller than header length", length);
700147899Ssam		return;
701147899Ssam	}
70256893Sfenner	if (flag_t) {
703147899Ssam		if (!flag_l) {
704147899Ssam			printf(" No length");
705147899Ssam			return;
706147899Ssam		}
70756893Sfenner		if (length - cnt == 0) {
70856893Sfenner			printf(" ZLB");
70956893Sfenner		} else {
71056893Sfenner			l2tp_avp_print((u_char *)ptr, length - cnt);
71156893Sfenner		}
71256893Sfenner	} else {
71356893Sfenner		printf(" {");
71475115Sfenner		ppp_print((u_char *)ptr, length - cnt);
71556893Sfenner		printf("}");
71656893Sfenner	}
71798524Sfenner
71898524Sfenner	return;
71998524Sfenner
72098524Sfenner trunc:
72198524Sfenner	printf("%s", tstr);
722127668Sbms}
723