summaryrefslogtreecommitdiff
path: root/usr.sbin/tcpdump/print-l2tp.c
diff options
context:
space:
mode:
authorJakob Schlyter <jakob@cvs.openbsd.org>2000-01-16 10:54:59 +0000
committerJakob Schlyter <jakob@cvs.openbsd.org>2000-01-16 10:54:59 +0000
commite0ad2399cfb10bb4b9903e44ee7db3953cb11eec (patch)
tree40a3130a4051adb4b7a4d139ddb70e35410ed6e6 /usr.sbin/tcpdump/print-l2tp.c
parent4f8aa862930674882c18bd874d1e03ef2b683b90 (diff)
L2TP support (from KAME)
Diffstat (limited to 'usr.sbin/tcpdump/print-l2tp.c')
-rw-r--r--usr.sbin/tcpdump/print-l2tp.c712
1 files changed, 712 insertions, 0 deletions
diff --git a/usr.sbin/tcpdump/print-l2tp.c b/usr.sbin/tcpdump/print-l2tp.c
new file mode 100644
index 00000000000..d5d1bde2f3b
--- /dev/null
+++ b/usr.sbin/tcpdump/print-l2tp.c
@@ -0,0 +1,712 @@
+/* $OpenBSD: print-l2tp.c,v 1.1 2000/01/16 10:54:58 jakob Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * L2TP support contributed by Motonori Shindo (mshindo@ascend.co.jp)
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-l2tp.c,v 1.1 2000/01/16 10:54:58 jakob Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+
+#include "l2tp.h"
+#include "interface.h"
+
+static char tstr[] = " [|l2tp]";
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+static u_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 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
+};
+
+#if 0
+static char *l2tp_result_code_StopCCN[] = {
+ "Reserved",
+ "General request to clear control connection",
+ "General error--Error Code indicates the problem",
+ "Control channel already exists",
+ "Requester is not authorized to establish a control channel",
+ "The protocol version of the requester is not supported",
+ "Requester is being shut down",
+ "Finite State Machine error"
+#define L2TP_MAX_RESULT_CODE_STOPCC_INDEX 8
+};
+#endif
+
+#if 0
+static char *l2tp_result_code_CDN[] = {
+ "Reserved",
+ "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 " \
+ "available (temporary condition)",
+ "Call failed due to lack of appropriate facilities being " \
+ "available (permanent condition)",
+ "Invalid destination",
+ "Call failed due to no carrier detected",
+ "Call failed due to detection of a busy signal",
+ "Call failed due to lack of a dial tone",
+ "Call was not established within time allotted by LAC",
+ "Call was connected but no appropriate framing was detected"
+#define L2TP_MAX_RESULT_CODE_CDN_INDEX 12
+};
+#endif
+
+#if 0
+static char *l2tp_error_code_general[] = {
+ "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 " \
+ "reserved field was non-zero"
+ "Insufficient resources to handle this operation now",
+ "The Session ID is invalid in this context",
+ "A generic vendor-specific error occurred in the LAC",
+ "Try another"
+#define L2TP_MAX_ERROR_CODE_GENERAL_INDEX 8
+};
+#endif
+
+/******************************/
+/* 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)
+{
+ int i;
+ for (i=0; i<length; i++) {
+ printf("%02x", *dat++);
+ }
+}
+
+static void
+print_short(const u_short *dat)
+{
+ printf("%u", ntohs(*dat));
+}
+
+static void
+print_int(const u_int *dat)
+{
+ printf("%lu", (u_long)ntohl(*dat));
+}
+
+/**********************************/
+/* AVP-specific print out routines*/
+/**********************************/
+static void
+l2tp_msgtype_print(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)]);
+ }
+}
+
+static void
+l2tp_result_code_print(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("%d", ntohs(*ptr));
+ } else if (length == 4) { /* result & error code */
+ printf("%d/%d", 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);
+ }
+}
+
+static void
+l2tp_proto_ver_print(const u_char *dat, u_int length)
+{
+ printf("%d.%d", *dat, *(dat+1));
+}
+
+
+static void
+l2tp_framing_cap_print(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");
+ }
+}
+
+static void
+l2tp_bearer_cap_print(const u_char *dat, u_int length)
+{
+ u_int *ptr = (u_int *)dat;
+
+ if (ntohl(*ptr) & L2TP_BEARER_CAP_ANALOG_MASK) {
+ printf("A");
+ }
+ if (ntohl(*ptr) & L2TP_BEARER_CAP_DIGITAL_MASK) {
+ printf("D");
+ }
+}
+
+static void
+l2tp_tie_breaker_print(const u_char *dat, u_int length)
+{
+ printf("%lx", *(u_long *)dat); /* XXX */
+}
+
+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);
+ print_short((u_short *)(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)
+{
+ print_int((u_int *)dat);
+}
+
+static void
+l2tp_maximum_bps_print(const u_char *dat, u_int length)
+{
+ print_int((u_int *)dat);
+}
+
+static void
+l2tp_bearer_type_print(const u_char *dat, u_int length)
+{
+ u_int *ptr = (u_int *)dat;
+
+ if (ntohl(*ptr) & L2TP_BEARER_TYPE_ANALOG_MASK) {
+ printf("A");
+ }
+ if (ntohl(*ptr) & L2TP_BEARER_TYPE_DIGITAL_MASK) {
+ printf("D");
+ }
+}
+
+static void
+l2tp_framing_type_print(const u_char *dat, u_int length)
+{
+ u_int *ptr = (u_int *)dat;
+
+ if (ntohl(*ptr) & L2TP_FRAMING_TYPE_ASYNC_MASK) {
+ printf("A");
+ }
+ if (ntohl(*ptr) & L2TP_FRAMING_TYPE_SYNC_MASK) {
+ printf("S");
+ }
+}
+
+static void
+l2tp_packet_proc_delay_print(const u_char *dat, u_int length)
+{
+ printf("obsolete");
+}
+
+static void
+l2tp_called_number_print(const u_char *dat, u_int length)
+{
+ print_string(dat, length);
+}
+
+static void
+l2tp_calling_number_print(const u_char *dat, u_int length)
+{
+ print_string(dat, length);
+}
+
+static void
+l2tp_sub_address_print(const u_char *dat, u_int length)
+{
+ print_string(dat, length);
+}
+
+static void
+l2tp_tx_conn_speed_print(const u_char *dat, u_int length)
+{
+ print_int((u_int *)dat);
+}
+
+static void
+l2tp_phy_channel_id_print(const u_char *dat, u_int length)
+{
+ print_int((u_int *)dat);
+}
+
+static void
+l2tp_ini_recv_lcp_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+static void
+l2tp_last_sent_lcp_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+static void
+l2tp_last_recv_lcp_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+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");
+ }
+}
+
+static void
+l2tp_proxy_auth_name_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+static void
+l2tp_proxy_auth_chal_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+static void
+l2tp_proxy_auth_id_print(const u_char *dat, u_int length)
+{
+ u_short *ptr = (u_short *)dat;
+
+ printf("%d", ntohs(*ptr) & L2TP_PROXY_AUTH_ID_MASK);
+}
+
+static void
+l2tp_proxy_auth_resp_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+static void
+l2tp_call_errors_print(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);
+}
+
+static void
+l2tp_accm_print(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);
+}
+
+static void
+l2tp_random_vector_print(const u_char *dat, u_int length)
+{
+ print_octets(dat, length);
+}
+
+static void
+l2tp_private_grp_id_print(const u_char *dat, u_int length)
+{
+ print_string(dat, length);
+ /* XXX print_octets is more appropriate?? */
+}
+
+static void
+l2tp_rx_conn_speed_print(const u_char *dat, u_int length)
+{
+ print_int((u_int *)dat);
+}
+
+static void
+l2tp_seq_required_print(const u_char *dat, u_int length)
+{
+ return;
+}
+
+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;
+
+ 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)) { /* IETF == 0 */
+ printf("vendor=%04x", ntohs(*ptr));
+ }
+ 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("???");
+ }
+ printf(")");
+ } else {
+ printf(" invalid AVP %u", ntohs(*ptr));
+ }
+
+ l2tp_avp_print(dat + len, length - len);
+ } else if (length == 0) {
+ return;
+ } else {
+ printf("|...");
+ }
+}
+
+
+void
+l2tp_print(const u_char *dat, u_int length)
+{
+ const u_short *ptr = (u_short *)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;
+
+ 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;
+ }
+
+ if ((ntohs(*ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
+ printf(" l2tp:");
+ } else if ((ntohs(*ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
+ printf(" l2f:");
+ return; /* nothing to do */
+ } else {
+ printf(" Unknown Version, neither L2F(1) nor L2TP(2)");
+ return; /* nothing we can do */
+ }
+
+ printf("[");
+ if (ntohs(*ptr) & L2TP_FLAG_TYPE) {
+ flag_t = TRUE;
+ printf("T");
+ }
+ if (ntohs(*ptr) & L2TP_FLAG_LENGTH) {
+ flag_l = TRUE;
+ printf("L");
+ }
+ if (ntohs(*ptr) & L2TP_FLAG_SEQUENCE) {
+ flag_s = TRUE;
+ printf("S");
+ }
+ if (ntohs(*ptr) & L2TP_FLAG_OFFSET) {
+ flag_o = TRUE;
+ printf("O");
+ }
+ if (ntohs(*ptr) & L2TP_FLAG_PRIORITY) {
+ flag_p = TRUE;
+ printf("P");
+ }
+ printf("]");
+
+ ptr++;
+ cnt += 2;
+
+ if (flag_l) {
+ l2tp_len = ntohs(*ptr++); /* XXX need to consider
+ truncation ?? */
+ cnt += 2;
+ } else {
+ l2tp_len = 0;
+ }
+
+ printf("(%d/", ntohs(*ptr++)); /* Tunnel ID */
+ printf("%d)", ntohs(*ptr++)); /* Session ID */
+ cnt += 4;
+
+ if (flag_s) {
+ printf("Ns=%d,", ntohs(*ptr++));
+ printf("Nr=%d", ntohs(*ptr++));
+ cnt += 4;
+ }
+
+ if (flag_o) {
+ pad = ntohs(*ptr++);
+ (u_char *)ptr += pad;
+ cnt += (2 + pad);
+ }
+
+ if (flag_t) {
+ if (length - cnt == 0) {
+ printf(" ZLB");
+ } else {
+ l2tp_avp_print((u_char *)ptr, length - cnt);
+ }
+ } else {
+#if 0
+ printf(" {");
+ ppp_hdlc_print((u_char *)ptr, length - cnt);
+ printf("}");
+#else
+ printf("[hdlc|]");
+#endif
+ }
+}