print-l2tp.c revision 111726
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
2556893Sfennerstatic const char rcsid[] =
26111726Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.10.2.1 2002/05/25 09:47:07 guy Exp $";
2756893Sfenner#endif
2856893Sfenner
2956893Sfenner#ifdef HAVE_CONFIG_H
3056893Sfenner#include "config.h"
3156893Sfenner#endif
3256893Sfenner
3356893Sfenner#include <stdio.h>
3456893Sfenner#include <sys/types.h>
3556893Sfenner#include <sys/param.h>
3656893Sfenner#include <netinet/in.h>
3756893Sfenner#include <arpa/inet.h>
3856893Sfenner
3956893Sfenner#include "l2tp.h"
4056893Sfenner#include "interface.h"
41111726Sfenner#include "extract.h"
4256893Sfenner
4356893Sfennerstatic char tstr[] = " [|l2tp]";
4456893Sfenner
4556893Sfenner#ifndef TRUE
4656893Sfenner#define TRUE 1
4756893Sfenner#endif
4856893Sfenner
4956893Sfenner#ifndef FALSE
5056893Sfenner#define FALSE 0
5156893Sfenner#endif
5256893Sfenner
5398524Sfenner#define	L2TP_MSGTYPE_SCCRQ	1  /* Start-Control-Connection-Request */
5498524Sfenner#define	L2TP_MSGTYPE_SCCRP	2  /* Start-Control-Connection-Reply */
5598524Sfenner#define	L2TP_MSGTYPE_SCCCN	3  /* Start-Control-Connection-Connected */
5698524Sfenner#define	L2TP_MSGTYPE_STOPCCN	4  /* Stop-Control-Connection-Notification */
5798524Sfenner#define	L2TP_MSGTYPE_HELLO	6  /* Hello */
5898524Sfenner#define	L2TP_MSGTYPE_OCRQ	7  /* Outgoing-Call-Request */
5998524Sfenner#define	L2TP_MSGTYPE_OCRP	8  /* Outgoing-Call-Reply */
6098524Sfenner#define	L2TP_MSGTYPE_OCCN	9  /* Outgoing-Call-Connected */
6198524Sfenner#define	L2TP_MSGTYPE_ICRQ	10 /* Incoming-Call-Request */
6298524Sfenner#define	L2TP_MSGTYPE_ICRP	11 /* Incoming-Call-Reply */
6398524Sfenner#define	L2TP_MSGTYPE_ICCN	12 /* Incoming-Call-Connected */
6498524Sfenner#define	L2TP_MSGTYPE_CDN	14 /* Call-Disconnect-Notify */
6598524Sfenner#define	L2TP_MSGTYPE_WEN	15 /* WAN-Error-Notify */
6698524Sfenner#define	L2TP_MSGTYPE_SLI	16 /* Set-Link-Info */
6798524Sfenner
6898524Sfennerstatic struct tok l2tp_msgtype2str[] = {
6998524Sfenner	{ L2TP_MSGTYPE_SCCRQ, 	"SCCRQ" },
7098524Sfenner	{ L2TP_MSGTYPE_SCCRP,	"SCCRP" },
7198524Sfenner	{ L2TP_MSGTYPE_SCCCN,	"SCCCN" },
7298524Sfenner	{ L2TP_MSGTYPE_STOPCCN,	"StopCCN" },
7398524Sfenner	{ L2TP_MSGTYPE_HELLO,	"HELLO" },
7498524Sfenner	{ L2TP_MSGTYPE_OCRQ,	"OCRQ" },
7598524Sfenner	{ L2TP_MSGTYPE_OCRP,	"OCRP" },
7698524Sfenner	{ L2TP_MSGTYPE_OCCN,	"OCCN" },
7798524Sfenner	{ L2TP_MSGTYPE_ICRQ,	"ICRQ" },
7898524Sfenner	{ L2TP_MSGTYPE_ICRP,	"ICRP" },
7998524Sfenner	{ L2TP_MSGTYPE_ICCN,	"ICCN" },
8098524Sfenner	{ L2TP_MSGTYPE_CDN,	"CDN" },
8198524Sfenner	{ L2TP_MSGTYPE_WEN,	"WEN" },
8298524Sfenner	{ L2TP_MSGTYPE_SLI,	"SLI" },
8398524Sfenner	{ 0,			NULL }
8456893Sfenner};
8556893Sfenner
8698524Sfenner#define L2TP_AVP_MSGTYPE		0  /* Message Type */
8798524Sfenner#define L2TP_AVP_RESULT_CODE		1  /* Result Code */
8898524Sfenner#define L2TP_AVP_PROTO_VER		2  /* Protocol Version */
8998524Sfenner#define L2TP_AVP_FRAMING_CAP		3  /* Framing Capabilities */
9098524Sfenner#define L2TP_AVP_BEARER_CAP		4  /* Bearer Capabilities */
9198524Sfenner#define L2TP_AVP_TIE_BREAKER		5  /* Tie Breaker */
9298524Sfenner#define L2TP_AVP_FIRM_VER		6  /* Firmware Revision */
9398524Sfenner#define L2TP_AVP_HOST_NAME		7  /* Host Name */
9498524Sfenner#define L2TP_AVP_VENDOR_NAME		8  /* Vendor Name */
9598524Sfenner#define L2TP_AVP_ASSND_TUN_ID 		9  /* Assigned Tunnel ID */
9698524Sfenner#define L2TP_AVP_RECV_WIN_SIZE		10 /* Receive Window Size */
9798524Sfenner#define L2TP_AVP_CHALLENGE		11 /* Challenge */
9898524Sfenner#define L2TP_AVP_Q931_CC		12 /* Q.931 Cause Code */
9998524Sfenner#define L2TP_AVP_CHALLENGE_RESP		13 /* Challenge Response */
10098524Sfenner#define L2TP_AVP_ASSND_SESS_ID  	14 /* Assigned Session ID */
10198524Sfenner#define L2TP_AVP_CALL_SER_NUM 		15 /* Call Serial Number */
10298524Sfenner#define L2TP_AVP_MINIMUM_BPS		16 /* Minimum BPS */
10398524Sfenner#define L2TP_AVP_MAXIMUM_BPS		17 /* Maximum BPS */
10498524Sfenner#define L2TP_AVP_BEARER_TYPE		18 /* Bearer Type */
10598524Sfenner#define L2TP_AVP_FRAMING_TYPE 		19 /* Framing Type */
10698524Sfenner#define L2TP_AVP_PACKET_PROC_DELAY	20 /* Packet Processing Delay (OBSOLETE) */
10798524Sfenner#define L2TP_AVP_CALLED_NUMBER		21 /* Called Number */
10898524Sfenner#define L2TP_AVP_CALLING_NUMBER		22 /* Calling Number */
10998524Sfenner#define L2TP_AVP_SUB_ADDRESS		23 /* Sub-Address */
11098524Sfenner#define L2TP_AVP_TX_CONN_SPEED		24 /* (Tx) Connect Speed */
11198524Sfenner#define L2TP_AVP_PHY_CHANNEL_ID		25 /* Physical Channel ID */
11298524Sfenner#define L2TP_AVP_INI_RECV_LCP		26 /* Initial Received LCP CONFREQ */
11398524Sfenner#define L2TP_AVP_LAST_SENT_LCP		27 /* Last Sent LCP CONFREQ */
11498524Sfenner#define L2TP_AVP_LAST_RECV_LCP		28 /* Last Received LCP CONFREQ */
11598524Sfenner#define L2TP_AVP_PROXY_AUTH_TYPE	29 /* Proxy Authen Type */
11698524Sfenner#define L2TP_AVP_PROXY_AUTH_NAME	30 /* Proxy Authen Name */
11798524Sfenner#define L2TP_AVP_PROXY_AUTH_CHAL	31 /* Proxy Authen Challenge */
11898524Sfenner#define L2TP_AVP_PROXY_AUTH_ID		32 /* Proxy Authen ID */
11998524Sfenner#define L2TP_AVP_PROXY_AUTH_RESP	33 /* Proxy Authen Response */
12098524Sfenner#define L2TP_AVP_CALL_ERRORS		34 /* Call Errors */
12198524Sfenner#define L2TP_AVP_ACCM			35 /* ACCM */
12298524Sfenner#define L2TP_AVP_RANDOM_VECTOR		36 /* Random Vector */
12398524Sfenner#define L2TP_AVP_PRIVATE_GRP_ID		37 /* Private Group ID */
12498524Sfenner#define L2TP_AVP_RX_CONN_SPEED		38 /* (Rx) Connect Speed */
12598524Sfenner#define L2TP_AVP_SEQ_REQUIRED 		39 /* Sequencing Required */
12698524Sfenner#define L2TP_AVP_PPP_DISCON_CC		46 /* PPP Disconnect Cause Code */
12756893Sfenner
12898524Sfennerstatic struct tok l2tp_avp2str[] = {
12998524Sfenner	{ L2TP_AVP_MSGTYPE,		"MSGTYPE" },
13098524Sfenner	{ L2TP_AVP_RESULT_CODE,		"RESULT_CODE" },
13198524Sfenner	{ L2TP_AVP_PROTO_VER,		"PROTO_VER" },
13298524Sfenner	{ L2TP_AVP_FRAMING_CAP,		"FRAMING_CAP" },
13398524Sfenner	{ L2TP_AVP_BEARER_CAP,		"BEARER_CAP" },
13498524Sfenner	{ L2TP_AVP_TIE_BREAKER,		"TIE_BREAKER" },
13598524Sfenner	{ L2TP_AVP_FIRM_VER,		"FIRM_VER" },
13698524Sfenner	{ L2TP_AVP_HOST_NAME,		"HOST_NAME" },
13798524Sfenner	{ L2TP_AVP_VENDOR_NAME,		"VENDOR_NAME" },
13898524Sfenner	{ L2TP_AVP_ASSND_TUN_ID,	"ASSND_TUN_ID" },
13998524Sfenner	{ L2TP_AVP_RECV_WIN_SIZE,	"RECV_WIN_SIZE" },
14098524Sfenner	{ L2TP_AVP_CHALLENGE,		"CHALLENGE" },
14198524Sfenner	{ L2TP_AVP_Q931_CC,		"Q931_CC", },
14298524Sfenner	{ L2TP_AVP_CHALLENGE_RESP,	"CHALLENGE_RESP" },
14398524Sfenner	{ L2TP_AVP_ASSND_SESS_ID,	"ASSND_SESS_ID" },
14498524Sfenner	{ L2TP_AVP_CALL_SER_NUM,	"CALL_SER_NUM" },
14598524Sfenner	{ L2TP_AVP_MINIMUM_BPS,		"MINIMUM_BPS" },
14698524Sfenner	{ L2TP_AVP_MAXIMUM_BPS,		"MAXIMUM_BPS" },
14798524Sfenner	{ L2TP_AVP_BEARER_TYPE,		"BEARER_TYPE" },
14898524Sfenner	{ L2TP_AVP_FRAMING_TYPE,	"FRAMING_TYPE" },
14998524Sfenner	{ L2TP_AVP_PACKET_PROC_DELAY,	"PACKET_PROC_DELAY" },
15098524Sfenner	{ L2TP_AVP_CALLED_NUMBER,	"CALLED_NUMBER" },
15198524Sfenner	{ L2TP_AVP_CALLING_NUMBER,	"CALLING_NUMBER" },
15298524Sfenner	{ L2TP_AVP_SUB_ADDRESS,		"SUB_ADDRESS" },
15398524Sfenner	{ L2TP_AVP_TX_CONN_SPEED,	"TX_CONN_SPEED" },
15498524Sfenner	{ L2TP_AVP_PHY_CHANNEL_ID,	"PHY_CHANNEL_ID" },
15598524Sfenner	{ L2TP_AVP_INI_RECV_LCP,	"INI_RECV_LCP" },
15698524Sfenner	{ L2TP_AVP_LAST_SENT_LCP,	"LAST_SENT_LCP" },
15798524Sfenner	{ L2TP_AVP_LAST_RECV_LCP,	"LAST_RECV_LCP" },
15898524Sfenner	{ L2TP_AVP_PROXY_AUTH_TYPE,	"PROXY_AUTH_TYPE" },
15998524Sfenner	{ L2TP_AVP_PROXY_AUTH_NAME,	"PROXY_AUTH_NAME" },
16098524Sfenner	{ L2TP_AVP_PROXY_AUTH_CHAL,	"PROXY_AUTH_CHAL" },
16198524Sfenner	{ L2TP_AVP_PROXY_AUTH_ID,	"PROXY_AUTH_ID" },
16298524Sfenner	{ L2TP_AVP_PROXY_AUTH_RESP,	"PROXY_AUTH_RESP" },
16398524Sfenner	{ L2TP_AVP_CALL_ERRORS,		"CALL_ERRORS" },
16498524Sfenner	{ L2TP_AVP_ACCM,		"ACCM" },
16598524Sfenner	{ L2TP_AVP_RANDOM_VECTOR,	"RANDOM_VECTOR" },
16698524Sfenner	{ L2TP_AVP_PRIVATE_GRP_ID,	"PRIVATE_GRP_ID" },
16798524Sfenner	{ L2TP_AVP_RX_CONN_SPEED,	"RX_CONN_SPEED" },
16898524Sfenner	{ L2TP_AVP_SEQ_REQUIRED,	"SEQ_REQUIRED" },
16998524Sfenner	{ L2TP_AVP_PPP_DISCON_CC,	"PPP_DISCON_CC" },
17098524Sfenner	{ 0,				NULL }
17156893Sfenner};
17256893Sfenner
17398524Sfennerstatic struct tok l2tp_authentype2str[] = {
17498524Sfenner	{ L2TP_AUTHEN_TYPE_RESERVED,	"Reserved" },
17598524Sfenner	{ L2TP_AUTHEN_TYPE_TEXTUAL,	"Textual" },
17698524Sfenner	{ L2TP_AUTHEN_TYPE_CHAP,	"CHAP" },
17798524Sfenner	{ L2TP_AUTHEN_TYPE_PAP,		"PAP" },
17898524Sfenner	{ L2TP_AUTHEN_TYPE_NO_AUTH,	"No Auth" },
17998524Sfenner	{ L2TP_AUTHEN_TYPE_MSCHAPv1,	"MS-CHAPv1" },
18098524Sfenner	{ 0,				NULL }
18198524Sfenner};
18298524Sfenner
18398524Sfenner#define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL	0
18498524Sfenner#define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER	1
18598524Sfenner#define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL	2
18698524Sfenner
18798524Sfennerstatic struct tok l2tp_cc_direction2str[] = {
18898524Sfenner	{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL,	"global error" },
18998524Sfenner	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER,	"at peer" },
19098524Sfenner	{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
19198524Sfenner	{ 0,					NULL }
19298524Sfenner};
19398524Sfenner
19456893Sfenner#if 0
19556893Sfennerstatic char *l2tp_result_code_StopCCN[] = {
19656893Sfenner         "Reserved",
19756893Sfenner         "General request to clear control connection",
19856893Sfenner         "General error--Error Code indicates the problem",
19956893Sfenner         "Control channel already exists",
20056893Sfenner         "Requester is not authorized to establish a control channel",
20156893Sfenner         "The protocol version of the requester is not supported",
20256893Sfenner         "Requester is being shut down",
20356893Sfenner         "Finite State Machine error"
20456893Sfenner#define L2TP_MAX_RESULT_CODE_STOPCC_INDEX	8
20556893Sfenner};
20656893Sfenner#endif
20756893Sfenner
20856893Sfenner#if 0
20956893Sfennerstatic char *l2tp_result_code_CDN[] = {
21056893Sfenner	"Reserved",
21156893Sfenner	"Call disconnected due to loss of carrier",
21256893Sfenner	"Call disconnected for the reason indicated in error code",
21356893Sfenner	"Call disconnected for administrative reasons",
21456893Sfenner	"Call failed due to lack of appropriate facilities being " \
21556893Sfenner	"available (temporary condition)",
21656893Sfenner	"Call failed due to lack of appropriate facilities being " \
21756893Sfenner	"available (permanent condition)",
21856893Sfenner	"Invalid destination",
21956893Sfenner	"Call failed due to no carrier detected",
22056893Sfenner	"Call failed due to detection of a busy signal",
22156893Sfenner	"Call failed due to lack of a dial tone",
22256893Sfenner	"Call was not established within time allotted by LAC",
22356893Sfenner	"Call was connected but no appropriate framing was detected"
22456893Sfenner#define L2TP_MAX_RESULT_CODE_CDN_INDEX	12
22556893Sfenner};
22656893Sfenner#endif
22756893Sfenner
22856893Sfenner#if 0
22956893Sfennerstatic char *l2tp_error_code_general[] = {
23056893Sfenner	"No general error",
23156893Sfenner	"No control connection exists yet for this LAC-LNS pair",
23256893Sfenner	"Length is wrong",
23356893Sfenner	"One of the field values was out of range or " \
23456893Sfenner	"reserved field was non-zero"
23556893Sfenner	"Insufficient resources to handle this operation now",
23656893Sfenner	"The Session ID is invalid in this context",
23756893Sfenner	"A generic vendor-specific error occurred in the LAC",
23856893Sfenner	"Try another"
23956893Sfenner#define L2TP_MAX_ERROR_CODE_GENERAL_INDEX	8
24056893Sfenner};
24156893Sfenner#endif
24256893Sfenner
24356893Sfenner/******************************/
24456893Sfenner/* generic print out routines */
24556893Sfenner/******************************/
24656893Sfennerstatic void
24756893Sfennerprint_string(const u_char *dat, u_int length)
24856893Sfenner{
24956893Sfenner	int i;
25056893Sfenner	for (i=0; i<length; i++) {
25156893Sfenner		printf("%c", *dat++);
25256893Sfenner	}
25356893Sfenner}
25456893Sfenner
25556893Sfennerstatic void
25656893Sfennerprint_octets(const u_char *dat, u_int length)
25756893Sfenner{
25856893Sfenner	int i;
25956893Sfenner	for (i=0; i<length; i++) {
26056893Sfenner		printf("%02x", *dat++);
26156893Sfenner	}
26256893Sfenner}
26356893Sfenner
26456893Sfennerstatic void
26598524Sfennerprint_16bits_val(const u_int16_t *dat)
26656893Sfenner{
267111726Sfenner	printf("%u", EXTRACT_16BITS(dat));
26856893Sfenner}
26956893Sfenner
27056893Sfennerstatic void
27198524Sfennerprint_32bits_val(const u_int32_t *dat)
27256893Sfenner{
273111726Sfenner	printf("%lu", (u_long)EXTRACT_32BITS(dat));
27456893Sfenner}
27556893Sfenner
27698524Sfenner/***********************************/
27798524Sfenner/* AVP-specific print out routines */
27898524Sfenner/***********************************/
27956893Sfennerstatic void
28098524Sfennerl2tp_msgtype_print(const u_char *dat)
28156893Sfenner{
28298524Sfenner	u_int16_t *ptr = (u_int16_t*)dat;
28356893Sfenner
284111726Sfenner	printf("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
285111726Sfenner	    EXTRACT_16BITS(ptr)));
28656893Sfenner}
28756893Sfenner
28856893Sfennerstatic void
28956893Sfennerl2tp_result_code_print(const u_char *dat, u_int length)
29056893Sfenner{
29198524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
29256893Sfenner
293111726Sfenner	printf("%u", EXTRACT_16BITS(ptr)); ptr++;	/* Result Code */
294111726Sfenner	if (length > 2) {				/* Error Code (opt) */
295111726Sfenner	        printf("/%u", EXTRACT_16BITS(ptr)); ptr++;
29656893Sfenner	}
297111726Sfenner	if (length > 4) {				/* Error Message (opt) */
29898524Sfenner		printf(" ");
29998524Sfenner		print_string((u_char *)ptr, length - 4);
30098524Sfenner	}
30156893Sfenner}
30256893Sfenner
30356893Sfennerstatic void
30498524Sfennerl2tp_proto_ver_print(const u_int16_t *dat)
30556893Sfenner{
306111726Sfenner	printf("%u.%u", (EXTRACT_16BITS(dat) >> 8),
307111726Sfenner	    (EXTRACT_16BITS(dat) & 0xff));
30856893Sfenner}
30956893Sfenner
31056893Sfennerstatic void
31198524Sfennerl2tp_framing_cap_print(const u_char *dat)
31256893Sfenner{
31398524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
31456893Sfenner
315111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_ASYNC_MASK) {
31656893Sfenner		printf("A");
31756893Sfenner	}
318111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_CAP_SYNC_MASK) {
31956893Sfenner		printf("S");
32056893Sfenner	}
32156893Sfenner}
32256893Sfenner
32356893Sfennerstatic void
32498524Sfennerl2tp_bearer_cap_print(const u_char *dat)
32556893Sfenner{
32698524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
32756893Sfenner
328111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_ANALOG_MASK) {
32956893Sfenner		printf("A");
33056893Sfenner	}
331111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_CAP_DIGITAL_MASK) {
33256893Sfenner		printf("D");
33356893Sfenner	}
33456893Sfenner}
33556893Sfenner
33656893Sfennerstatic void
33756893Sfennerl2tp_q931_cc_print(const u_char *dat, u_int length)
33856893Sfenner{
33998524Sfenner	print_16bits_val((u_int16_t *)dat);
34056893Sfenner	printf(", %02x", dat[2]);
34156893Sfenner	if (length > 3) {
34256893Sfenner		printf(" ");
34356893Sfenner		print_string(dat+3, length-3);
34456893Sfenner	}
34556893Sfenner}
34656893Sfenner
34756893Sfennerstatic void
34898524Sfennerl2tp_bearer_type_print(const u_char *dat)
34956893Sfenner{
35098524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
35156893Sfenner
352111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_ANALOG_MASK) {
35356893Sfenner		printf("A");
35456893Sfenner	}
355111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_BEARER_TYPE_DIGITAL_MASK) {
35656893Sfenner		printf("D");
35756893Sfenner	}
35856893Sfenner}
35956893Sfenner
36056893Sfennerstatic void
36198524Sfennerl2tp_framing_type_print(const u_char *dat)
36256893Sfenner{
36398524Sfenner	u_int32_t *ptr = (u_int32_t *)dat;
36456893Sfenner
365111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_ASYNC_MASK) {
36656893Sfenner		printf("A");
36756893Sfenner	}
368111726Sfenner	if (EXTRACT_32BITS(ptr) &  L2TP_FRAMING_TYPE_SYNC_MASK) {
36956893Sfenner		printf("S");
37056893Sfenner	}
37156893Sfenner}
37256893Sfenner
37356893Sfennerstatic void
37498524Sfennerl2tp_packet_proc_delay_print(void)
37556893Sfenner{
37656893Sfenner	printf("obsolete");
37756893Sfenner}
37856893Sfenner
37956893Sfennerstatic void
38098524Sfennerl2tp_proxy_auth_type_print(const u_char *dat)
38156893Sfenner{
38298524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
38356893Sfenner
38498524Sfenner	printf("%s", tok2str(l2tp_authentype2str,
385111726Sfenner			     "AuthType-#%u", EXTRACT_16BITS(ptr)));
38656893Sfenner}
38756893Sfenner
38856893Sfennerstatic void
38998524Sfennerl2tp_proxy_auth_id_print(const u_char *dat)
39056893Sfenner{
39198524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
39256893Sfenner
393111726Sfenner	printf("%u", EXTRACT_16BITS(ptr) & L2TP_PROXY_AUTH_ID_MASK);
39456893Sfenner}
39556893Sfenner
39656893Sfennerstatic void
39798524Sfennerl2tp_call_errors_print(const u_char *dat)
39856893Sfenner{
39998524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
40098524Sfenner	u_int16_t val_h, val_l;
40198524Sfenner
40298524Sfenner	ptr++;		/* skip "Reserved" */
40356893Sfenner
404111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
405111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
40698524Sfenner	printf("CRCErr=%u ", (val_h<<16) + val_l);
40756893Sfenner
408111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
409111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
41098524Sfenner	printf("FrameErr=%u ", (val_h<<16) + val_l);
41156893Sfenner
412111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
413111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
41498524Sfenner	printf("HardOver=%u ", (val_h<<16) + val_l);
41556893Sfenner
416111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
417111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
41898524Sfenner	printf("BufOver=%u ", (val_h<<16) + val_l);
41956893Sfenner
420111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
421111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
42298524Sfenner	printf("Timeout=%u ", (val_h<<16) + val_l);
42356893Sfenner
424111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
425111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
42698524Sfenner	printf("AlignErr=%u ", (val_h<<16) + val_l);
42756893Sfenner}
42856893Sfenner
42956893Sfennerstatic void
43098524Sfennerl2tp_accm_print(const u_char *dat)
43156893Sfenner{
43298524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
43398524Sfenner	u_int16_t val_h, val_l;
43456893Sfenner
43598524Sfenner	ptr++;		/* skip "Reserved" */
43656893Sfenner
437111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
438111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
43998524Sfenner	printf("send=%08x ", (val_h<<16) + val_l);
44098524Sfenner
441111726Sfenner	val_h = EXTRACT_16BITS(ptr); ptr++;
442111726Sfenner	val_l = EXTRACT_16BITS(ptr); ptr++;
44398524Sfenner	printf("recv=%08x ", (val_h<<16) + val_l);
44456893Sfenner}
44556893Sfenner
44656893Sfennerstatic void
44798524Sfennerl2tp_ppp_discon_cc_print(const u_char *dat, u_int length)
44856893Sfenner{
44998524Sfenner	u_int16_t *ptr = (u_int16_t *)dat;
45098524Sfenner
451111726Sfenner	printf("%04x, ", EXTRACT_16BITS(ptr)); ptr++;	/* Disconnect Code */
452111726Sfenner	printf("%04x ",  EXTRACT_16BITS(ptr)); ptr++;	/* Control Protocol Number */
45398524Sfenner	printf("%s", tok2str(l2tp_cc_direction2str,
45498524Sfenner			     "Direction-#%u", *((u_char *)ptr++)));
45556893Sfenner
45698524Sfenner	if (length > 5) {
45798524Sfenner		printf(" ");
45898524Sfenner		print_string((const u_char *)ptr, length-5);
45998524Sfenner	}
46056893Sfenner}
46156893Sfenner
46256893Sfennerstatic void
46398524Sfennerl2tp_avp_print(const u_char *dat, int length)
46456893Sfenner{
46598524Sfenner	u_int len;
46698524Sfenner	const u_int16_t *ptr = (u_int16_t *)dat;
46798524Sfenner	u_int16_t attr_type;
46898524Sfenner	int hidden = FALSE;
46956893Sfenner
47098524Sfenner	if (length <= 0) {
47198524Sfenner		return;
47298524Sfenner	}
47356893Sfenner
47498524Sfenner	printf(" ");
47556893Sfenner
47698524Sfenner	TCHECK(*ptr);	/* Flags & Length */
477111726Sfenner	len = EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_LEN_MASK;
47856893Sfenner
47998524Sfenner	/* If it is not long enough to decode the entire AVP, we'll
48098524Sfenner	   abandon. */
48198524Sfenner	TCHECK2(*ptr, len);
48298524Sfenner	/* After this point, no need to worry about truncation */
48356893Sfenner
484111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
48598524Sfenner		printf("*");
48698524Sfenner	}
487111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
48898524Sfenner		hidden = TRUE;
48998524Sfenner		printf("?");
49098524Sfenner	}
49198524Sfenner	ptr++;
49256893Sfenner
493111726Sfenner	if (EXTRACT_16BITS(ptr)) {
49498524Sfenner		/* Vendor Specific Attribute */
495111726Sfenner	        printf("VENDOR%04x:", EXTRACT_16BITS(ptr)); ptr++;
496111726Sfenner		printf("ATTR%04x", EXTRACT_16BITS(ptr)); ptr++;
49798524Sfenner		printf("(");
49898524Sfenner		print_octets((u_char *)ptr, len-6);
49998524Sfenner		printf(")");
50098524Sfenner	} else {
50198524Sfenner		/* IETF-defined Attributes */
50256893Sfenner		ptr++;
503111726Sfenner		attr_type = EXTRACT_16BITS(ptr); ptr++;
50498524Sfenner		printf("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
50598524Sfenner		printf("(");
50698524Sfenner		if (hidden) {
50798524Sfenner			printf("???");
50875115Sfenner		} else {
50998524Sfenner			switch (attr_type) {
51098524Sfenner			case L2TP_AVP_MSGTYPE:
51198524Sfenner				l2tp_msgtype_print((u_char *)ptr);
51298524Sfenner				break;
51398524Sfenner			case L2TP_AVP_RESULT_CODE:
51498524Sfenner				l2tp_result_code_print((u_char *)ptr, len-6);
51598524Sfenner				break;
51698524Sfenner			case L2TP_AVP_PROTO_VER:
51798524Sfenner				l2tp_proto_ver_print(ptr);
51898524Sfenner				break;
51998524Sfenner			case L2TP_AVP_FRAMING_CAP:
52098524Sfenner				l2tp_framing_cap_print((u_char *)ptr);
52198524Sfenner				break;
52298524Sfenner			case L2TP_AVP_BEARER_CAP:
52398524Sfenner				l2tp_bearer_cap_print((u_char *)ptr);
52498524Sfenner				break;
52598524Sfenner			case L2TP_AVP_TIE_BREAKER:
52698524Sfenner				print_octets((u_char *)ptr, 8);
52798524Sfenner				break;
52898524Sfenner			case L2TP_AVP_FIRM_VER:
52998524Sfenner			case L2TP_AVP_ASSND_TUN_ID:
53098524Sfenner			case L2TP_AVP_RECV_WIN_SIZE:
53198524Sfenner			case L2TP_AVP_ASSND_SESS_ID:
53298524Sfenner				print_16bits_val(ptr);
53398524Sfenner				break;
53498524Sfenner			case L2TP_AVP_HOST_NAME:
53598524Sfenner			case L2TP_AVP_VENDOR_NAME:
53698524Sfenner			case L2TP_AVP_CALLING_NUMBER:
53798524Sfenner			case L2TP_AVP_CALLED_NUMBER:
53898524Sfenner			case L2TP_AVP_SUB_ADDRESS:
53998524Sfenner			case L2TP_AVP_PROXY_AUTH_NAME:
54098524Sfenner			case L2TP_AVP_PRIVATE_GRP_ID:
54198524Sfenner				print_string((u_char *)ptr, len-6);
54298524Sfenner				break;
54398524Sfenner			case L2TP_AVP_CHALLENGE:
54498524Sfenner			case L2TP_AVP_INI_RECV_LCP:
54598524Sfenner			case L2TP_AVP_LAST_SENT_LCP:
54698524Sfenner			case L2TP_AVP_LAST_RECV_LCP:
54798524Sfenner			case L2TP_AVP_PROXY_AUTH_CHAL:
54898524Sfenner			case L2TP_AVP_PROXY_AUTH_RESP:
54998524Sfenner			case L2TP_AVP_RANDOM_VECTOR:
55098524Sfenner				print_octets((u_char *)ptr, len-6);
55198524Sfenner				break;
55298524Sfenner			case L2TP_AVP_Q931_CC:
55398524Sfenner				l2tp_q931_cc_print((u_char *)ptr, len-6);
55498524Sfenner				break;
55598524Sfenner			case L2TP_AVP_CHALLENGE_RESP:
55698524Sfenner				print_octets((u_char *)ptr, 16);
55798524Sfenner				break;
55898524Sfenner			case L2TP_AVP_CALL_SER_NUM:
55998524Sfenner			case L2TP_AVP_MINIMUM_BPS:
56098524Sfenner			case L2TP_AVP_MAXIMUM_BPS:
56198524Sfenner			case L2TP_AVP_TX_CONN_SPEED:
56298524Sfenner			case L2TP_AVP_PHY_CHANNEL_ID:
56398524Sfenner			case L2TP_AVP_RX_CONN_SPEED:
56498524Sfenner				print_32bits_val((u_int32_t *)ptr);
56598524Sfenner				break;
56698524Sfenner			case L2TP_AVP_BEARER_TYPE:
56798524Sfenner				l2tp_bearer_type_print((u_char *)ptr);
56898524Sfenner				break;
56998524Sfenner			case L2TP_AVP_FRAMING_TYPE:
57098524Sfenner				l2tp_framing_type_print((u_char *)ptr);
57198524Sfenner				break;
57298524Sfenner			case L2TP_AVP_PACKET_PROC_DELAY:
57398524Sfenner				l2tp_packet_proc_delay_print();
57498524Sfenner				break;
57598524Sfenner			case L2TP_AVP_PROXY_AUTH_TYPE:
57698524Sfenner				l2tp_proxy_auth_type_print((u_char *)ptr);
57798524Sfenner				break;
57898524Sfenner			case L2TP_AVP_PROXY_AUTH_ID:
57998524Sfenner				l2tp_proxy_auth_id_print((u_char *)ptr);
58098524Sfenner				break;
58198524Sfenner			case L2TP_AVP_CALL_ERRORS:
58298524Sfenner				l2tp_call_errors_print((u_char *)ptr);
58398524Sfenner				break;
58498524Sfenner			case L2TP_AVP_ACCM:
58598524Sfenner				l2tp_accm_print((u_char *)ptr);
58698524Sfenner				break;
58798524Sfenner			case L2TP_AVP_SEQ_REQUIRED:
58898524Sfenner				break;	/* No Attribute Value */
58998524Sfenner			case L2TP_AVP_PPP_DISCON_CC:
59098524Sfenner				l2tp_ppp_discon_cc_print((u_char *)ptr, len-6);
59198524Sfenner				break;
59298524Sfenner			default:
59398524Sfenner				break;
59456893Sfenner			}
59556893Sfenner		}
59698524Sfenner		printf(")");
59798524Sfenner	}
59856893Sfenner
59998524Sfenner	l2tp_avp_print(dat+len, length-len);
60098524Sfenner	return;
60198524Sfenner
60298524Sfenner trunc:
60398524Sfenner	printf("|...");
60456893Sfenner}
60556893Sfenner
60656893Sfenner
60756893Sfennervoid
60856893Sfennerl2tp_print(const u_char *dat, u_int length)
60956893Sfenner{
61098524Sfenner	const u_int16_t *ptr = (u_int16_t *)dat;
61156893Sfenner	u_int cnt = 0;			/* total octets consumed */
61298524Sfenner	u_int16_t pad;
61356893Sfenner	int flag_t, flag_l, flag_s, flag_o, flag_p;
61498524Sfenner	u_int16_t l2tp_len;
61556893Sfenner
61656893Sfenner	flag_t = flag_l = flag_s = flag_o = flag_p = FALSE;
61756893Sfenner
61898524Sfenner	TCHECK(*ptr);	/* Flags & Version */
619111726Sfenner	if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
62056893Sfenner		printf(" l2tp:");
621111726Sfenner	} else if ((EXTRACT_16BITS(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
62256893Sfenner		printf(" l2f:");
62356893Sfenner		return;		/* nothing to do */
62456893Sfenner	} else {
62556893Sfenner		printf(" Unknown Version, neither L2F(1) nor L2TP(2)");
62656893Sfenner		return;		/* nothing we can do */
62756893Sfenner	}
62856893Sfenner
62956893Sfenner	printf("[");
630111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_TYPE) {
63156893Sfenner		flag_t = TRUE;
63256893Sfenner		printf("T");
63356893Sfenner	}
634111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_LENGTH) {
63556893Sfenner		flag_l = TRUE;
63656893Sfenner		printf("L");
63756893Sfenner	}
638111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_SEQUENCE) {
63956893Sfenner		flag_s = TRUE;
64056893Sfenner		printf("S");
64156893Sfenner	}
642111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_OFFSET) {
64356893Sfenner		flag_o = TRUE;
64456893Sfenner		printf("O");
64556893Sfenner	}
646111726Sfenner	if (EXTRACT_16BITS(ptr) & L2TP_FLAG_PRIORITY) {
64756893Sfenner		flag_p = TRUE;
64856893Sfenner		printf("P");
64956893Sfenner	}
65056893Sfenner	printf("]");
65156893Sfenner
65256893Sfenner	ptr++;
65356893Sfenner	cnt += 2;
65456893Sfenner
65556893Sfenner	if (flag_l) {
65698524Sfenner		TCHECK(*ptr);	/* Length */
657111726Sfenner		l2tp_len = EXTRACT_16BITS(ptr); ptr++;
65856893Sfenner		cnt += 2;
65956893Sfenner	} else {
66056893Sfenner		l2tp_len = 0;
66156893Sfenner	}
66256893Sfenner
66398524Sfenner	TCHECK(*ptr);		/* Tunnel ID */
664111726Sfenner	printf("(%u/", EXTRACT_16BITS(ptr)); ptr++;
66598524Sfenner	cnt += 2;
66698524Sfenner	TCHECK(*ptr);		/* Session ID */
667111726Sfenner	printf("%u)",  EXTRACT_16BITS(ptr)); ptr++;
66898524Sfenner	cnt += 2;
66956893Sfenner
67056893Sfenner	if (flag_s) {
67198524Sfenner		TCHECK(*ptr);	/* Ns */
672111726Sfenner		printf("Ns=%u,", EXTRACT_16BITS(ptr)); ptr++;
67398524Sfenner		cnt += 2;
67498524Sfenner		TCHECK(*ptr);	/* Nr */
675111726Sfenner		printf("Nr=%u",  EXTRACT_16BITS(ptr)); ptr++;
67698524Sfenner		cnt += 2;
67756893Sfenner	}
67856893Sfenner
67956893Sfenner	if (flag_o) {
68098524Sfenner		TCHECK(*ptr);	/* Offset Size */
681111726Sfenner		pad =  EXTRACT_16BITS(ptr); ptr++;
68256893Sfenner		ptr += pad / sizeof(*ptr);
68356893Sfenner		cnt += (2 + pad);
68456893Sfenner	}
68556893Sfenner
68656893Sfenner	if (flag_t) {
68756893Sfenner		if (length - cnt == 0) {
68856893Sfenner			printf(" ZLB");
68956893Sfenner		} else {
69056893Sfenner			l2tp_avp_print((u_char *)ptr, length - cnt);
69156893Sfenner		}
69256893Sfenner	} else {
69356893Sfenner		printf(" {");
69475115Sfenner		ppp_print((u_char *)ptr, length - cnt);
69556893Sfenner		printf("}");
69656893Sfenner	}
69798524Sfenner
69898524Sfenner	return;
69998524Sfenner
70098524Sfenner trunc:
70198524Sfenner	printf("%s", tstr);
70256893Sfenner}
703