*/
-#ifndef lint
-static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.7 2000-07-01 03:48:44 assar Exp $";
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "l2tp.h"
-#include "interface.h"
-
-static char tstr[] = " [|l2tp]";
-
-#ifndef TRUE
-#define TRUE 1
-#endif
+/* \summary: Layer Two Tunneling Protocol (L2TP) printer */
+
+/* specification: RFC 2661 */
+
+#include <config.h>
+
+#include "netdissect-stdinc.h"
+
+#define ND_LONGJMP_FROM_TCHECK
+#include "netdissect.h"
+#include "extract.h"
+
+#define L2TP_FLAG_TYPE 0x8000 /* Type (0=Data, 1=Control) */
+#define L2TP_FLAG_LENGTH 0x4000 /* Length */
+#define L2TP_FLAG_SEQUENCE 0x0800 /* Sequence */
+#define L2TP_FLAG_OFFSET 0x0200 /* Offset */
+#define L2TP_FLAG_PRIORITY 0x0100 /* Priority */
+
+#define L2TP_VERSION_MASK 0x000f /* Version Mask */
+#define L2TP_VERSION_L2F 0x0001 /* L2F */
+#define L2TP_VERSION_L2TP 0x0002 /* L2TP */
+
+#define L2TP_AVP_HDR_FLAG_MANDATORY 0x8000 /* Mandatory Flag */
+#define L2TP_AVP_HDR_FLAG_HIDDEN 0x4000 /* Hidden Flag */
+#define L2TP_AVP_HDR_LEN_MASK 0x03ff /* Length Mask */
+
+#define L2TP_FRAMING_CAP_SYNC_MASK 0x00000001 /* Synchronous */
+#define L2TP_FRAMING_CAP_ASYNC_MASK 0x00000002 /* Asynchronous */
+
+#define L2TP_FRAMING_TYPE_SYNC_MASK 0x00000001 /* Synchronous */
+#define L2TP_FRAMING_TYPE_ASYNC_MASK 0x00000002 /* Asynchronous */
+
+#define L2TP_BEARER_CAP_DIGITAL_MASK 0x00000001 /* Digital */
+#define L2TP_BEARER_CAP_ANALOG_MASK 0x00000002 /* Analog */
+
+#define L2TP_BEARER_TYPE_DIGITAL_MASK 0x00000001 /* Digital */
+#define L2TP_BEARER_TYPE_ANALOG_MASK 0x00000002 /* Analog */
+
+/* Authen Type */
+#define L2TP_AUTHEN_TYPE_RESERVED 0x0000 /* Reserved */
+#define L2TP_AUTHEN_TYPE_TEXTUAL 0x0001 /* Textual username/password exchange */
+#define L2TP_AUTHEN_TYPE_CHAP 0x0002 /* PPP CHAP */
+#define L2TP_AUTHEN_TYPE_PAP 0x0003 /* PPP PAP */
+#define L2TP_AUTHEN_TYPE_NO_AUTH 0x0004 /* No Authentication */
+#define L2TP_AUTHEN_TYPE_MSCHAPv1 0x0005 /* MSCHAPv1 */
+
+#define L2TP_PROXY_AUTH_ID_MASK 0x00ff
+
+
+#define L2TP_MSGTYPE_SCCRQ 1 /* Start-Control-Connection-Request */
+#define L2TP_MSGTYPE_SCCRP 2 /* Start-Control-Connection-Reply */
+#define L2TP_MSGTYPE_SCCCN 3 /* Start-Control-Connection-Connected */
+#define L2TP_MSGTYPE_STOPCCN 4 /* Stop-Control-Connection-Notification */
+#define L2TP_MSGTYPE_HELLO 6 /* Hello */
+#define L2TP_MSGTYPE_OCRQ 7 /* Outgoing-Call-Request */
+#define L2TP_MSGTYPE_OCRP 8 /* Outgoing-Call-Reply */
+#define L2TP_MSGTYPE_OCCN 9 /* Outgoing-Call-Connected */
+#define L2TP_MSGTYPE_ICRQ 10 /* Incoming-Call-Request */
+#define L2TP_MSGTYPE_ICRP 11 /* Incoming-Call-Reply */
+#define L2TP_MSGTYPE_ICCN 12 /* Incoming-Call-Connected */
+#define L2TP_MSGTYPE_CDN 14 /* Call-Disconnect-Notify */
+#define L2TP_MSGTYPE_WEN 15 /* WAN-Error-Notify */
+#define L2TP_MSGTYPE_SLI 16 /* Set-Link-Info */
+
+static const struct tok l2tp_msgtype2str[] = {
+ { L2TP_MSGTYPE_SCCRQ, "SCCRQ" },
+ { L2TP_MSGTYPE_SCCRP, "SCCRP" },
+ { L2TP_MSGTYPE_SCCCN, "SCCCN" },
+ { L2TP_MSGTYPE_STOPCCN, "StopCCN" },
+ { L2TP_MSGTYPE_HELLO, "HELLO" },
+ { L2TP_MSGTYPE_OCRQ, "OCRQ" },
+ { L2TP_MSGTYPE_OCRP, "OCRP" },
+ { L2TP_MSGTYPE_OCCN, "OCCN" },
+ { L2TP_MSGTYPE_ICRQ, "ICRQ" },
+ { L2TP_MSGTYPE_ICRP, "ICRP" },
+ { L2TP_MSGTYPE_ICCN, "ICCN" },
+ { L2TP_MSGTYPE_CDN, "CDN" },
+ { L2TP_MSGTYPE_WEN, "WEN" },
+ { L2TP_MSGTYPE_SLI, "SLI" },
+ { 0, NULL }
+};
-#ifndef FALSE
-#define FALSE 0
-#endif
+#define L2TP_AVP_MSGTYPE 0 /* Message Type */
+#define L2TP_AVP_RESULT_CODE 1 /* Result Code */
+#define L2TP_AVP_PROTO_VER 2 /* Protocol Version */
+#define L2TP_AVP_FRAMING_CAP 3 /* Framing Capabilities */
+#define L2TP_AVP_BEARER_CAP 4 /* Bearer Capabilities */
+#define L2TP_AVP_TIE_BREAKER 5 /* Tie Breaker */
+#define L2TP_AVP_FIRM_VER 6 /* Firmware Revision */
+#define L2TP_AVP_HOST_NAME 7 /* Host Name */
+#define L2TP_AVP_VENDOR_NAME 8 /* Vendor Name */
+#define L2TP_AVP_ASSND_TUN_ID 9 /* Assigned Tunnel ID */
+#define L2TP_AVP_RECV_WIN_SIZE 10 /* Receive Window Size */
+#define L2TP_AVP_CHALLENGE 11 /* Challenge */
+#define L2TP_AVP_Q931_CC 12 /* Q.931 Cause Code */
+#define L2TP_AVP_CHALLENGE_RESP 13 /* Challenge Response */
+#define L2TP_AVP_ASSND_SESS_ID 14 /* Assigned Session ID */
+#define L2TP_AVP_CALL_SER_NUM 15 /* Call Serial Number */
+#define L2TP_AVP_MINIMUM_BPS 16 /* Minimum BPS */
+#define L2TP_AVP_MAXIMUM_BPS 17 /* Maximum BPS */
+#define L2TP_AVP_BEARER_TYPE 18 /* Bearer Type */
+#define L2TP_AVP_FRAMING_TYPE 19 /* Framing Type */
+#define L2TP_AVP_PACKET_PROC_DELAY 20 /* Packet Processing Delay (OBSOLETE) */
+#define L2TP_AVP_CALLED_NUMBER 21 /* Called Number */
+#define L2TP_AVP_CALLING_NUMBER 22 /* Calling Number */
+#define L2TP_AVP_SUB_ADDRESS 23 /* Sub-Address */
+#define L2TP_AVP_TX_CONN_SPEED 24 /* (Tx) Connect Speed */
+#define L2TP_AVP_PHY_CHANNEL_ID 25 /* Physical Channel ID */
+#define L2TP_AVP_INI_RECV_LCP 26 /* Initial Received LCP CONFREQ */
+#define L2TP_AVP_LAST_SENT_LCP 27 /* Last Sent LCP CONFREQ */
+#define L2TP_AVP_LAST_RECV_LCP 28 /* Last Received LCP CONFREQ */
+#define L2TP_AVP_PROXY_AUTH_TYPE 29 /* Proxy Authen Type */
+#define L2TP_AVP_PROXY_AUTH_NAME 30 /* Proxy Authen Name */
+#define L2TP_AVP_PROXY_AUTH_CHAL 31 /* Proxy Authen Challenge */
+#define L2TP_AVP_PROXY_AUTH_ID 32 /* Proxy Authen ID */
+#define L2TP_AVP_PROXY_AUTH_RESP 33 /* Proxy Authen Response */
+#define L2TP_AVP_CALL_ERRORS 34 /* Call Errors */
+#define L2TP_AVP_ACCM 35 /* ACCM */
+#define L2TP_AVP_RANDOM_VECTOR 36 /* Random Vector */
+#define L2TP_AVP_PRIVATE_GRP_ID 37 /* Private Group ID */
+#define L2TP_AVP_RX_CONN_SPEED 38 /* (Rx) Connect Speed */
+#define L2TP_AVP_SEQ_REQUIRED 39 /* Sequencing Required */
+#define L2TP_AVP_PPP_DISCON_CC 46 /* PPP Disconnect Cause Code - RFC 3145 */
+
+static const struct tok l2tp_avp2str[] = {
+ { L2TP_AVP_MSGTYPE, "MSGTYPE" },
+ { L2TP_AVP_RESULT_CODE, "RESULT_CODE" },
+ { L2TP_AVP_PROTO_VER, "PROTO_VER" },
+ { L2TP_AVP_FRAMING_CAP, "FRAMING_CAP" },
+ { L2TP_AVP_BEARER_CAP, "BEARER_CAP" },
+ { L2TP_AVP_TIE_BREAKER, "TIE_BREAKER" },
+ { L2TP_AVP_FIRM_VER, "FIRM_VER" },
+ { L2TP_AVP_HOST_NAME, "HOST_NAME" },
+ { L2TP_AVP_VENDOR_NAME, "VENDOR_NAME" },
+ { L2TP_AVP_ASSND_TUN_ID, "ASSND_TUN_ID" },
+ { L2TP_AVP_RECV_WIN_SIZE, "RECV_WIN_SIZE" },
+ { L2TP_AVP_CHALLENGE, "CHALLENGE" },
+ { L2TP_AVP_Q931_CC, "Q931_CC", },
+ { L2TP_AVP_CHALLENGE_RESP, "CHALLENGE_RESP" },
+ { L2TP_AVP_ASSND_SESS_ID, "ASSND_SESS_ID" },
+ { L2TP_AVP_CALL_SER_NUM, "CALL_SER_NUM" },
+ { L2TP_AVP_MINIMUM_BPS, "MINIMUM_BPS" },
+ { L2TP_AVP_MAXIMUM_BPS, "MAXIMUM_BPS" },
+ { L2TP_AVP_BEARER_TYPE, "BEARER_TYPE" },
+ { L2TP_AVP_FRAMING_TYPE, "FRAMING_TYPE" },
+ { L2TP_AVP_PACKET_PROC_DELAY, "PACKET_PROC_DELAY" },
+ { L2TP_AVP_CALLED_NUMBER, "CALLED_NUMBER" },
+ { L2TP_AVP_CALLING_NUMBER, "CALLING_NUMBER" },
+ { L2TP_AVP_SUB_ADDRESS, "SUB_ADDRESS" },
+ { L2TP_AVP_TX_CONN_SPEED, "TX_CONN_SPEED" },
+ { L2TP_AVP_PHY_CHANNEL_ID, "PHY_CHANNEL_ID" },
+ { L2TP_AVP_INI_RECV_LCP, "INI_RECV_LCP" },
+ { L2TP_AVP_LAST_SENT_LCP, "LAST_SENT_LCP" },
+ { L2TP_AVP_LAST_RECV_LCP, "LAST_RECV_LCP" },
+ { L2TP_AVP_PROXY_AUTH_TYPE, "PROXY_AUTH_TYPE" },
+ { L2TP_AVP_PROXY_AUTH_NAME, "PROXY_AUTH_NAME" },
+ { L2TP_AVP_PROXY_AUTH_CHAL, "PROXY_AUTH_CHAL" },
+ { L2TP_AVP_PROXY_AUTH_ID, "PROXY_AUTH_ID" },
+ { L2TP_AVP_PROXY_AUTH_RESP, "PROXY_AUTH_RESP" },
+ { L2TP_AVP_CALL_ERRORS, "CALL_ERRORS" },
+ { L2TP_AVP_ACCM, "ACCM" },
+ { L2TP_AVP_RANDOM_VECTOR, "RANDOM_VECTOR" },
+ { L2TP_AVP_PRIVATE_GRP_ID, "PRIVATE_GRP_ID" },
+ { L2TP_AVP_RX_CONN_SPEED, "RX_CONN_SPEED" },
+ { L2TP_AVP_SEQ_REQUIRED, "SEQ_REQUIRED" },
+ { L2TP_AVP_PPP_DISCON_CC, "PPP_DISCON_CC" },
+ { 0, NULL }
+};
-static char *l2tp_message_type_string[] = {
- "RESERVED_0", /* 0 Reserved */
- "SCCRQ", /* 1 Start-Control-Connection-Request */
- "SCCRP", /* 2 Start-Control-Connection-Reply */
- "SCCCN", /* 3 Start-Control-Connection-Connected */
- "StopCCN", /* 4 Stop-Control-Connection-Notification */
- "RESERVED_5", /* 5 Reserved */
- "HELLO", /* 6 Hello */
- "OCRQ", /* 7 Outgoing-Call-Request */
- "OCRP", /* 8 Outgoing-Call-Reply */
- "OCCN", /* 9 Outgoing-Call-Connected */
- "ICRQ", /* 10 Incoming-Call-Request */
- "ICRP", /* 11 Incoming-Call-Reply */
- "ICCN", /* 12 Incoming-Call-Connected */
- "RESERVED_13", /* 13 Reserved */
- "CDN", /* 14 Call-Disconnect-Notify */
- "WEN", /* 15 WAN-Error-Notify */
- "SLI" /* 16 Set-Link-Info */
-#define L2TP_MAX_MSGTYPE_INDEX 17
+static const struct tok l2tp_authentype2str[] = {
+ { L2TP_AUTHEN_TYPE_RESERVED, "Reserved" },
+ { L2TP_AUTHEN_TYPE_TEXTUAL, "Textual" },
+ { L2TP_AUTHEN_TYPE_CHAP, "CHAP" },
+ { L2TP_AUTHEN_TYPE_PAP, "PAP" },
+ { L2TP_AUTHEN_TYPE_NO_AUTH, "No Auth" },
+ { L2TP_AUTHEN_TYPE_MSCHAPv1, "MS-CHAPv1" },
+ { 0, NULL }
};
-static void l2tp_msgtype_print(const u_char *dat, u_int length);
-static void l2tp_result_code_print(const u_char *dat, u_int length);
-static void l2tp_proto_ver_print(const u_char *dat, u_int length);
-static void l2tp_framing_cap_print(const u_char *dat, u_int length);
-static void l2tp_bearer_cap_print(const u_char *dat, u_int length);
-static void l2tp_tie_breaker_print(const u_char *dat, u_int length);
-static void l2tp_firm_ver_print(const u_char *dat, u_int length);
-static void l2tp_host_name_print(const u_char *dat, u_int length);
-static void l2tp_vendor_name_print(const u_char *dat, u_int length);
-static void l2tp_assnd_tun_id_print(const u_char *dat, u_int length);
-static void l2tp_recv_win_size_print(const u_char *dat, u_int length);
-static void l2tp_challenge_print(const u_char *dat, u_int length);
-static void l2tp_q931_cc_print(const u_char *dat, u_int length);
-static void l2tp_challenge_resp_print(const u_char *dat, u_int length);
-static void l2tp_assnd_sess_id_print(const u_char *dat, u_int length);
-static void l2tp_call_ser_num_print(const u_char *dat, u_int length);
-static void l2tp_minimum_bps_print(const u_char *dat, u_int length);
-static void l2tp_maximum_bps_print(const u_char *dat, u_int length);
-static void l2tp_bearer_type_print(const u_char *dat, u_int length);
-static void l2tp_framing_type_print(const u_char *dat, u_int length);
-static void l2tp_packet_proc_delay_print(const u_char *dat, u_int length);
-static void l2tp_called_number_print(const u_char *dat, u_int length);
-static void l2tp_calling_number_print(const u_char *dat, u_int length);
-static void l2tp_sub_address_print(const u_char *dat, u_int length);
-static void l2tp_tx_conn_speed_print(const u_char *dat, u_int length);
-static void l2tp_phy_channel_id_print(const u_char *dat, u_int length);
-static void l2tp_ini_recv_lcp_print(const u_char *dat, u_int length);
-static void l2tp_last_sent_lcp_print(const u_char *dat, u_int length);
-static void l2tp_last_recv_lcp_print(const u_char *dat, u_int length);
-static void l2tp_proxy_auth_type_print(const u_char *dat, u_int length);
-static void l2tp_proxy_auth_name_print(const u_char *dat, u_int length);
-static void l2tp_proxy_auth_chal_print(const u_char *dat, u_int length);
-static void l2tp_proxy_auth_id_print(const u_char *dat, u_int length);
-static void l2tp_proxy_auth_resp_print(const u_char *dat, u_int length);
-static void l2tp_call_errors_print(const u_char *dat, u_int length);
-static void l2tp_accm_print(const u_char *dat, u_int length);
-static void l2tp_random_vector_print(const u_char *dat, u_int length);
-static void l2tp_private_grp_id_print(const u_char *dat, u_int length);
-static void l2tp_rx_conn_speed_print(const u_char *dat, u_int length);
-static void l2tp_seq_required_print(const u_char *dat, u_int length);
-static void l2tp_avp_print(const u_char *dat, u_int length);
-
-static struct l2tp_avp_vec l2tp_avp[] = {
- {"MSGTYPE", l2tp_msgtype_print}, /* 0 Message Type */
- {"RESULT_CODE", l2tp_result_code_print}, /* 1 Result Code */
- {"PROTO_VER", l2tp_proto_ver_print}, /* 2 Protocol Version */
- {"FRAMING_CAP", l2tp_framing_cap_print}, /* 3 Framing Capabilities */
- {"BEARER_CAP", l2tp_bearer_cap_print}, /* 4 Bearer Capabilities */
- {"TIE_BREAKER", l2tp_tie_breaker_print}, /* 5 Tie Breaker */
- {"FIRM_VER", l2tp_firm_ver_print}, /* 6 Firmware Revision */
- {"HOST_NAME", l2tp_host_name_print}, /* 7 Host Name */
- {"VENDOR_NAME", l2tp_vendor_name_print}, /* 8 Vendor Name */
- {"ASSND_TUN_ID", l2tp_assnd_tun_id_print}, /* 9 Assigned Tunnel ID */
- {"RECV_WIN_SIZE", l2tp_recv_win_size_print}, /* 10 Receive Window Size */
- {"CHALLENGE", l2tp_challenge_print}, /* 11 Challenge */
- {"Q931_CC", l2tp_q931_cc_print}, /* 12 Q.931 Cause Code */
- {"CHALLENGE_RESP", l2tp_challenge_resp_print},/* 13 Challenge Response */
- {"ASSND_SESS_ID", l2tp_assnd_sess_id_print}, /* 14 Assigned Session ID */
- {"CALL_SER_NUM", l2tp_call_ser_num_print}, /* 15 Call Serial Number */
- {"MINIMUM_BPS", l2tp_minimum_bps_print},/* 16 Minimum BPS */
- {"MAXIMUM_BPS", l2tp_maximum_bps_print}, /* 17 Maximum BPS */
- {"BEARER_TYPE", l2tp_bearer_type_print},/* 18 Bearer Type */
- {"FRAMING_TYPE", l2tp_framing_type_print}, /* 19 Framing Type */
- {"PACKET_PROC_DELAY", l2tp_packet_proc_delay_print}, /* 20 Packet Processing Delay (OBSOLETE) */
- {"CALLED_NUMBER", l2tp_called_number_print}, /* 21 Called Number */
- {"CALLING_NUMBER", l2tp_calling_number_print},/* 22 Calling Number */
- {"SUB_ADDRESS", l2tp_sub_address_print},/* 23 Sub-Address */
- {"TX_CONN_SPEED", l2tp_tx_conn_speed_print}, /* 24 (Tx) Connect Speed */
- {"PHY_CHANNEL_ID", l2tp_phy_channel_id_print},/* 25 Physical Channel ID */
- {"INI_RECV_LCP", l2tp_ini_recv_lcp_print}, /* 26 Initial Received LCP CONFREQ */
- {"LAST_SENT_LCP", l2tp_last_sent_lcp_print}, /* 27 Last Sent LCP CONFREQ */
- {"LAST_RECV_LCP", l2tp_last_recv_lcp_print}, /* 28 Last Received LCP CONFREQ */
- {"PROXY_AUTH_TYPE", l2tp_proxy_auth_type_print},/* 29 Proxy Authen Type */
- {"PROXY_AUTH_NAME", l2tp_proxy_auth_name_print},/* 30 Proxy Authen Name */
- {"PROXY_AUTH_CHAL", l2tp_proxy_auth_chal_print},/* 31 Proxy Authen Challenge */
- {"PROXY_AUTH_ID", l2tp_proxy_auth_id_print}, /* 32 Proxy Authen ID */
- {"PROXY_AUTH_RESP", l2tp_proxy_auth_resp_print},/* 33 Proxy Authen Response */
- {"CALL_ERRORS", l2tp_call_errors_print}, /* 34 Call Errors */
- {"ACCM", l2tp_accm_print}, /* 35 ACCM */
- {"RANDOM_VECTOR", l2tp_random_vector_print}, /* 36 Random Vector */
- {"PRIVATE_GRP_ID", l2tp_private_grp_id_print},/* 37 Private Group ID */
- {"RX_CONN_SPEED", l2tp_rx_conn_speed_print}, /* 38 (Rx) Connect Speed */
- {"SEQ_REQUIRED", l2tp_seq_required_print}, /* 39 Sequencing Required */
-#define L2TP_MAX_AVP_INDEX 40
+#define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL 0
+#define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER 1
+#define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL 2
+
+static const struct tok l2tp_cc_direction2str[] = {
+ { L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL, "global error" },
+ { L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER, "at peer" },
+ { L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
+ { 0, NULL }
};
#if 0
"Call disconnected due to loss of carrier",
"Call disconnected for the reason indicated in error code",
"Call disconnected for administrative reasons",
- "Call failed due to lack of appropriate facilities being " \
+ "Call failed due to lack of appropriate facilities being "
"available (temporary condition)",
- "Call failed due to lack of appropriate facilities being " \
+ "Call failed due to lack of appropriate facilities being "
"available (permanent condition)",
"Invalid destination",
"Call failed due to no carrier detected",
"No general error",
"No control connection exists yet for this LAC-LNS pair",
"Length is wrong",
- "One of the field values was out of range or " \
+ "One of the field values was out of range or "
"reserved field was non-zero"
"Insufficient resources to handle this operation now",
"The Session ID is invalid in this context",
/******************************/
/* generic print out routines */
/******************************/
-static void
-print_string(const u_char *dat, u_int length)
-{
- int i;
- for (i=0; i<length; i++) {
- printf("%c", *dat++);
- }
-}
-
-static void
-print_octets(const u_char *dat, u_int length)
+static void
+print_octets(netdissect_options *ndo, const u_char *dat, u_int length)
{
- int i;
+ u_int i;
for (i=0; i<length; i++) {
- printf("%02x", *dat++);
+ ND_PRINT("%02x", GET_U_1(dat));
+ dat++;
}
}
static void
-print_short(const u_short *dat)
+print_16bits_val(netdissect_options *ndo, const uint8_t *dat)
{
- printf("%u", ntohs(*dat));
+ ND_PRINT("%u", GET_BE_U_2(dat));
}
static void
-print_int(const u_int *dat)
+print_32bits_val(netdissect_options *ndo, const uint8_t *dat)
{
- printf("%lu", (u_long)ntohl(*dat));
+ ND_PRINT("%u", GET_BE_U_4(dat));
}
-/**********************************/
-/* AVP-specific print out routines*/
-/**********************************/
+/***********************************/
+/* AVP-specific print out routines */
+/***********************************/
static void
-l2tp_msgtype_print(const u_char *dat, u_int length)
+l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- u_short *ptr = (u_short *)dat;
-
- if (ntohs(*ptr) < L2TP_MAX_MSGTYPE_INDEX) {
- printf("%s", l2tp_message_type_string[ntohs(*ptr)]);
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
}
+ ND_PRINT("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
+ GET_BE_U_2(dat)));
}
static void
-l2tp_result_code_print(const u_char *dat, u_int length)
+l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- /* we just print out the result and error code number */
- u_short *ptr = (u_short *)dat;
-
- if (length == 2) { /* result code */
- printf("%u", ntohs(*ptr));
- } else if (length == 4) { /* result & error code */
- printf("%u/%u", ntohs(*ptr), ntohs(*(ptr+1)));
- } else if (length > 4) { /* result & error code & msg */
- printf("%u/%u ", ntohs(*ptr), ntohs(*(ptr+1)));
- print_string((u_char *)(ptr+2), length - 4);
+ /* Result Code */
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
}
-}
+ ND_PRINT("%u", GET_BE_U_2(dat));
+ dat += 2;
+ length -= 2;
-static void
-l2tp_proto_ver_print(const u_char *dat, u_int length)
-{
- printf("%d.%d", *dat, *(dat+1));
-}
+ /* Error Code (opt) */
+ if (length == 0)
+ return;
+ if (length < 2) {
+ ND_PRINT(" AVP too short");
+ return;
+ }
+ ND_PRINT("/%u", GET_BE_U_2(dat));
+ dat += 2;
+ length -= 2;
+ /* Error Message (opt) */
+ if (length == 0)
+ return;
+ ND_PRINT(" ");
+ nd_printjn(ndo, dat, length);
+}
static void
-l2tp_framing_cap_print(const u_char *dat, u_int length)
+l2tp_proto_ver_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- u_int *ptr = (u_int *)dat;
-
- if (ntohl(*ptr) & L2TP_FRAMING_CAP_ASYNC_MASK) {
- printf("A");
- }
- if (ntohl(*ptr) & L2TP_FRAMING_CAP_SYNC_MASK) {
- printf("S");
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
}
+ ND_PRINT("%u.%u", (GET_BE_U_2(dat) >> 8),
+ (GET_BE_U_2(dat) & 0xff));
}
static void
-l2tp_bearer_cap_print(const u_char *dat, u_int length)
+l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- u_int *ptr = (u_int *)dat;
-
- if (ntohl(*ptr) & L2TP_BEARER_CAP_ANALOG_MASK) {
- printf("A");
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
}
- if (ntohl(*ptr) & L2TP_BEARER_CAP_DIGITAL_MASK) {
- printf("D");
+ if (GET_BE_U_4(dat) & L2TP_FRAMING_CAP_ASYNC_MASK) {
+ ND_PRINT("A");
+ }
+ if (GET_BE_U_4(dat) & L2TP_FRAMING_CAP_SYNC_MASK) {
+ ND_PRINT("S");
}
}
static void
-l2tp_tie_breaker_print(const u_char *dat, u_int length)
-{
- print_octets(dat, 8); /* Tie Break Value is 64bits long */
-}
-
-static void
-l2tp_firm_ver_print(const u_char *dat, u_int length)
-{
- print_short((u_short *)dat);
-}
-
-static void
-l2tp_host_name_print(const u_char *dat, u_int length)
-{
- print_string(dat, length);
-}
-
-static void
-l2tp_vendor_name_print(const u_char *dat, u_int length)
-{
- print_string(dat, length);
-}
-
-static void
-l2tp_assnd_tun_id_print(const u_char *dat, u_int length)
-{
- print_short((u_short *)dat);
-}
-
-static void
-l2tp_recv_win_size_print(const u_char *dat, u_int length)
-{
- print_short((u_short *)dat);
-}
-
-static void
-l2tp_challenge_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
-}
-
-static void
-l2tp_q931_cc_print(const u_char *dat, u_int length)
-{
- print_short((u_short *)dat);
- printf(", %02x", dat[2]);
- if (length > 3) {
- printf(" ");
- print_string(dat+3, length-3);
- }
-}
-
-static void
-l2tp_challenge_resp_print(const u_char *dat, u_int length)
-{
- print_octets(dat, 16); /* XXX length should be 16? */
-}
-
-static void
-l2tp_assnd_sess_id_print(const u_char *dat, u_int length)
-{
- print_short((u_short *)dat);
-}
-
-static void
-l2tp_call_ser_num_print(const u_char *dat, u_int length)
-{
- print_int((u_int *)dat);
-}
-
-static void
-l2tp_minimum_bps_print(const u_char *dat, u_int length)
+l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- print_int((u_int *)dat);
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ if (GET_BE_U_4(dat) & L2TP_BEARER_CAP_ANALOG_MASK) {
+ ND_PRINT("A");
+ }
+ if (GET_BE_U_4(dat) & L2TP_BEARER_CAP_DIGITAL_MASK) {
+ ND_PRINT("D");
+ }
}
static void
-l2tp_maximum_bps_print(const u_char *dat, u_int length)
+l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- print_int((u_int *)dat);
+ if (length < 3) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ print_16bits_val(ndo, dat);
+ ND_PRINT(", %02x", GET_U_1(dat + 2));
+ dat += 3;
+ length -= 3;
+ if (length != 0) {
+ ND_PRINT(" ");
+ nd_printjn(ndo, dat, length);
+ }
}
static void
-l2tp_bearer_type_print(const u_char *dat, u_int length)
+l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- u_int *ptr = (u_int *)dat;
-
- if (ntohl(*ptr) & L2TP_BEARER_TYPE_ANALOG_MASK) {
- printf("A");
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ if (GET_BE_U_4(dat) & L2TP_BEARER_TYPE_ANALOG_MASK) {
+ ND_PRINT("A");
}
- if (ntohl(*ptr) & L2TP_BEARER_TYPE_DIGITAL_MASK) {
- printf("D");
+ if (GET_BE_U_4(dat) & L2TP_BEARER_TYPE_DIGITAL_MASK) {
+ ND_PRINT("D");
}
}
static void
-l2tp_framing_type_print(const u_char *dat, u_int length)
+l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- u_int *ptr = (u_int *)dat;
-
- if (ntohl(*ptr) & L2TP_FRAMING_TYPE_ASYNC_MASK) {
- printf("A");
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ if (GET_BE_U_4(dat) & L2TP_FRAMING_TYPE_ASYNC_MASK) {
+ ND_PRINT("A");
}
- if (ntohl(*ptr) & L2TP_FRAMING_TYPE_SYNC_MASK) {
- printf("S");
+ if (GET_BE_U_4(dat) & L2TP_FRAMING_TYPE_SYNC_MASK) {
+ ND_PRINT("S");
}
}
static void
-l2tp_packet_proc_delay_print(const u_char *dat, u_int length)
+l2tp_packet_proc_delay_print(netdissect_options *ndo)
{
- printf("obsolete");
+ ND_PRINT("obsolete");
}
static void
-l2tp_called_number_print(const u_char *dat, u_int length)
+l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- print_string(dat, length);
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ ND_PRINT("%s", tok2str(l2tp_authentype2str,
+ "AuthType-#%u", GET_BE_U_2(dat)));
}
static void
-l2tp_calling_number_print(const u_char *dat, u_int length)
+l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- print_string(dat, length);
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ ND_PRINT("%u", GET_BE_U_2(dat) & L2TP_PROXY_AUTH_ID_MASK);
}
static void
-l2tp_sub_address_print(const u_char *dat, u_int length)
+l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- print_string(dat, length);
-}
+ uint32_t val;
-static void
-l2tp_tx_conn_speed_print(const u_char *dat, u_int length)
-{
- print_int((u_int *)dat);
-}
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ dat += 2; /* skip "Reserved" */
+ length -= 2;
-static void
-l2tp_phy_channel_id_print(const u_char *dat, u_int length)
-{
- print_int((u_int *)dat);
-}
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("CRCErr=%u ", val);
-static void
-l2tp_ini_recv_lcp_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
-}
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("FrameErr=%u ", val);
-static void
-l2tp_last_sent_lcp_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
-}
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("HardOver=%u ", val);
-static void
-l2tp_last_recv_lcp_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
-}
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("BufOver=%u ", val);
-static void
-l2tp_proxy_auth_type_print(const u_char *dat, u_int length)
-{
- u_short *ptr = (u_short *)dat;
-
- switch (ntohs(*ptr)) {
- case L2TP_AUTHEN_TYPE_RESERVED:
- printf("Reserved");
- break;
- case L2TP_AUTHEN_TYPE_TEXTUAL:
- printf("Textual");
- break;
- case L2TP_AUTHEN_TYPE_CHAP:
- printf("CHAP");
- break;
- case L2TP_AUTHEN_TYPE_PAP:
- printf("PAP");
- break;
- case L2TP_AUTHEN_TYPE_NO_AUTH:
- printf("No Auth");
- break;
- case L2TP_AUTHEN_TYPE_MSCHAP:
- printf("MS-CHAP");
- break;
- default:
- printf("unknown");
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
}
-}
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("Timeout=%u ", val);
-static void
-l2tp_proxy_auth_name_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("AlignErr=%u ", val);
}
static void
-l2tp_proxy_auth_chal_print(const u_char *dat, u_int length)
+l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- print_octets(dat, length);
-}
+ uint32_t val;
-static void
-l2tp_proxy_auth_id_print(const u_char *dat, u_int length)
-{
- u_short *ptr = (u_short *)dat;
+ if (length < 2) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ dat += 2; /* skip "Reserved" */
+ length -= 2;
- printf("%u", ntohs(*ptr) & L2TP_PROXY_AUTH_ID_MASK);
-}
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("send=%08x ", val);
-static void
-l2tp_proxy_auth_resp_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
+ if (length < 4) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ val = GET_BE_U_4(dat); dat += 4; length -= 4;
+ ND_PRINT("recv=%08x ", val);
}
static void
-l2tp_call_errors_print(const u_char *dat, u_int length)
+l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- struct l2tp_call_errors *ptr = (struct l2tp_call_errors *)dat;
-
- printf("CRCErr=%d FrameErr=%d HardOver=%d BufOver=%d ",
- ptr->crc_errs,
- ptr->framing_errs,
- ptr->hardware_overruns,
- ptr->buffer_overruns);
- printf("Timeout=%d AlingErr=%d",
- ptr->timeout_errs,
- ptr->alignment_errs);
+ if (length < 5) {
+ ND_PRINT("AVP too short");
+ return;
+ }
+ /* Disconnect Code */
+ ND_PRINT("%04x, ", GET_BE_U_2(dat));
+ dat += 2;
+ length -= 2;
+ /* Control Protocol Number */
+ ND_PRINT("%04x ", GET_BE_U_2(dat));
+ dat += 2;
+ length -= 2;
+ /* Direction */
+ ND_PRINT("%s", tok2str(l2tp_cc_direction2str,
+ "Direction-#%u", GET_U_1(dat)));
+ dat++;
+ length--;
+
+ if (length != 0) {
+ ND_PRINT(" ");
+ nd_printjn(ndo, (const u_char *)dat, length);
+ }
}
-static void
-l2tp_accm_print(const u_char *dat, u_int length)
+static u_int
+l2tp_avp_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- struct l2tp_accm *ptr = (struct l2tp_accm *)dat;
-
- printf("send=%x recv=%x", ptr->send_accm, ptr->recv_accm);
-}
+ u_int len;
+ uint16_t attr_type;
+ int hidden = FALSE;
-static void
-l2tp_random_vector_print(const u_char *dat, u_int length)
-{
- print_octets(dat, length);
-}
+ ND_PRINT(" ");
+ /* Flags & Length */
+ len = GET_BE_U_2(dat) & L2TP_AVP_HDR_LEN_MASK;
-static void
-l2tp_private_grp_id_print(const u_char *dat, u_int length)
-{
- print_string(dat, length);
- /* XXX print_octets is more appropriate?? */
-}
+ /* If it is not long enough to contain the header, we'll give up. */
+ ND_ICHECKMSG_U("AVP length", len, <, 6);
-static void
-l2tp_rx_conn_speed_print(const u_char *dat, u_int length)
-{
- print_int((u_int *)dat);
-}
+ /* If it goes past the end of the remaining length of the packet,
+ we'll give up. */
+ if (len > length) {
+ ND_PRINT(" (len > %u)", length);
+ goto invalid;
+ }
-static void
-l2tp_seq_required_print(const u_char *dat, u_int length)
-{
- return;
-}
+ /* If it goes past the end of the remaining length of the captured
+ data, we'll give up. */
+ ND_TCHECK_LEN(dat, len);
-static void
-l2tp_avp_print(const u_char *dat, u_int length)
-{
- u_int len;
- const u_short *ptr = (u_short *)dat;
- int hidden = FALSE;
+ /*
+ * After this point, we don't need to check whether we go past
+ * the length of the captured data; however, we *do* need to
+ * check whether we go past the end of the AVP.
+ */
- printf(" ");
- if (length > 0 && (snapend - dat) >= 2) {
- /* there must be at least two octets for the length
- to be decoded */
- if ((len = (ntohs(*ptr) & L2TP_AVP_HDR_LEN_MASK)) <=
- (snapend - dat)) {
- if (ntohs(*ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) {
- printf("*");
- }
- if (ntohs(*ptr) & L2TP_AVP_HDR_FLAG_HIDDEN) {
- hidden = TRUE;
- printf("?");
- }
- } else {
- printf("|...");
- return;
- }
- ptr++;
-
- if (ntohs(*ptr)) {
- /* Vendor Specific Attribute */
- printf("VENDOR%04x:", ntohs(*ptr));
- ptr++;
- printf("ATTR%04x", ntohs(*ptr));
- printf("(");
- print_octets((u_char *)ptr+2, len-6);
- printf(")");
+ if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_MANDATORY) {
+ ND_PRINT("*");
+ }
+ if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_HIDDEN) {
+ hidden = TRUE;
+ ND_PRINT("?");
+ }
+ dat += 2;
+
+ if (GET_BE_U_2(dat)) {
+ /* Vendor Specific Attribute */
+ ND_PRINT("VENDOR%04x:", GET_BE_U_2(dat)); dat += 2;
+ ND_PRINT("ATTR%04x", GET_BE_U_2(dat)); dat += 2;
+ ND_PRINT("(");
+ print_octets(ndo, dat, len-6);
+ ND_PRINT(")");
+ } else {
+ /* IETF-defined Attributes */
+ dat += 2;
+ attr_type = GET_BE_U_2(dat); dat += 2;
+ ND_PRINT("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
+ ND_PRINT("(");
+ if (hidden) {
+ ND_PRINT("???");
} else {
- /* IETF-defined Attribute */
- ptr++;
- if (ntohs(*ptr) < L2TP_MAX_AVP_INDEX) {
- printf("%s", l2tp_avp[ntohs(*ptr)].name);
- printf("(");
- if (!hidden) {
- (l2tp_avp[ntohs(*ptr)].print)
- ((u_char *)ptr+2, len-6);
- } else {
- printf("???");
+ switch (attr_type) {
+ case L2TP_AVP_MSGTYPE:
+ l2tp_msgtype_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_RESULT_CODE:
+ l2tp_result_code_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_PROTO_VER:
+ l2tp_proto_ver_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_FRAMING_CAP:
+ l2tp_framing_cap_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_BEARER_CAP:
+ l2tp_bearer_cap_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_TIE_BREAKER:
+ if (len-6 < 8) {
+ ND_PRINT("AVP too short");
+ break;
+ }
+ print_octets(ndo, dat, 8);
+ break;
+ case L2TP_AVP_FIRM_VER:
+ case L2TP_AVP_ASSND_TUN_ID:
+ case L2TP_AVP_RECV_WIN_SIZE:
+ case L2TP_AVP_ASSND_SESS_ID:
+ if (len-6 < 2) {
+ ND_PRINT("AVP too short");
+ break;
}
- printf(")");
- } else {
- printf(" invalid AVP %u", ntohs(*ptr));
+ print_16bits_val(ndo, dat);
+ break;
+ case L2TP_AVP_HOST_NAME:
+ case L2TP_AVP_VENDOR_NAME:
+ case L2TP_AVP_CALLING_NUMBER:
+ case L2TP_AVP_CALLED_NUMBER:
+ case L2TP_AVP_SUB_ADDRESS:
+ case L2TP_AVP_PROXY_AUTH_NAME:
+ case L2TP_AVP_PRIVATE_GRP_ID:
+ nd_printjn(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_CHALLENGE:
+ case L2TP_AVP_INI_RECV_LCP:
+ case L2TP_AVP_LAST_SENT_LCP:
+ case L2TP_AVP_LAST_RECV_LCP:
+ case L2TP_AVP_PROXY_AUTH_CHAL:
+ case L2TP_AVP_PROXY_AUTH_RESP:
+ case L2TP_AVP_RANDOM_VECTOR:
+ print_octets(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_Q931_CC:
+ l2tp_q931_cc_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_CHALLENGE_RESP:
+ if (len-6 < 16) {
+ ND_PRINT("AVP too short");
+ break;
+ }
+ print_octets(ndo, dat, 16);
+ break;
+ case L2TP_AVP_CALL_SER_NUM:
+ case L2TP_AVP_MINIMUM_BPS:
+ case L2TP_AVP_MAXIMUM_BPS:
+ case L2TP_AVP_TX_CONN_SPEED:
+ case L2TP_AVP_PHY_CHANNEL_ID:
+ case L2TP_AVP_RX_CONN_SPEED:
+ if (len-6 < 4) {
+ ND_PRINT("AVP too short");
+ break;
+ }
+ print_32bits_val(ndo, dat);
+ break;
+ case L2TP_AVP_BEARER_TYPE:
+ l2tp_bearer_type_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_FRAMING_TYPE:
+ l2tp_framing_type_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_PACKET_PROC_DELAY:
+ l2tp_packet_proc_delay_print(ndo);
+ break;
+ case L2TP_AVP_PROXY_AUTH_TYPE:
+ l2tp_proxy_auth_type_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_PROXY_AUTH_ID:
+ l2tp_proxy_auth_id_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_CALL_ERRORS:
+ l2tp_call_errors_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_ACCM:
+ l2tp_accm_print(ndo, dat, len-6);
+ break;
+ case L2TP_AVP_SEQ_REQUIRED:
+ break; /* No Attribute Value */
+ case L2TP_AVP_PPP_DISCON_CC:
+ l2tp_ppp_discon_cc_print(ndo, dat, len-6);
+ break;
+ default:
+ break;
}
}
-
- l2tp_avp_print(dat + len, length - len);
- } else if (length == 0) {
- return;
- } else {
- printf("|...");
+ ND_PRINT(")");
}
+
+ return (len);
+
+invalid:
+ return (0);
}
void
-l2tp_print(const u_char *dat, u_int length)
+l2tp_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
- const u_short *ptr = (u_short *)dat;
+ const u_char *ptr = dat;
u_int cnt = 0; /* total octets consumed */
- u_short pad;
- int flag_t, flag_l, flag_s, flag_o, flag_p;
- u_short l2tp_len;
+ uint16_t pad;
+ int flag_t, flag_l, flag_s, flag_o;
+ uint16_t l2tp_len;
- flag_t = flag_l = flag_s = flag_o = flag_p = FALSE;
-
- if (min(length, snapend - dat) - 6 < 0) {
- /* flag/ver, tunnel_id, session_id must be present for
- this packet to be properly decoded */
- printf("%s", tstr);
- return;
- }
+ ndo->ndo_protocol = "l2tp";
+ flag_t = flag_l = flag_s = flag_o = FALSE;
- if ((ntohs(*ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
- printf(" l2tp:");
- } else if ((ntohs(*ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
- printf(" l2f:");
+ if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
+ ND_PRINT(" l2tp:");
+ } else if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
+ ND_PRINT(" l2f:");
return; /* nothing to do */
} else {
- printf(" Unknown Version, neither L2F(1) nor L2TP(2)");
+ ND_PRINT(" Unknown Version, neither L2F(1) nor L2TP(2)");
return; /* nothing we can do */
}
- printf("[");
- if (ntohs(*ptr) & L2TP_FLAG_TYPE) {
+ ND_PRINT("[");
+ if (GET_BE_U_2(ptr) & L2TP_FLAG_TYPE) {
flag_t = TRUE;
- printf("T");
+ ND_PRINT("T");
}
- if (ntohs(*ptr) & L2TP_FLAG_LENGTH) {
+ if (GET_BE_U_2(ptr) & L2TP_FLAG_LENGTH) {
flag_l = TRUE;
- printf("L");
+ ND_PRINT("L");
}
- if (ntohs(*ptr) & L2TP_FLAG_SEQUENCE) {
+ if (GET_BE_U_2(ptr) & L2TP_FLAG_SEQUENCE) {
flag_s = TRUE;
- printf("S");
+ ND_PRINT("S");
}
- if (ntohs(*ptr) & L2TP_FLAG_OFFSET) {
+ if (GET_BE_U_2(ptr) & L2TP_FLAG_OFFSET) {
flag_o = TRUE;
- printf("O");
+ ND_PRINT("O");
}
- if (ntohs(*ptr) & L2TP_FLAG_PRIORITY) {
- flag_p = TRUE;
- printf("P");
- }
- printf("]");
+ if (GET_BE_U_2(ptr) & L2TP_FLAG_PRIORITY)
+ ND_PRINT("P");
+ ND_PRINT("]");
- ptr++;
+ ptr += 2;
cnt += 2;
-
+
if (flag_l) {
- l2tp_len = ntohs(*ptr++); /* XXX need to consider
- truncation ?? */
+ l2tp_len = GET_BE_U_2(ptr);
+ ptr += 2;
cnt += 2;
} else {
l2tp_len = 0;
}
-
- printf("(%u/", ntohs(*ptr++)); /* Tunnel ID */
- printf("%u)", ntohs(*ptr++)); /* Session ID */
- cnt += 4;
+ /* Tunnel ID */
+ ND_PRINT("(%u/", GET_BE_U_2(ptr));
+ ptr += 2;
+ cnt += 2;
+ /* Session ID */
+ ND_PRINT("%u)", GET_BE_U_2(ptr));
+ ptr += 2;
+ cnt += 2;
if (flag_s) {
- printf("Ns=%u,", ntohs(*ptr++));
- printf("Nr=%u", ntohs(*ptr++));
- cnt += 4;
+ ND_PRINT("Ns=%u,", GET_BE_U_2(ptr));
+ ptr += 2;
+ cnt += 2;
+ ND_PRINT("Nr=%u", GET_BE_U_2(ptr));
+ ptr += 2;
+ cnt += 2;
}
- if (flag_o) {
- pad = ntohs(*ptr++);
- ptr += pad / sizeof(*ptr);
+ if (flag_o) { /* Offset Size */
+ pad = GET_BE_U_2(ptr);
+ /* Offset padding octets in packet buffer? */
+ ND_TCHECK_LEN(ptr + 2, pad);
+ ptr += (2 + pad);
cnt += (2 + pad);
}
+ if (flag_l) {
+ if (length < l2tp_len) {
+ ND_PRINT(" Length %u larger than packet", l2tp_len);
+ goto invalid;
+ }
+ length = l2tp_len;
+ }
+ if (length < cnt) {
+ ND_PRINT(" Length %u smaller than header length", length);
+ goto invalid;
+ }
if (flag_t) {
+ if (!flag_l) {
+ ND_PRINT(" No length");
+ goto invalid;
+ }
if (length - cnt == 0) {
- printf(" ZLB");
+ ND_PRINT(" ZLB");
} else {
- l2tp_avp_print((u_char *)ptr, length - cnt);
+ /*
+ * Print AVPs.
+ */
+ while (length - cnt != 0) {
+ u_int avp_length;
+
+ avp_length = l2tp_avp_print(ndo, ptr, length - cnt);
+ if (avp_length == 0) {
+ goto invalid;
+ }
+ cnt += avp_length;
+ ptr += avp_length;
+ }
}
} else {
-#if 0
- printf(" {");
- ppp_hdlc_print((u_char *)ptr, length - cnt);
- printf("}");
-#else
- printf("[hdlc|]");
-#endif
+ ND_PRINT(" {");
+ ppp_print(ndo, ptr, length - cnt);
+ ND_PRINT("}");
}
-}
+ return;
+invalid:
+ nd_print_invalid(ndo);
+}