diff options
author | Jakob Schlyter <jakob@cvs.openbsd.org> | 2000-01-16 10:54:59 +0000 |
---|---|---|
committer | Jakob Schlyter <jakob@cvs.openbsd.org> | 2000-01-16 10:54:59 +0000 |
commit | e0ad2399cfb10bb4b9903e44ee7db3953cb11eec (patch) | |
tree | 40a3130a4051adb4b7a4d139ddb70e35410ed6e6 /usr.sbin/tcpdump/print-l2tp.c | |
parent | 4f8aa862930674882c18bd874d1e03ef2b683b90 (diff) |
L2TP support (from KAME)
Diffstat (limited to 'usr.sbin/tcpdump/print-l2tp.c')
-rw-r--r-- | usr.sbin/tcpdump/print-l2tp.c | 712 |
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 + } +} |