summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ppp.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-ppp.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-ppp.c')
-rw-r--r--epan/dissectors/packet-ppp.c8348
1 files changed, 8348 insertions, 0 deletions
diff --git a/epan/dissectors/packet-ppp.c b/epan/dissectors/packet-ppp.c
new file mode 100644
index 00000000..ac104d26
--- /dev/null
+++ b/epan/dissectors/packet-ppp.c
@@ -0,0 +1,8348 @@
+/* packet-ppp.c
+ * Routines for ppp packet disassembly
+ * RFC 1661, RFC 1662
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ *
+ * This file created and by Mike Hall <mlh@io.com>
+ * Copyright 1998
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/capture_dissectors.h>
+#include <wsutil/pint.h>
+#include <wsutil/str_util.h>
+#include <epan/prefs.h>
+#include "packet-ppp.h"
+#include <epan/ppptypes.h>
+#include <epan/etypes.h>
+#include <epan/expert.h>
+#include <epan/ip_opts.h>
+#include "packet-chdlc.h"
+#include "packet-ip.h"
+#include "packet-ipx.h"
+#include <epan/nlpid.h>
+#include <epan/crc16-tvb.h>
+#include <epan/crc32-tvb.h>
+#include <epan/ipproto.h>
+#include <epan/addr_resolv.h>
+#include <epan/reassemble.h>
+#include "packet-sll.h"
+#include "packet-juniper.h"
+#include "packet-sflow.h"
+#include "packet-l2tp.h"
+
+void proto_register_ppp_raw_hdlc(void);
+void proto_reg_handoff_ppp_raw_hdlc(void);
+void proto_register_ppp(void);
+void proto_reg_handoff_ppp(void);
+void proto_register_mp(void);
+void proto_reg_handoff_mp(void);
+void proto_register_lcp(void);
+void proto_reg_handoff_lcp(void);
+void proto_register_vsncp(void);
+void proto_reg_handoff_vsncp(void);
+void proto_register_vsnp(void);
+void proto_reg_handoff_vsnp(void);
+void proto_register_ipcp(void);
+void proto_reg_handoff_ipcp(void);
+void proto_register_bcp_bpdu(void);
+void proto_reg_handoff_bcp_bpdu(void);
+void proto_register_bcp_ncp(void);
+void proto_reg_handoff_bcp_ncp(void);
+void proto_register_osinlcp(void);
+void proto_reg_handoff_bcp(void);
+void proto_reg_handoff_osinlcp(void);
+void proto_register_ccp(void);
+void proto_reg_handoff_ccp(void);
+void proto_register_cbcp(void);
+void proto_reg_handoff_cbcp(void);
+void proto_register_bacp(void);
+void proto_reg_handoff_bacp(void);
+void proto_register_bap(void);
+void proto_reg_handoff_bap(void);
+void proto_register_comp_data(void);
+void proto_reg_handoff_comp_data(void);
+void proto_register_pap(void);
+void proto_reg_handoff_pap(void);
+void proto_register_chap(void);
+void proto_reg_handoff_chap(void);
+void proto_register_pppmuxcp(void);
+void proto_reg_handoff_pppmuxcp(void);
+void proto_register_pppmux(void);
+void proto_reg_handoff_pppmux(void);
+void proto_register_mplscp(void);
+void proto_reg_handoff_mplscp(void);
+void proto_register_cdpcp(void);
+void proto_reg_handoff_cdpcp(void);
+void proto_register_ipv6cp(void);
+void proto_reg_handoff_ipv6cp(void);
+void proto_register_iphc_crtp(void);
+void proto_reg_handoff_iphc_crtp(void);
+
+static int proto_ppp = -1;
+static int hf_ppp_direction = -1;
+static int hf_ppp_address = -1;
+static int hf_ppp_control = -1;
+static int hf_ppp_protocol = -1;
+static int hf_ppp_code = -1;
+static int hf_ppp_identifier = -1;
+static int hf_ppp_length = -1;
+static int hf_ppp_magic_number = -1;
+static int hf_ppp_oui = -1;
+static int hf_ppp_kind = -1;
+static int hf_ppp_data = -1;
+static int hf_ppp_fcs_16 = -1;
+static int hf_ppp_fcs_32 = -1;
+static int hf_ppp_fcs_status = -1;
+
+static gint ett_ppp = -1;
+static gint ett_ppp_opt_type = -1;
+static gint ett_ppp_unknown_opt = -1;
+
+static expert_field ei_ppp_opt_len_invalid = EI_INIT;
+static expert_field ei_ppp_fcs = EI_INIT;
+
+static int proto_ppp_hdlc = -1;
+
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_ppp_hdlc_data = -1;
+static int hf_ppp_hdlc_fragment = -1;
+
+static gint ett_ppp_hdlc_data = -1;
+
+static int proto_lcp = -1;
+static int proto_lcp_option_vendor = -1;
+static int proto_lcp_option_mru = -1;
+static int proto_lcp_option_async_map = -1;
+static int proto_lcp_option_authprot = -1;
+static int proto_lcp_option_qualprot = -1;
+static int proto_lcp_option_magicnumber = -1;
+static int proto_lcp_option_linkqualmon = -1;
+static int proto_lcp_option_field_compress = -1;
+static int proto_lcp_option_addr_field_compress = -1;
+static int proto_lcp_option_fcs_alternatives = -1;
+static int proto_lcp_option_self_desc_pad = -1;
+static int proto_lcp_option_numbered_mode = -1;
+static int proto_lcp_option_callback = -1;
+static int proto_lcp_option_compound_frames = -1;
+static int proto_lcp_option_nomdataencap = -1;
+static int proto_lcp_option_multilink_mrru = -1;
+static int proto_lcp_option_multilink_ssnh = -1;
+static int proto_lcp_option_multilink_ep_disc = -1;
+static int proto_lcp_option_dce_identifier = -1;
+static int proto_lcp_option_multilink_pp = -1;
+static int proto_lcp_option_link_discrim = -1;
+static int proto_lcp_option_auth = -1;
+static int proto_lcp_option_cobs = -1;
+static int proto_lcp_option_prefix_elision = -1;
+static int proto_lcp_option_multilink_hdr_fmt = -1;
+static int proto_lcp_option_internationalization = -1;
+static int proto_lcp_option_sonet_sdh = -1;
+
+static gint ett_lcp = -1;
+static gint ett_lcp_options = -1;
+static gint ett_lcp_vendor_opt = -1;
+static gint ett_lcp_mru_opt = -1;
+static gint ett_lcp_asyncmap_opt = -1;
+static gint ett_lcp_authprot_opt = -1;
+static gint ett_lcp_qualprot_opt = -1;
+static gint ett_lcp_magicnumber_opt = -1;
+static gint ett_lcp_linkqualmon_opt = -1;
+static gint ett_lcp_pcomp_opt = -1;
+static gint ett_lcp_acccomp_opt = -1;
+static gint ett_lcp_fcs_alternatives_opt = -1;
+static gint ett_lcp_self_desc_pad_opt = -1;
+static gint ett_lcp_numbered_mode_opt = -1;
+static gint ett_lcp_callback_opt = -1;
+static gint ett_lcp_compound_frames_opt = -1;
+static gint ett_lcp_nomdataencap_opt = -1;
+static gint ett_lcp_multilink_mrru_opt = -1;
+static gint ett_lcp_multilink_ssnh_opt = -1;
+static gint ett_lcp_multilink_ep_disc_opt = -1;
+static gint ett_lcp_magic_block = -1;
+static gint ett_lcp_dce_identifier_opt = -1;
+static gint ett_lcp_multilink_pp_opt = -1;
+static gint ett_lcp_bacp_link_discrim_opt = -1;
+static gint ett_lcp_auth_opt = -1;
+static gint ett_lcp_cobs_opt = -1;
+static gint ett_lcp_prefix_elision_opt = -1;
+static gint ett_multilink_hdr_fmt_opt = -1;
+static gint ett_lcp_internationalization_opt = -1;
+static gint ett_lcp_sonet_sdh_opt = -1;
+
+static dissector_table_t lcp_option_table;
+
+static int proto_ipcp = -1;
+static int proto_ipcp_option_addrs = -1;
+static int proto_ipcp_option_compress = -1;
+static int proto_ipcp_option_addr = -1;
+static int proto_ipcp_option_mobileipv4 = -1;
+static int proto_ipcp_option_pri_dns = -1;
+static int proto_ipcp_option_pri_nbns = -1;
+static int proto_ipcp_option_sec_dns = -1;
+static int proto_ipcp_option_sec_nbns = -1;
+static int proto_ipcp_rohc_option_profiles = -1;
+static int proto_ipcp_iphc_option_rtp_compress = -1;
+static int proto_ipcp_iphc_option_enhanced_rtp_compress = -1;
+static int proto_ipcp_iphc_option_neghdrcomp = -1;
+
+static gint ett_ipcp = -1;
+static gint ett_ipcp_options = -1;
+static gint ett_ipcp_ipaddrs_opt = -1;
+static gint ett_ipcp_compress_opt = -1;
+static gint ett_ipcp_ipaddr_opt = -1;
+static gint ett_ipcp_mobileipv4_opt = -1;
+static gint ett_ipcp_pridns_opt = -1;
+static gint ett_ipcp_secdns_opt = -1;
+static gint ett_ipcp_prinbns_opt = -1;
+static gint ett_ipcp_secnbns_opt = -1;
+
+static gint ett_ipcp_iphc_rtp_compress_opt = -1;
+static gint ett_ipcp_iphc_enhanced_rtp_compress_opt = -1;
+static gint ett_ipcp_iphc_neghdrcomp_opt = -1;
+static gint ett_ipcp_rohc_profiles_opt = -1;
+
+static dissector_table_t ipcp_option_table;
+static dissector_table_t ipcp_rohc_suboption_table;
+static dissector_table_t ipcp_iphc_suboption_table;
+
+static int proto_vsncp = -1;
+static int proto_vsncp_option_pdnid = -1;
+static int proto_vsncp_option_apname = -1;
+static int proto_vsncp_option_pdntype = -1;
+static int proto_vsncp_option_pdnaddress = -1;
+static int proto_vsncp_option_pco = -1;
+static int proto_vsncp_option_errorcode = -1;
+static int proto_vsncp_option_attachtype = -1;
+static int proto_vsncp_option_ipv4address = -1;
+static int proto_vsncp_option_addressalloc = -1;
+static int proto_vsncp_option_apn_ambr = -1;
+static int proto_vsncp_option_ipv6_hsgw_lla_iid = -1;
+
+static int hf_vsncp_opt_type = -1;
+static int hf_vsncp_opt_length = -1;
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_vsncp_protocol_configuration_length = -1;
+static int hf_vsncp_error_code = -1;
+static int hf_vsncp_identifier = -1;
+static int hf_vsncp_attach_type = -1;
+static int hf_vsncp_protocol_configuration_data = -1;
+static int hf_vsncp_default_router_address = -1;
+static int hf_vsncp_pdn_identifier = -1;
+static int hf_vsncp_address_allocation_cause = -1;
+static int hf_vsncp_length = -1;
+static int hf_vsncp_code = -1;
+static int hf_vsncp_protocol = -1;
+static int hf_vsncp_pdn_type = -1;
+static int hf_vsncp_ipv6_interface_identifier = -1;
+static int hf_vsncp_pdn_ipv4 = -1;
+static int hf_vsncp_access_point_name = -1;
+static int hf_vsncp_ambr_data = -1;
+static int hf_vsncp_pdn_ipv6 = -1;
+
+static gint ett_vsncp = -1;
+static gint ett_vsncp_options = -1;
+static gint ett_vsncp_pdnid_opt = -1;
+static gint ett_vsncp_apname_opt = -1;
+static gint ett_vsncp_pdntype_opt = -1;
+static gint ett_vsncp_pdnaddress_opt = -1;
+static gint ett_vsncp_pco_opt = -1;
+static gint ett_vsncp_errorcode_opt = -1;
+static gint ett_vsncp_attachtype_opt = -1;
+static gint ett_vsncp_ipv4address_opt = -1;
+static gint ett_vsncp_addressalloc_opt = -1;
+static gint ett_vsncp_apn_ambr_opt = -1;
+static gint ett_vsncp_ipv6_hsgw_lla_iid_opt = -1;
+
+static dissector_table_t vsncp_option_table;
+
+/*
+* VSNP (RFC3772) has no defined packet structure.
+* The following organisations have defined their own VSNPs,
+* any VSNCPs containing one of the below OUIs will result in the VSNP being parsed accordingly.
+*/
+#define OUI_BBF 0x00256D /* Broadband Forum TR 456 */
+#define OUI_3GPP 0xCF0002 /* 3GPP X.S0057-0 */
+
+static guint32 vsnp_oui = -1;
+static int proto_vsnp = -1;
+
+/* 3GPP Variables */
+static gint hf_vsnp_3gpp_pdnid = -1;
+
+/* BBF Variables */
+/* TO DO */
+
+static gint ett_vsnp =-1;
+
+static int proto_osinlcp = -1;
+static int proto_osinlcp_option_align_npdu = -1;
+
+static gint ett_osinlcp = -1;
+static gint ett_osinlcp_options = -1;
+static gint ett_osinlcp_align_npdu_opt = -1;
+
+static dissector_table_t osinlcp_option_table;
+
+static int proto_bcp_bpdu = -1;
+static int hf_bcp_bpdu_flags = -1;
+static int hf_bcp_bpdu_fcs_present = -1;
+static int hf_bcp_bpdu_zeropad = -1;
+static int hf_bcp_bpdu_bcontrol = -1;
+static int hf_bcp_bpdu_pads = -1;
+static int hf_bcp_bpdu_mac_type = -1;
+static int hf_bcp_bpdu_pad = -1;
+
+static gint ett_bcp_bpdu = -1;
+static gint ett_bcp_bpdu_flags = -1;
+
+static int proto_bcp_ncp = -1;
+static int proto_bcp_ncp_option_bridge_id = -1;
+static int proto_bcp_ncp_option_line_id = -1;
+static int proto_bcp_ncp_option_mac_sup = -1;
+static int proto_bcp_ncp_option_tinygram_comp = -1;
+static int proto_bcp_ncp_option_lan_id = -1;
+static int proto_bcp_ncp_option_mac_addr = -1;
+static int proto_bcp_ncp_option_stp = -1;
+static int proto_bcp_ncp_option_ieee_802_tagged_frame = -1;
+static int proto_bcp_ncp_option_management_inline = -1;
+static int proto_bcp_ncp_option_bcp_ind = -1;
+
+static int hf_bcp_ncp_opt_type = -1;
+static int hf_bcp_ncp_opt_length = -1;
+static int hf_bcp_ncp_lan_seg_no = -1;
+static int hf_bcp_ncp_bridge_no = -1;
+static int hf_bcp_ncp_tinygram_comp = -1;
+static int hf_bcp_ncp_mac = -1;
+static int hf_bcp_ncp_mac_l = -1;
+static int hf_bcp_ncp_mac_m = -1;
+static int hf_bcp_ncp_stp_prot = -1;
+static int hf_bcp_ncp_ieee_802_tagged_frame = -1;
+
+static gint ett_bcp_ncp = -1;
+static gint ett_bcp_ncp_options = -1;
+static gint ett_bcp_ncp_ieee_802_tagged_frame_opt = -1;
+static gint ett_bcp_ncp_management_inline_opt = -1;
+static gint ett_bcp_ncp_bcp_ind_opt = -1;
+static gint ett_bcp_ncp_bridge_id_opt = -1;
+static gint ett_bcp_ncp_line_id_opt = -1;
+static gint ett_bcp_ncp_mac_sup_opt = -1;
+static gint ett_bcp_ncp_tinygram_comp_opt = -1;
+static gint ett_bcp_ncp_lan_id_opt = -1;
+static gint ett_bcp_ncp_mac_addr_opt = -1;
+static gint ett_bcp_ncp_stp_opt = -1;
+
+static dissector_table_t bcp_ncp_option_table;
+
+static int proto_ccp = -1;
+static int proto_ccp_option_oui = -1;
+static int proto_ccp_option_predict1 = -1;
+static int proto_ccp_option_predict2 = -1;
+static int proto_ccp_option_puddle = -1;
+static int proto_ccp_option_hpppc = -1;
+static int proto_ccp_option_stac = -1;
+static int proto_ccp_option_stac_ascend = -1;
+static int proto_ccp_option_mppe = -1;
+static int proto_ccp_option_gfza = -1;
+static int proto_ccp_option_v42bis = -1;
+static int proto_ccp_option_bsdcomp = -1;
+static int proto_ccp_option_lzsdcp = -1;
+static int proto_ccp_option_mvrca = -1;
+static int proto_ccp_option_dce = -1;
+static int proto_ccp_option_deflate = -1;
+static int proto_ccp_option_v44lzjh = -1;
+
+static gint ett_ccp = -1;
+static gint ett_ccp_options = -1;
+static gint ett_ccp_oui_opt = -1;
+static gint ett_ccp_predict1_opt = -1;
+static gint ett_ccp_predict2_opt = -1;
+static gint ett_ccp_puddle_opt = -1;
+static gint ett_ccp_hpppc_opt = -1;
+static gint ett_ccp_stac_opt = -1;
+static gint ett_ccp_stac_opt_check_mode = -1;
+static gint ett_ccp_mppe_opt = -1;
+static gint ett_ccp_mppe_opt_supp_bits = -1;
+static gint ett_ccp_gfza_opt = -1;
+static gint ett_ccp_v42bis_opt = -1;
+static gint ett_ccp_bsdcomp_opt = -1;
+static gint ett_ccp_lzsdcp_opt = -1;
+static gint ett_ccp_mvrca_opt = -1;
+static gint ett_ccp_dce_opt = -1;
+static gint ett_ccp_deflate_opt = -1;
+static gint ett_ccp_v44lzjh_opt = -1;
+
+static dissector_table_t ccp_option_table;
+
+static int proto_cbcp = -1;
+static int proto_cbcp_option_no_callback = -1;
+static int proto_cbcp_option_callback_user = -1;
+static int proto_cbcp_option_callback_admin = -1;
+static int proto_cbcp_option_callback_list = -1;
+
+static int hf_cbcp_opt_type = -1;
+static int hf_cbcp_opt_length = -1;
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_cbcp_address_type = -1;
+static int hf_cbcp_address = -1;
+static int hf_cbcp_callback_delay = -1;
+static int hf_cbcp_no_callback = -1;
+
+static gint ett_cbcp = -1;
+static gint ett_cbcp_options = -1;
+static gint ett_cbcp_callback_opt = -1;
+static gint ett_cbcp_callback_opt_addr = -1;
+static gint ett_cbcp_no_callback = -1;
+static gint ett_cbcp_callback_user = -1;
+static gint ett_cbcp_callback_admin = -1;
+static gint ett_cbcp_callback_list = -1;
+
+static expert_field ei_cbcp_address = EI_INIT;
+
+static dissector_table_t cbcp_option_table;
+
+static int proto_bacp = -1;
+static int proto_bacp_option_favored_peer = -1;
+
+static int hf_bacp_opt_type = -1;
+static int hf_bacp_opt_length = -1;
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_bacp_link_speed = -1;
+static int hf_bacp_magic_number = -1;
+static int hf_bacp_link_type = -1;
+
+static gint ett_bacp = -1;
+static gint ett_bacp_options = -1;
+static gint ett_bacp_favored_peer_opt = -1;
+
+static dissector_table_t bacp_option_table;
+
+static int proto_bap = -1;
+static int proto_bap_option_link_type = -1;
+static int proto_bap_option_phone_delta = -1;
+static int proto_bap_option_no_phone = -1;
+static int proto_bap_option_reason = -1;
+static int proto_bap_option_link_disc = -1;
+static int proto_bap_option_call_status = -1;
+
+static int hf_bap_opt_type = -1;
+static int hf_bap_opt_length = -1;
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_bap_sub_option_length = -1;
+static int hf_bap_call_status = -1;
+static int hf_bap_unknown_option_data = -1;
+static int hf_bap_sub_option_type = -1;
+static int hf_bap_reason = -1;
+static int hf_bap_link_discriminator = -1;
+static int hf_bap_unique_digit = -1;
+static int hf_bap_type = -1;
+static int hf_bap_identifier = -1;
+static int hf_bap_subscriber_number = -1;
+static int hf_bap_phone_number_sub_address = -1;
+static int hf_bap_response_code = -1;
+static int hf_bap_call_action = -1;
+static int hf_bap_length = -1;
+
+static gint ett_bap = -1;
+static gint ett_bap_options = -1;
+static gint ett_bap_link_type_opt = -1;
+static gint ett_bap_phone_delta_opt = -1;
+static gint ett_bap_phone_delta_subopt = -1;
+static gint ett_bap_call_status_opt = -1;
+static gint ett_bap_no_phone_opt = -1;
+static gint ett_bap_reason_opt = -1;
+static gint ett_bap_link_disc_opt = -1;
+
+static expert_field ei_bap_sub_option_length = EI_INIT;
+
+static dissector_table_t bap_option_table;
+
+static dissector_handle_t ppp_hdlc_handle, ppp_handle;
+static dissector_handle_t ppp_raw_hdlc_handle;
+static dissector_handle_t mp_handle;
+static dissector_handle_t lcp_handle;
+static dissector_handle_t vsncp_handle;
+static dissector_handle_t vsnp_handle;
+static dissector_handle_t ipcp_handle;
+static dissector_handle_t bcp_bpdu_handle;
+static dissector_handle_t bcp_ncp_handle;
+static dissector_handle_t osinlcp_handle;
+static dissector_handle_t ccp_handle;
+static dissector_handle_t cbcp_handle;
+static dissector_handle_t bacp_handle;
+static dissector_handle_t bap_handle;
+static dissector_handle_t comp_data_handle;
+static dissector_handle_t pap_handle;
+static dissector_handle_t chap_handle;
+static dissector_handle_t muxcp_handle;
+static dissector_handle_t pppmux_handle;
+static dissector_handle_t mplscp_handle;
+static dissector_handle_t cdpcp_handle;
+static dissector_handle_t ipv6cp_handle;
+static dissector_handle_t fh_handle;
+static dissector_handle_t cudp16_handle;
+static dissector_handle_t cudp8_handle;
+static dissector_handle_t cs_handle;
+static dissector_handle_t cntcp_handle;
+
+
+static int proto_comp_data = -1;
+
+#if 0 /* see dissect_comp_data() */
+static gint ett_comp_data = -1;
+#endif
+static int proto_pppmuxcp = -1;
+static int proto_pppmuxcp_option_def_pid = -1;
+
+static int hf_pppmux_flags_pid = -1;
+static int hf_pppmux_flags_field_length = -1;
+static int hf_pppmuxcp_opt_type = -1;
+static int hf_pppmuxcp_opt_length = -1;
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_pppmux_sub_frame_length = -1;
+static int hf_pppmux_flags = -1;
+static int hf_pppmux_def_prot_id = -1;
+
+static gint ett_pppmuxcp = -1;
+static gint ett_pppmuxcp_options = -1;
+static gint ett_pppmuxcp_def_pid_opt = -1;
+
+static dissector_table_t pppmuxcp_option_table;
+
+static int proto_pppmux = -1;
+static int hf_pppmux_protocol = -1;
+
+static gint ett_pppmux = -1;
+static gint ett_pppmux_subframe = -1;
+static gint ett_pppmux_subframe_hdr = -1;
+static gint ett_pppmux_subframe_flags = -1;
+static gint ett_pppmux_subframe_info = -1;
+
+static reassembly_table mp_reassembly_table;
+
+static int proto_mp = -1;
+static int hf_mp_frag = -1;
+static int hf_mp_frag_short = -1;
+static int hf_mp_frag_first = -1;
+static int hf_mp_frag_last = -1;
+static int hf_mp_sequence_num = -1;
+static int hf_mp_sequence_num_cls = -1;
+static int hf_mp_sequence_num_reserved = -1;
+static int hf_mp_short_sequence_num = -1;
+static int hf_mp_short_sequence_num_cls = -1;
+static int hf_mp_payload = -1;
+static gint hf_mp_fragments = -1;
+static gint hf_mp_fragment = -1;
+static gint hf_mp_fragment_overlap = -1;
+static gint hf_mp_fragment_overlap_conflicts = -1;
+static gint hf_mp_fragment_multiple_tails = -1;
+static gint hf_mp_fragment_too_long_fragment = -1;
+static gint hf_mp_fragment_error = -1;
+static gint hf_mp_fragment_count = -1;
+static gint hf_mp_reassembled_in = -1;
+static gint hf_mp_reassembled_length = -1;
+
+static int ett_mp = -1;
+static int ett_mp_flags = -1;
+static gint ett_mp_fragment = -1;
+static gint ett_mp_fragments = -1;
+
+static const fragment_items mp_frag_items = {
+ /* Fragment subtrees */
+ &ett_mp_fragment,
+ &ett_mp_fragments,
+ /* Fragment fields */
+ &hf_mp_fragments,
+ &hf_mp_fragment,
+ &hf_mp_fragment_overlap,
+ &hf_mp_fragment_overlap_conflicts,
+ &hf_mp_fragment_multiple_tails,
+ &hf_mp_fragment_too_long_fragment,
+ &hf_mp_fragment_error,
+ &hf_mp_fragment_count,
+ /* Reassembled in field */
+ &hf_mp_reassembled_in,
+ /* Reassembled length field */
+ &hf_mp_reassembled_length,
+ /* Reassembled data field */
+ NULL,
+ /* Tag */
+ "Message fragments"
+};
+
+static int proto_mplscp = -1;
+static gint ett_mplscp = -1;
+static gint ett_mplscp_options = -1;
+
+static int proto_cdpcp = -1;
+static gint ett_cdpcp = -1;
+static gint ett_cdpcp_options = -1;
+
+static int proto_pap = -1; /* PAP vars */
+static gint ett_pap = -1;
+static gint ett_pap_data = -1;
+
+static gint hf_pap_code = -1;
+static gint hf_pap_identifier = -1;
+static gint hf_pap_length = -1;
+static gint hf_pap_data = -1;
+static gint hf_pap_peer_id = -1;
+static gint hf_pap_peer_id_length = -1;
+static gint hf_pap_password = -1;
+static gint hf_pap_password_length = -1;
+static gint hf_pap_message = -1;
+static gint hf_pap_message_length = -1;
+static gint hf_pap_stuff = -1;
+
+static int proto_chap = -1; /* CHAP vars */
+static gint ett_chap = -1;
+static gint ett_chap_data = -1;
+
+
+static gint hf_chap_code = -1;
+static gint hf_chap_identifier = -1;
+static gint hf_chap_length = -1;
+static gint hf_chap_data = -1;
+static gint hf_chap_value_size = -1;
+static gint hf_chap_value = -1;
+static gint hf_chap_name = -1;
+static gint hf_chap_message = -1;
+static int hf_chap_stuff = -1;
+
+static int proto_ipv6cp = -1; /* IPv6CP vars */
+static int proto_ipv6cp_option_if_id = -1;
+static int proto_ipv6cp_option_compress = -1;
+
+/* Generated from convert_proto_tree_add_text.pl */
+static int hf_ipv6cp_opt_type = -1;
+static int hf_ipv6cp_opt_length = -1;
+static int hf_ipv6cp_interface_identifier = -1;
+
+static gint ett_ipv6cp = -1;
+static gint ett_ipv6cp_options = -1;
+static gint ett_ipv6cp_if_id_opt = -1;
+static gint ett_ipv6cp_compress_opt = -1;
+
+static dissector_table_t ipv6cp_option_table;
+
+static int proto_iphc_crtp = -1; /* CRTP vars */
+static int proto_iphc_crtp_cudp16 = -1;
+static int proto_iphc_crtp_cudp8 = -1;
+static int proto_iphc_crtp_cs = -1;
+static int proto_iphc_crtp_cntcp = -1;
+
+static int hf_iphc_crtp_cid8 = -1;
+static int hf_iphc_crtp_cid16 = -1;
+static int hf_iphc_crtp_gen = -1;
+static int hf_iphc_crtp_seq = -1;
+static int hf_iphc_crtp_fh_flags = -1;
+static int hf_iphc_crtp_fh_cidlenflag = -1;
+static int hf_iphc_crtp_fh_dataflag = -1;
+static int hf_iphc_crtp_cs_flags = -1;
+static int hf_iphc_crtp_cs_cnt = -1;
+static int hf_iphc_crtp_cs_invalid = -1;
+static int hf_iphc_crtp_ip_id = -1;
+static int hf_iphc_crtp_data = -1;
+
+static gint ett_iphc_crtp = -1;
+static gint ett_iphc_crtp_hdr = -1;
+static gint ett_iphc_crtp_info = -1;
+static gint ett_iphc_crtp_fh_flags = -1;
+
+static expert_field ei_iphc_crtp_ip_version = EI_INIT;
+static expert_field ei_iphc_crtp_next_protocol = EI_INIT;
+static expert_field ei_iphc_crtp_seq_nonzero = EI_INIT;
+
+static dissector_table_t ppp_subdissector_table;
+static dissector_handle_t chdlc_handle;
+static dissector_handle_t eth_withfcs_handle;
+static dissector_handle_t eth_withoutfcs_handle;
+
+static capture_dissector_handle_t chdlc_cap_handle;
+
+static const value_string ppp_direction_vals[] = {
+ {P2P_DIR_RECV, "DCE->DTE"},
+ {P2P_DIR_SENT, "DTE->DCE"},
+ {0, NULL}
+};
+
+/* options */
+static gint ppp_fcs_decode = 0; /* 0 = No FCS, 1 = 16 bit FCS, 2 = 32 bit FCS */
+#define NO_FCS 0
+#define FCS_16 1
+#define FCS_32 2
+
+const enum_val_t fcs_options[] = {
+ {"none", "None", NO_FCS},
+ {"16-bit", "16-Bit", FCS_16},
+ {"32-bit", "32-Bit", FCS_32},
+ {NULL, NULL, -1}
+};
+
+/*
+ * For Default Protocol ID negotiated with PPPMuxCP. We need to
+ * this ID so that if the first subframe doesn't have protocol
+ * ID, we can use it
+ */
+
+static guint pppmux_def_prot_id = 0;
+
+/* PPP definitions */
+
+/*
+ * Used by the GTP dissector as well.
+ * www.iana.org/assignments/ppp-numbers
+ */
+static const value_string ppp_vals[] = {
+ {PPP_PADDING, "Padding Protocol"},
+ {PPP_ROHC_SCID, "ROHC small-CID"},
+ {PPP_ROHC_LCID, "ROHC large-CID"},
+ {PPP_IP, "Internet Protocol version 4"},
+ {PPP_OSI, "OSI Network Layer"},
+ {PPP_XNSIDP, "Xerox NS IDP"},
+ {PPP_DEC4, "DECnet Phase IV"},
+ {PPP_AT, "Appletalk"},
+ {PPP_IPX, "Novell IPX"},
+ {PPP_VJC_COMP, "Van Jacobson Compressed TCP/IP"},
+ {PPP_VJC_UNCOMP, "Van Jacobson Uncompressed TCP/IP"},
+ {PPP_BCP_BPDU, "Bridging PDU"},
+ {PPP_ST, "Stream Protocol (ST-II)"},
+ {PPP_VINES, "Banyan Vines"},
+ {PPP_AT_EDDP, "AppleTalk EDDP"},
+ {PPP_AT_SB, "AppleTalk SmartBuffered"},
+ {PPP_MP, "Multi-Link"},
+ {PPP_NB, "NETBIOS Framing"},
+ {PPP_CISCO, "Cisco Systems"},
+ {PPP_ASCOM, "Ascom Timeplex"},
+ {PPP_LBLB, "Fujitsu Link Backup and Load Balancing (LBLB)"},
+ {PPP_RL, "DCA Remote Lan"},
+ {PPP_SDTP, "Serial Data Transport Protocol (PPP-SDTP)"},
+ {PPP_LLC, "SNA over 802.2"},
+ {PPP_SNA, "SNA"},
+ {PPP_IPV6HC, "IPv6 Header Compression "},
+ {PPP_KNX, "KNX Bridging Data"},
+ {PPP_ENCRYPT, "Encryption"},
+ {PPP_ILE, "Individual Link Encryption"},
+ {PPP_IPV6, "Internet Protocol version 6"},
+ {PPP_MUX, "PPP Muxing"},
+ {PPP_VSNP, "Vendor-Specific Network Protocol (VSNP)"},
+ {PPP_TNP, "TRILL Network Protocol (TNP)"},
+ {PPP_RTP_FH, "RTP IPHC Full Header"},
+ {PPP_RTP_CTCP, "RTP IPHC Compressed TCP"},
+ {PPP_RTP_CNTCP, "RTP IPHC Compressed Non TCP"},
+ {PPP_RTP_CUDP8, "RTP IPHC Compressed UDP 8"},
+ {PPP_RTP_CRTP8, "RTP IPHC Compressed RTP 8"},
+ {PPP_STAMPEDE, "Stampede Bridging"},
+ {PPP_MPPLUS, "MP+ Protocol"},
+ {PPP_NTCITS_IPI, "NTCITS IPI"},
+ {PPP_ML_SLCOMP, "Single link compression in multilink"},
+ {PPP_COMP, "Compressed datagram"},
+ {PPP_STP_HELLO, "802.1d Hello Packets"},
+ {PPP_IBM_SR, "IBM Source Routing BPDU"},
+ {PPP_DEC_LB, "DEC LANBridge100 Spanning Tree"},
+ {PPP_CDP, "Cisco Discovery Protocol"},
+ {PPP_NETCS, "Netcs Twin Routing"},
+ {PPP_STP, "STP - Scheduled Transfer Protocol"},
+ {PPP_EDP, "EDP - Extreme Discovery Protocol"},
+ {PPP_OSCP, "Optical Supervisory Channel Protocol (OSCP)"},
+ {PPP_OSCP2, "Optical Supervisory Channel Protocol (OSCP)"},
+ {PPP_LUXCOM, "Luxcom"},
+ {PPP_SIGMA, "Sigma Network Systems"},
+ {PPP_ACSP, "Apple Client Server Protocol"},
+ {PPP_MPLS_UNI, "MPLS Unicast"},
+ {PPP_MPLS_MULTI, "MPLS Multicast"},
+ {PPP_P12844, "IEEE p1284.4 standard - data packets"},
+ {PPP_TETRA, "ETSI TETRA Network Protocol Type 1"},
+ {PPP_MFTP, "Multichannel Flow Treatment Protocol"},
+ {PPP_RTP_CTCPND, "RTP IPHC Compressed TCP No Delta"},
+ {PPP_RTP_CS, "RTP IPHC Context State"},
+ {PPP_RTP_CUDP16, "RTP IPHC Compressed UDP 16"},
+ {PPP_RTP_CRDP16, "RTP IPHC Compressed RTP 16"},
+ {PPP_CCCP, "Cray Communications Control Protocol"},
+ {PPP_CDPD_MNRP, "CDPD Mobile Network Registration Protocol"},
+ {PPP_EXPANDAP, "Expand accelerator protocol"},
+ {PPP_ODSICP, "ODSICP NCP"},
+ {PPP_DOCSIS, "DOCSIS DLL"},
+ {PPP_CETACEANNDP, "Cetacean Network Detection Protocol"},
+ {PPP_LZS, "Stacker LZS"},
+ {PPP_REFTEK, "RefTek Protocol"},
+ {PPP_FC, "Fibre Channel"},
+ {PPP_EMIT, "EMIT Protocols"},
+ {PPP_VSP, "Vendor-Specific Protocol (VSP)"},
+ {PPP_TLSP, "TRILL Link State Protocol (TLSP)"},
+ {PPP_IPCP, "Internet Protocol Control Protocol"},
+ {PPP_OSINLCP, "OSI Network Layer Control Protocol"},
+ {PPP_XNSIDPCP, "Xerox NS IDP Control Protocol"},
+ {PPP_DECNETCP, "DECnet Phase IV Control Protocol"},
+ {PPP_ATCP, "AppleTalk Control Protocol"},
+ {PPP_IPXCP, "Novell IPX Control Protocol"},
+ {PPP_BCP_NCP, "Bridging NCP"},
+ {PPP_SPCP, "Stream Protocol Control Protocol"},
+ {PPP_BVCP, "Banyan Vines Control Protocol"},
+ {PPP_MLCP, "Multi-Link Control Protocol"},
+ {PPP_NBCP, "NETBIOS Framing Control Protocol"},
+ {PPP_CISCOCP, "Cisco Systems Control Protocol"},
+ {PPP_ASCOMCP, "Ascom Timeplex"},
+ {PPP_LBLBCP, "Fujitsu LBLB Control Protocol"},
+ {PPP_RLNCP, "DCA Remote Lan Network Control Protocol (RLNCP)"},
+ {PPP_SDCP, "Serial Data Control Protocol (PPP-SDCP)"},
+ {PPP_LLCCP, "SNA over 802.2 Control Protocol"},
+ {PPP_SNACP, "SNA Control Protocol"},
+ {PPP_IP6HCCP, "IP6 Header Compression Control Protocol"},
+ {PPP_KNXCP, "KNX Bridging Control Protocol"},
+ {PPP_ECP, "Encryption Control Protocol"},
+ {PPP_ILECP, "Individual Link Encryption Control Protocol"},
+ {PPP_IPV6CP, "IPv6 Control Protocol"},
+ {PPP_MUXCP, "PPP Muxing Control Protocol"},
+ {PPP_VSNCP, "Vendor-Specific Network Control Protocol (VSNCP)"},
+ {PPP_TNCP, "TRILL Network Control Protocol"},
+ {PPP_STAMPEDECP, "Stampede Bridging Control Protocol"},
+ {PPP_MPPCP, "MP+ Control Protocol"},
+ {PPP_IPICP, "NTCITS IPI Control Protocol"},
+ {PPP_SLCC, "Single link compression in multilink control"},
+ {PPP_CCP, "Compression Control Protocol"},
+ {PPP_CDPCP, "Cisco Discovery Protocol Control Protocol"},
+ {PPP_NETCSCP, "Netcs Twin Routing"},
+ {PPP_STPCP, "STP - Control Protocol"},
+ {PPP_EDPCP, "EDPCP - Extreme Discovery Protocol Control Protocol"},
+ {PPP_ACSPC, "Apple Client Server Protocol Control"},
+ {PPP_MPLSCP, "MPLS Control Protocol"},
+ {PPP_P12844CP, "IEEE p1284.4 standard - Protocol Control"},
+ {PPP_TETRACP, "ETSI TETRA TNP1 Control Protocol"},
+ {PPP_MFTPCP, "Multichannel Flow Treatment Protocol"},
+ {PPP_LCP, "Link Control Protocol"},
+ {PPP_PAP, "Password Authentication Protocol"},
+ {PPP_LQR, "Link Quality Report"},
+ {PPP_SPAP, "Shiva Password Authentication Protocol"},
+ {PPP_CBCP, "Callback Control Protocol (CBCP)"},
+ {PPP_BACP, "BACP Bandwidth Allocation Control Protocol"},
+ {PPP_BAP, "BAP Bandwidth Allocation Protocol"},
+ {PPP_VSAP, "Vendor-Specific Authentication Protocol (VSAP)"},
+ {PPP_CONTCP, "Container Control Protocol"},
+ {PPP_CHAP, "Challenge Handshake Authentication Protocol"},
+ {PPP_RSAAP, "RSA Authentication Protocol"},
+ {PPP_EAP, "Extensible Authentication Protocol"},
+ {PPP_SIEP, "Mitsubishi Security Information Exchange Protocol (SIEP)"},
+ {PPP_SBAP, "Stampede Bridging Authorization Protocol"},
+ {PPP_PRPAP, "Proprietary Authentication Protocol"},
+ {PPP_PRPAP2, "Proprietary Authentication Protocol"},
+ {PPP_PRPNIAP, "Proprietary Node ID Authentication Protocol"},
+ {0, NULL}
+};
+value_string_ext ppp_vals_ext = VALUE_STRING_EXT_INIT(ppp_vals);
+
+/* CP (LCP, CCP, IPCP, etc.) codes.
+ * from pppd fsm.h
+ */
+#define VNDRSPCFC 0 /* Vendor Specific: RFC 2153 */
+#define CONFREQ 1 /* Configuration Request */
+#define CONFACK 2 /* Configuration Ack */
+#define CONFNAK 3 /* Configuration Nak */
+#define CONFREJ 4 /* Configuration Reject */
+#define TERMREQ 5 /* Termination Request */
+#define TERMACK 6 /* Termination Ack */
+#define CODEREJ 7 /* Code Reject */
+
+static const value_string cp_vals[] = {
+ {VNDRSPCFC, "Vendor Specific"},
+ {CONFREQ, "Configuration Request"},
+ {CONFACK, "Configuration Ack"},
+ {CONFNAK, "Configuration Nak"},
+ {CONFREJ, "Configuration Reject"},
+ {TERMREQ, "Termination Request"},
+ {TERMACK, "Termination Ack"},
+ {CODEREJ, "Code Reject"},
+ {0, NULL}
+};
+
+/*
+ * LCP-specific packet types.
+ */
+#define PROTREJ 8 /* Protocol Reject */
+#define ECHOREQ 9 /* Echo Request */
+#define ECHOREP 10 /* Echo Reply */
+#define DISCREQ 11 /* Discard Request */
+#define IDENT 12 /* Identification */
+#define TIMEREMAIN 13 /* Time remaining */
+
+/*
+ * CCP-specific packet types.
+ */
+#define RESETREQ 14 /* Reset Request */
+#define RESETACK 15 /* Reset Ack */
+
+/*
+ * CBCP-specific packet types.
+ */
+#define CBREQ 1 /* Callback Request */
+#define CBRES 2 /* Callback Response */
+#define CBACK 3 /* Callback Ack */
+
+#define CBCP_OPT 6 /* Use callback control protocol */
+
+/*
+ * BAP-specific packet types.
+ */
+#define BAP_CREQ 1 /* Call Request */
+#define BAP_CRES 2 /* Call Response */
+#define BAP_CBREQ 3 /* Callback Request */
+#define BAP_CBRES 4 /* Callback Response */
+#define BAP_LDQREQ 5 /* Link Drop Query Request */
+#define BAP_LDQRES 6 /* Link Drop Query Response */
+#define BAP_CSI 7 /* Call Status Indication */
+#define BAP_CSRES 8 /* Call Status Response */
+
+static const value_string lcp_vals[] = {
+ {VNDRSPCFC, "Vendor Specific"},
+ {CONFREQ, "Configuration Request"},
+ {CONFACK, "Configuration Ack"},
+ {CONFNAK, "Configuration Nak"},
+ {CONFREJ, "Configuration Reject"},
+ {TERMREQ, "Termination Request"},
+ {TERMACK, "Termination Ack"},
+ {CODEREJ, "Code Reject"},
+ {PROTREJ, "Protocol Reject"},
+ {ECHOREQ, "Echo Request"},
+ {ECHOREP, "Echo Reply"},
+ {DISCREQ, "Discard Request"},
+ {IDENT, "Identification"},
+ {TIMEREMAIN, "Time Remaining"},
+ {0, NULL}
+};
+
+static const value_string ccp_vals[] = {
+ {VNDRSPCFC, "Vendor Specific"},
+ {CONFREQ, "Configuration Request"},
+ {CONFACK, "Configuration Ack"},
+ {CONFNAK, "Configuration Nak"},
+ {CONFREJ, "Configuration Reject"},
+ {TERMREQ, "Termination Request"},
+ {TERMACK, "Termination Ack"},
+ {CODEREJ, "Code Reject"},
+ {RESETREQ, "Reset Request"},
+ {RESETACK, "Reset Ack"},
+ {0, NULL}
+};
+
+static const value_string cbcp_vals[] = {
+ {CBREQ, "Callback Request"},
+ {CBRES, "Callback Response"},
+ {CBACK, "Callback Ack"},
+ {0, NULL}
+};
+
+static const value_string bap_vals[] = {
+ {BAP_CREQ, "Call Request"},
+ {BAP_CRES, "Call Response"},
+ {BAP_CBREQ, "Callback Request"},
+ {BAP_CBRES, "Callback Response"},
+ {BAP_LDQREQ, "Link Drop Query Request"},
+ {BAP_LDQRES, "Link Drop Query Response"},
+ {BAP_CSI, "Call Status Indication"},
+ {BAP_CSRES, "Call Status Response"},
+ {0, NULL}
+};
+
+#define BAP_RESP_CODE_REQACK 0x00
+#define BAP_RESP_CODE_REQNAK 0x01
+#define BAP_RESP_CODE_REQREJ 0x02
+#define BAP_RESP_CODE_REQFULLNAK 0x03
+static const value_string bap_resp_code_vals[] = {
+ {BAP_RESP_CODE_REQACK, "Request Ack"},
+ {BAP_RESP_CODE_REQNAK, "Request Nak"},
+ {BAP_RESP_CODE_REQREJ, "Request Rej"},
+ {BAP_RESP_CODE_REQFULLNAK, "Request Full Nak"},
+ {0, NULL}
+};
+
+#define BAP_LINK_TYPE_ISDN 0 /* ISDN */
+#define BAP_LINK_TYPE_X25 1 /* X.25 */
+#define BAP_LINK_TYPE_ANALOG 2 /* Analog */
+#define BAP_LINK_TYPE_SD 3 /* Switched Digital (non-ISDN) */
+#define BAP_LINK_TYPE_ISDNOV 4 /* ISDN data over voice */
+#define BAP_LINK_TYPE_RESV5 5 /* Reserved */
+#define BAP_LINK_TYPE_RESV6 6 /* Reserved */
+#define BAP_LINK_TYPE_RESV7 7 /* Reserved */
+static const value_string bap_link_type_vals[] = {
+ {BAP_LINK_TYPE_ISDN, "ISDN"},
+ {BAP_LINK_TYPE_X25, "X.25"},
+ {BAP_LINK_TYPE_ANALOG, "Analog"},
+ {BAP_LINK_TYPE_SD, "Switched Digital (non-ISDN)"},
+ {BAP_LINK_TYPE_ISDNOV, "ISDN data over voice"},
+ {BAP_LINK_TYPE_RESV5, "Reserved"},
+ {BAP_LINK_TYPE_RESV6, "Reserved"},
+ {BAP_LINK_TYPE_RESV7, "Reserved"},
+ {0, NULL}
+};
+
+#define BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT 1 /* Unique Digit */
+#define BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM 2 /* Subscriber Number */
+#define BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR 3 /* Phone Number Sub Address */
+static const value_string bap_phone_delta_subopt_vals[] = {
+ {BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT, "Unique Digit"},
+ {BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM, "Subscriber Number"},
+ {BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR, "Phone Number Sub Address"},
+ {0, NULL}
+};
+
+/*
+ * Cause codes for Cause.
+ *
+ * The following code table is taken from packet-q931.c but is slightly
+ * adapted to BAP protocol.
+ */
+static const value_string q931_cause_code_vals[] = {
+ {0x00, "Call successful"},
+ {0x01, "Unallocated (unassigned) number"},
+ {0x02, "No route to specified transit network"},
+ {0x03, "No route to destination"},
+ {0x04, "Send special information tone"},
+ {0x05, "Misdialled trunk prefix"},
+ {0x06, "Channel unacceptable"},
+ {0x07, "Call awarded and being delivered in an established channel"},
+ {0x08, "Prefix 0 dialed but not allowed"},
+ {0x09, "Prefix 1 dialed but not allowed"},
+ {0x0A, "Prefix 1 dialed but not required"},
+ {0x0B, "More digits received than allowed, call is proceeding"},
+ {0x10, "Normal call clearing"},
+ {0x11, "User busy"},
+ {0x12, "No user responding"},
+ {0x13, "No answer from user (user alerted)"},
+ {0x14, "Subscriber absent"},
+ {0x15, "Call rejected"},
+ {0x16, "Number changed"},
+ {0x17, "Reverse charging rejected"},
+ {0x18, "Call suspended"},
+ {0x19, "Call resumed"},
+ {0x1A, "Non-selected user clearing"},
+ {0x1B, "Destination out of order"},
+ {0x1C, "Invalid number format (incomplete number)"},
+ {0x1D, "Facility rejected"},
+ {0x1E, "Response to STATUS ENQUIRY"},
+ {0x1F, "Normal unspecified"},
+ {0x21, "Circuit out of order"},
+ {0x22, "No circuit/channel available"},
+ {0x23, "Destination unattainable"},
+ {0x25, "Degraded service"},
+ {0x26, "Network out of order"},
+ {0x27, "Transit delay range cannot be achieved"},
+ {0x28, "Throughput range cannot be achieved"},
+ {0x29, "Temporary failure"},
+ {0x2A, "Switching equipment congestion"},
+ {0x2B, "Access information discarded"},
+ {0x2C, "Requested circuit/channel not available"},
+ {0x2D, "Pre-empted"},
+ {0x2E, "Precedence call blocked"},
+ {0x2F, "Resources unavailable, unspecified"},
+ {0x31, "Quality of service unavailable"},
+ {0x32, "Requested facility not subscribed"},
+ {0x33, "Reverse charging not allowed"},
+ {0x34, "Outgoing calls barred"},
+ {0x35, "Outgoing calls barred within CUG"},
+ {0x36, "Incoming calls barred"},
+ {0x37, "Incoming calls barred within CUG"},
+ {0x38, "Call waiting not subscribed"},
+ {0x39, "Bearer capability not authorized"},
+ {0x3A, "Bearer capability not presently available"},
+ {0x3E, "Inconsistency in designated outgoing access information and subscriber class"},
+ {0x3F, "Service or option not available, unspecified"},
+ {0x41, "Bearer capability not implemented"},
+ {0x42, "Channel type not implemented"},
+ {0x43, "Transit network selection not implemented"},
+ {0x44, "Message not implemented"},
+ {0x45, "Requested facility not implemented"},
+ {0x46, "Only restricted digital information bearer capability is available"},
+ {0x4F, "Service or option not implemented, unspecified"},
+ {0x51, "Invalid call reference value"},
+ {0x52, "Identified channel does not exist"},
+ {0x53, "Call identity does not exist for suspended call"},
+ {0x54, "Call identity in use"},
+ {0x55, "No call suspended"},
+ {0x56, "Call having the requested call identity has been cleared"},
+ {0x57, "Called user not member of CUG"},
+ {0x58, "Incompatible destination"},
+ {0x59, "Non-existent abbreviated address entry"},
+ {0x5A, "Destination address missing, and direct call not subscribed"},
+ {0x5B, "Invalid transit network selection (national use)"},
+ {0x5C, "Invalid facility parameter"},
+ {0x5D, "Mandatory information element is missing"},
+ {0x5F, "Invalid message, unspecified"},
+ {0x60, "Mandatory information element is missing"},
+ {0x61, "Message type non-existent or not implemented"},
+ {0x62, "Message not compatible with call state or message type non-existent or not implemented"},
+ {0x63, "Information element non-existent or not implemented"},
+ {0x64, "Invalid information element contents"},
+ {0x65, "Message not compatible with call state"},
+ {0x66, "Recovery on timer expiry"},
+ {0x67, "Parameter non-existent or not implemented - passed on"},
+ {0x6E, "Message with unrecognized parameter discarded"},
+ {0x6F, "Protocol error, unspecified"},
+ {0x7F, "Internetworking, unspecified"},
+ {0xFF, "Non-specific failure"},
+ {0, NULL}
+};
+static value_string_ext q931_cause_code_vals_ext = VALUE_STRING_EXT_INIT(q931_cause_code_vals);
+
+static const value_string bap_call_status_opt_action_vals[] = {
+ {0, "No retry"},
+ {1, "Retry"},
+ {0, NULL}
+};
+
+#define STAC_CM_NONE 0
+#define STAC_CM_LCB 1
+#define STAC_CM_CRC 2
+#define STAC_CM_SN 3
+#define STAC_CM_EXTMODE 4
+static const value_string stac_checkmode_vals[] = {
+ {STAC_CM_NONE, "None"},
+ {STAC_CM_LCB, "LCB"},
+ {STAC_CM_CRC, "CRC"},
+ {STAC_CM_SN, "Sequence Number"},
+ {STAC_CM_EXTMODE, "Extended Mode"},
+ {0, NULL}
+};
+
+#define LZSDCP_CM_NONE 0
+#define LZSDCP_CM_LCB 1
+#define LZSDCP_CM_SN 2
+#define LZSDCP_CM_SN_LCB 3
+static const value_string lzsdcp_checkmode_vals[] = {
+ {LZSDCP_CM_NONE, "None"},
+ {LZSDCP_CM_LCB, "LCB"},
+ {LZSDCP_CM_SN, "Sequence Number"},
+ {LZSDCP_CM_SN_LCB, "Sequence Number + LCB (default)"},
+ {0, NULL}
+};
+
+#define LZSDCP_PM_NONE 0
+#define LZSDCP_PM_PROC_UNCOMP 1
+static const value_string lzsdcp_processmode_vals[] = {
+ {LZSDCP_PM_NONE, "None (default)"},
+ {LZSDCP_PM_PROC_UNCOMP, "Process-Uncompressed"},
+ {0, NULL}
+};
+
+#define DCE_MODE_1 1
+#define DCE_MODE_2 2
+static const value_string dce_mode_vals[] = {
+ {DCE_MODE_1, "No Additional Negotiation"},
+ {DCE_MODE_2, "Full PPP Negotiation and State Machine"},
+ {0, NULL}
+};
+
+/*
+ * Options. (LCP)
+ */
+#define CI_VENDORSPECIFIC 0 /* Vendor Specific [RFC2153] */
+#define CI_MRU 1 /* Maximum Receive Unit [RFC1661] */
+#define CI_ASYNCMAP 2 /* Async Control Character Map */
+#define CI_AUTHPROT 3 /* Authentication Protocol [RFC1661] */
+#define CI_QUALITY 4 /* Quality Protocol [RFC1661] */
+#define CI_MAGICNUMBER 5 /* Magic Number [RFC1661] */
+#define CI_LINKQUALMON 6 /* DEPRECATED (Quality Protocol) [RFC1172] */
+#define CI_PCOMPRESSION 7 /* Protocol Field Compression [RFC1661] */
+#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression
+ [RFC1661] */
+#define CI_FCS_ALTERNATIVES 9 /* FCS Alternatives [RFC1570] */
+#define CI_SELF_DESCRIBING_PAD 10 /* Self-Describing Pad [RFC1570] */
+#define CI_NUMBERED_MODE 11 /* Numbered Mode [RFC1663] */
+#define CI_MULTILINK_PROC 12 /* DEPRECATED (Multi-Link Procedure) */
+#define CI_CALLBACK 13 /* Callback [RFC1570] */
+#define CI_CONNECTTIME 14 /* DEPRECATED (Connect Time) */
+#define CI_COMPOUND_FRAMES 15 /* DEPRECATED (Compound Frames) [RFC1570] */
+#define CI_NOMDATAENCAP 16 /* DEPRECATED (Nominal Data Encapsulation) */
+/* NOTE: IANA lists CI_NOMDATAENCAP as 16, but it is listed as 14 in
+ * https://tools.ietf.org/html/draft-ietf-pppext-dataencap-03.
+ * Which is correct is anyone's guess. */
+#define CI_MULTILINK_MRRU 17 /* Multilink MRRU [RFC1990] */
+#define CI_MULTILINK_SSNH 18 /* Multilink Short Sequence Number Header
+ [RFC1990] */
+#define CI_MULTILINK_EP_DISC 19 /* Multilink Endpoint Discriminator
+ [RFC1990] */
+#define CI_PROP_KEN 20 /* Proprietary [Ken Culbert] ken@funk.com */
+#define CI_DCE_IDENTIFIER 21 /* DCE Identifier [RFC1976]: Warning:
+ Option type 25 in the RFC is incorrect */
+#define CI_MULTILINK_PLUS_PROC 22 /* Multilink Plus Procedure [RFC1934] */
+#define CI_LINK_DISC_FOR_BACP 23 /* Link Discriminator for BACP [RFC2125] */
+#define CI_LCP_AUTHENTICATION 24 /* LCP Authentication Option [Culbert] */
+#define CI_COBS 25 /* Consistent Overhead Byte Stuffing (COBS)
+ [Carlson] */
+#define CI_PREFIX_ELISION 26 /* Prefix elision [RFC2686][RFC2687] */
+#define CI_MULTILINK_HDR_FMT 27 /* Multilink header format
+ [RFC2686][RFC2687] */
+#define CI_INTERNATIONALIZATION 28 /* Internationalization [RFC2484] */
+#define CI_SDL_ON_SONET_SDH 29 /* Simple Data Link on SONET/SDH
+ [RFC2823] */
+#define CI_UNASSIGNED 30 /* Unassigned ... but so are 31-255, so
+ why do they bother specifically
+ mentioning this one, I wonder? */
+
+static int hf_lcp_magic_number = -1;
+static int hf_lcp_data = -1;
+static int hf_lcp_message = -1;
+static int hf_lcp_secs_remaining = -1;
+static int hf_lcp_rej_proto = -1;
+static int hf_lcp_opt_type = -1;
+static int hf_lcp_opt_length = -1;
+static int hf_lcp_opt_oui = -1;
+static int hf_lcp_opt_kind = -1;
+static int hf_lcp_opt_data = -1;
+static int hf_lcp_opt_mru = -1;
+static int hf_lcp_opt_asyncmap = -1;
+static int hf_lcp_opt_asyncmap_nul = -1;
+static int hf_lcp_opt_asyncmap_soh = -1;
+static int hf_lcp_opt_asyncmap_stx = -1;
+static int hf_lcp_opt_asyncmap_etx = -1;
+static int hf_lcp_opt_asyncmap_eot = -1;
+static int hf_lcp_opt_asyncmap_enq = -1;
+static int hf_lcp_opt_asyncmap_ack = -1;
+static int hf_lcp_opt_asyncmap_bel = -1;
+static int hf_lcp_opt_asyncmap_bs = -1;
+static int hf_lcp_opt_asyncmap_ht = -1;
+static int hf_lcp_opt_asyncmap_lf = -1;
+static int hf_lcp_opt_asyncmap_vt = -1;
+static int hf_lcp_opt_asyncmap_ff = -1;
+static int hf_lcp_opt_asyncmap_cr = -1;
+static int hf_lcp_opt_asyncmap_so = -1;
+static int hf_lcp_opt_asyncmap_si = -1;
+static int hf_lcp_opt_asyncmap_dle = -1;
+static int hf_lcp_opt_asyncmap_dc1 = -1;
+static int hf_lcp_opt_asyncmap_dc2 = -1;
+static int hf_lcp_opt_asyncmap_dc3 = -1;
+static int hf_lcp_opt_asyncmap_dc4 = -1;
+static int hf_lcp_opt_asyncmap_nak = -1;
+static int hf_lcp_opt_asyncmap_syn = -1;
+static int hf_lcp_opt_asyncmap_etb = -1;
+static int hf_lcp_opt_asyncmap_can = -1;
+static int hf_lcp_opt_asyncmap_em = -1;
+static int hf_lcp_opt_asyncmap_sub = -1;
+static int hf_lcp_opt_asyncmap_esc = -1;
+static int hf_lcp_opt_asyncmap_fs = -1;
+static int hf_lcp_opt_asyncmap_gs = -1;
+static int hf_lcp_opt_asyncmap_rs = -1;
+static int hf_lcp_opt_asyncmap_us = -1;
+static int hf_lcp_opt_auth_protocol = -1;
+static int hf_lcp_opt_algorithm = -1;
+static int hf_lcp_opt_quality_protocol = -1;
+static int hf_lcp_opt_magic_number = -1;
+static int hf_lcp_opt_reportingperiod = -1;
+static int hf_lcp_opt_fcs_alternatives = -1;
+static int hf_lcp_opt_fcs_alternatives_null = -1;
+static int hf_lcp_opt_fcs_alternatives_ccitt16 = -1;
+static int hf_lcp_opt_fcs_alternatives_ccitt32 = -1;
+static int hf_lcp_opt_maximum = -1;
+static int hf_lcp_opt_window = -1;
+static int hf_lcp_opt_hdlc_address = -1;
+static int hf_lcp_opt_operation = -1;
+static int hf_lcp_opt_message = -1;
+static int hf_lcp_opt_mrru = -1;
+static int hf_lcp_opt_ep_disc_class = -1;
+static int hf_lcp_opt_ip_address = -1;
+static int hf_lcp_opt_802_1_address = -1;
+static int hf_lcp_opt_magic_block = -1;
+static int hf_lcp_opt_psndn = -1;
+static int hf_lcp_opt_mode = -1;
+static int hf_lcp_opt_unused = -1;
+static int hf_lcp_opt_link_discrim = -1;
+static int hf_lcp_opt_id = -1;
+static int hf_lcp_opt_cobs_flags = -1;
+static int hf_lcp_opt_cobs_flags_res = -1;
+static int hf_lcp_opt_cobs_flags_pre = -1;
+static int hf_lcp_opt_cobs_flags_zxe = -1;
+static int hf_lcp_opt_class = -1;
+static int hf_lcp_opt_prefix = -1;
+static int hf_lcp_opt_code = -1;
+static int hf_lcp_opt_max_susp_classes = -1;
+static int hf_lcp_opt_MIBenum = -1;
+static int hf_lcp_opt_language_tag = -1;
+
+static gboolean
+ppp_option_len_check(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, int proto, guint len, guint optlen)
+{
+ if (len != optlen) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
+ "%s (with option length = %u byte%s; should be %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto)),
+ len, plurality(len, "", "s"), optlen);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ /* Started as a copy of dissect_ip_tcp_options(), but was changed to support
+ options as a dissector table */
+static void
+ppp_dissect_options(tvbuff_t *tvb, int offset, guint length, dissector_table_t const option_dissectors,
+ packet_info *pinfo, proto_tree *opt_tree)
+{
+ guchar opt;
+ guint optlen;
+ const char *name;
+ dissector_handle_t option_dissector = NULL;
+ tvbuff_t *next_tvb;
+
+ while (length > 0) {
+ opt = tvb_get_guint8(tvb, offset);
+ --length; /* account for type byte */
+ if (option_dissectors != NULL) {
+ option_dissector = dissector_get_uint_handle(option_dissectors, opt);
+ if (option_dissector == NULL) {
+ name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);
+ } else {
+ name = dissector_handle_get_protocol_short_name(option_dissector);
+ }
+ } else {
+ name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);
+ }
+
+ /* Option has a length. Is it in the packet? */
+ if (length == 0) {
+ /* Bogus - packet must at least include option code byte and
+ length byte! */
+ proto_tree_add_expert_format(opt_tree, pinfo, &ei_ppp_opt_len_invalid, tvb, offset, 1,
+ "%s (length byte past end of options)", name);
+ return;
+ }
+
+ optlen = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
+ --length; /* account for length byte */
+
+ if (optlen < 2) {
+ /* Bogus - option length is too short to include option code and
+ option length. */
+ proto_tree_add_expert_format(opt_tree, pinfo, &ei_ppp_opt_len_invalid, tvb, offset, 2,
+ "%s (with too-short option length = %u byte%s)",
+ name, optlen, plurality(optlen, "", "s"));
+ return;
+ } else if (optlen - 2 > length) {
+ /* Bogus - option goes past the end of the header. */
+ proto_tree_add_expert_format(opt_tree, pinfo, &ei_ppp_opt_len_invalid, tvb, offset, length,
+ "%s (option length = %u byte%s says option goes past end of options)",
+ name, optlen, plurality(optlen, "", "s"));
+ return;
+ }
+
+ if (option_dissector == NULL) {
+ proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, ett_ppp_unknown_opt, NULL, "%s (%u byte%s)",
+ name, optlen, plurality(optlen, "", "s"));
+ } else {
+ next_tvb = tvb_new_subset_length(tvb, offset, optlen);
+ call_dissector(option_dissector, next_tvb, pinfo, opt_tree);
+ proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name);
+ }
+ offset += optlen;
+ length -= (optlen-2); //already accounted for type and len bytes
+ }
+}
+
+static void
+dissect_lcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_lcp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_lcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_lcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_lcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static gboolean
+dissect_lcp_var_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ int len = tvb_reported_length(tvb);
+
+ if (len < expected_length) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto_lcp_option_vendor)),
+ len, plurality(len, "", "s"), 6);
+ return FALSE;
+ }
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, -1, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_lcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+/* Used for:
+ * Protocol Field Compression
+ * Address and Control Field Compression
+ * Compound Frames (Deprecated)
+ * Nominal Data Encapsulation (Deprecated)
+ * Multilink Short Sequence Number Header
+ * Simple Data Link on SONET/SDH
+ */
+static int
+dissect_lcp_simple_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett)
+{
+ proto_tree *field_tree;
+ proto_item *ti;
+
+ dissect_lcp_fixed_opt(tvb, pinfo, tree, proto, ett, 2, &field_tree, &ti);
+ return tvb_captured_length(tvb);
+}
+
+/* 3GPP2 X.S0057-B v1.0
+ * 9.1.4.1 3GPP2 VSNCP Configuration Options
+ * Options. (VSNCP)
+ */
+
+#define CI_PDN_IDENTIFIER 1
+#define CI_ACCESS_POINT_NM 2
+#define CI_PDN_TYPE 3
+#define CI_PDN_ADDRESS 4
+#define CI_PROTOCOL_CONFIG 5
+#define CI_ERROR_CODE 6
+#define CI_ATTACH_TYPE 7
+#define CI_IPv4DEFAULT_ROUTER 8
+#define CI_ADDRESS_ALLOC 9
+#define CI_APN_AMBR 10
+#define CI_IPv6_HSGW_LLA_IID 11
+
+/*
+ * CHAP Algorithms
+ */
+/* 0-4: Reserved */
+#define CHAP_ALG_MD5 5 /* CHAP with MD5 */
+#define CHAP_AGL_SHA1 6 /* CHAP with SHA-1 [Black] */
+/* 7-127: Unassigned */
+#define CHAP_ALG_MSV1 128 /* MS-CHAP */
+#define CHAP_ALG_MSV2 129 /* MS-CHAP-2 */
+
+static const range_string chap_alg_rvals[] = {
+ {0, 4, "Reserved"},
+ {CHAP_ALG_MD5, CHAP_ALG_MD5, "CHAP with MD5"},
+ {CHAP_AGL_SHA1, CHAP_AGL_SHA1, "CHAP with SHA-1"},
+ {CHAP_ALG_MSV1, CHAP_ALG_MSV1, "MS-CHAP"},
+ {CHAP_ALG_MSV2, CHAP_ALG_MSV2, "MS-CHAP-2"},
+ {0, 0, NULL}
+};
+
+
+/*
+ * Options. (IPCP)
+ * https://tools.ietf.org/html/rfc1172
+ * https://tools.ietf.org/html/rfc1332
+ * https://tools.ietf.org/html/rfc1877
+ * https://tools.ietf.org/html/rfc2290
+ * https://tools.ietf.org/html/rfc3241
+ * https://tools.ietf.org/html/rfc3545
+ */
+#define CI_ADDRS 1 /* IP Addresses (deprecated) (RFC 1172) */
+#define CI_COMPRESS_PROTO 2 /* Compression Protocol (RFC 1332) */
+#define CI_ADDR 3 /* IP Address (RFC 1332) */
+#define CI_MOBILE_IPv4 4 /* Mobile IPv4 (RFC 2290) */
+#define CI_PRI_DNS 129 /* Primary DNS value (RFC 1877) */
+#define CI_PRI_NBNS 130 /* Primary NBNS value (RFC 1877) */
+#define CI_SEC_DNS 131 /* Secondary DNS value (RFC 1877) */
+#define CI_SEC_NBNS 132 /* Secondary NBNS value (RFC 1877) */
+
+static int hf_ipcp_opt_type = -1;
+static int hf_ipcp_opt_length = -1;
+static int hf_ipcp_opt_src_address = -1;
+static int hf_ipcp_opt_dst_address = -1;
+static int hf_ipcp_opt_compress_proto = -1;
+static int hf_ipcp_opt_max_cid = -1;
+static int hf_ipcp_opt_mrru = -1;
+static int hf_ipcp_opt_max_slot_id = -1;
+static int hf_ipcp_opt_comp_slot_id = -1;
+static int hf_ipcp_opt_tcp_space = -1;
+static int hf_ipcp_opt_non_tcp_space = -1;
+static int hf_ipcp_opt_f_max_period = -1;
+static int hf_ipcp_opt_f_max_time = -1;
+static int hf_ipcp_opt_max_header = -1;
+static int hf_ipcp_data = -1;
+static int hf_ipcp_opt_ip_address = -1;
+static int hf_ipcp_opt_mobilenodehomeaddr = -1;
+static int hf_ipcp_opt_pri_dns_address = -1;
+static int hf_ipcp_opt_pri_nbns_address = -1;
+static int hf_ipcp_opt_sec_dns_address = -1;
+static int hf_ipcp_opt_sec_nbns_address = -1;
+
+static int hf_ipcp_opt_rohc_type = -1;
+static int hf_ipcp_opt_rohc_length = -1;
+static int hf_ipcp_opt_rohc_profile = -1;
+static int hf_ipcp_opt_iphc_type = -1;
+static int hf_ipcp_opt_iphc_length = -1;
+static int hf_ipcp_opt_iphc_param = -1;
+
+/*
+ * IP Compression options
+ */
+#define IPCP_ROHC 0x0003 /* RFC3241 */
+#define IPCP_COMPRESS_VJ_1172 0x0037 /* value defined in RFC1172 (typo) */
+#define IPCP_COMPRESS_VJ 0x002d /* value defined in RFC1332 (correct) */
+#define IPCP_COMPRESS_IPHC 0x0061 /* RFC3544 (and RFC2509) */
+
+static const value_string ipcp_compress_proto_vals[] = {
+ {IPCP_ROHC, "Robust Header Compression (ROHC)"},
+ {IPCP_COMPRESS_VJ, "VJ compression"},
+ {IPCP_COMPRESS_VJ_1172, "VJ compression (RFC1172-typo)"},
+ {IPCP_COMPRESS_IPHC, "IPHC compression"},
+ {0, NULL}
+};
+
+/* IPHC suboptions (RFC2508, 3544) */
+#define IPCP_IPHC_CRTP 1
+#define IPCP_IPHC_ECRTP 2
+#define IPCP_IPHC_NEGHC 3
+
+static const value_string ipcp_iphc_parameter_vals[] = {
+ {1, "The number of contexts for TCP Space is 0"},
+ {2, "The number of contexts for Non TCP Space is 0"},
+ {0, NULL}
+};
+
+
+/* ROHC suboptions */
+#define IPCP_ROHC_PROFILES 1
+
+/* From https://tools.ietf.org/html/rfc3095 */
+static const value_string ipcp_rohc_profile_vals[] = {
+ {0x0000, "ROHC uncompressed -- no compression"},
+ {0x0002, "ROHC UDP -- non-RTP UDP/IP compression"},
+ {0x0003, "ROHC ESP -- ESP/IP compression"},
+ {0, NULL}
+};
+
+/*
+* Options. (bcp_ncp)
+1 Bridge-Identification
+2 Line-Identification
+3 MAC-Support
+4 Tinygram-Compression
+5 LAN-Identification (obsoleted)
+6 MAC-Address
+7 Spanning-Tree-Protocol (old formatted)
+8 IEEE 802 Tagged Frame
+9 Management Inline
+10 Bridge Control Packet Indicator
+
+*/
+#define CI_BCPNCP_BRIDGE_ID 1
+#define CI_BCPNCP_LINE_ID 2
+#define CI_BCPNCP_MAC_SUPPORT 3
+#define CI_BCPNCP_TINYGRAM_COMP 4
+#define CI_BCPNCP_LAN_ID 5
+#define CI_BCPNCP_MAC_ADDRESS 6
+#define CI_BCPNCP_STP 7
+#define CI_BCPNCP_IEEE_802_TAGGED_FRAME 8
+#define CI_BCPNCP_MANAGEMENT_INLINE 9
+#define CI_BCPNCP_BCP_IND 10
+
+/*
+ * Options. (OSINLCP)
+ */
+#define CI_OSINLCP_ALIGN_NPDU 1 /* Alignment of the OSI NPDU (RFC 1377) */
+
+static int hf_osinlcp_opt_type = -1;
+static int hf_osinlcp_opt_length = -1;
+static int hf_osinlcp_opt_alignment = -1;
+
+/*
+ * Options. (CCP)
+ */
+#define CI_CCP_OUI 0 /* OUI (RFC1962) */
+#define CI_CCP_PREDICT1 1 /* Predictor type 1 (RFC1962) */
+#define CI_CCP_PREDICT2 2 /* Predictor type 2 (RFC1962) */
+#define CI_CCP_PUDDLE 3 /* Puddle Jumper (RFC1962) */
+#define CI_CCP_HPPPC 16 /* Hewlett-Packard PPC (RFC1962) */
+#define CI_CCP_STAC 17 /* stac Electronics LZS (RFC1974) */
+#define CI_CCP_MPPE 18 /* Microsoft PPE/C (RFC2118/3078) */
+#define CI_CCP_GFZA 19 /* Gandalf FZA (RFC1962) */
+#define CI_CCP_V42BIS 20 /* V.42bis compression */
+#define CI_CCP_BSDLZW 21 /* BSD LZW Compress (RFC1977) */
+#define CI_CCP_LZSDCP 23 /* LZS-DCP (RFC1967) */
+#define CI_CCP_MVRCA 24 /* MVRCA (Magnalink) (RFC1975) */
+#define CI_CCP_DCE 25 /* DCE (RFC1976) */
+#define CI_CCP_DEFLATE 26 /* Deflate (RFC1979) */
+#define CI_CCP_V44LZJH 27 /* V.44/LZJH (https://tools.ietf.org/html/draft-heath-ppp-v44-01) */
+#define CI_CCP_RESERVED 255 /* Reserved (RFC1962) */
+
+static int hf_ccp_opt_type = -1;
+static int hf_ccp_opt_length = -1;
+static int hf_ccp_opt_oui = -1;
+static int hf_ccp_opt_subtype = -1;
+static int hf_ccp_opt_data = -1;
+static int hf_ccp_opt_history_count = -1;
+static int hf_ccp_opt_cm = -1;
+static int hf_ccp_opt_cm_reserved = -1;
+static int hf_ccp_opt_cm_check_mode = -1;
+static int hf_ccp_opt_supported_bits = -1;
+static int hf_ccp_opt_supported_bits_h = -1;
+static int hf_ccp_opt_supported_bits_m = -1;
+static int hf_ccp_opt_supported_bits_s = -1;
+static int hf_ccp_opt_supported_bits_l = -1;
+static int hf_ccp_opt_supported_bits_d = -1;
+static int hf_ccp_opt_supported_bits_c = -1;
+static int hf_ccp_opt_history = -1;
+static int hf_ccp_opt_version = -1;
+static int hf_ccp_opt_vd = -1;
+static int hf_ccp_opt_vd_vers = -1;
+static int hf_ccp_opt_vd_dict = -1;
+static int hf_ccp_opt_check_mode = -1;
+static int hf_ccp_opt_process_mode = -1;
+static int hf_ccp_opt_fe = -1;
+static int hf_ccp_opt_p = -1;
+static int hf_ccp_opt_History = -1; /* Different than hf_ccp_opt_history */
+static int hf_ccp_opt_contexts = -1;
+static int hf_ccp_opt_mode = -1;
+static int hf_ccp_opt_window = -1;
+static int hf_ccp_opt_method = -1;
+static int hf_ccp_opt_mbz = -1;
+static int hf_ccp_opt_chk = -1;
+static int hf_ccp_opt_mode_dictcount = -1;
+static int hf_ccp_opt_dict_size = -1;
+static int hf_ccp_opt_history_length = -1;
+
+/*
+ * Options. (CBCP)
+ */
+#define CI_CBCP_NO_CALLBACK 1 /* No callback */
+#define CI_CBCP_CB_USER 2 /* Callback to a user-specified number */
+#define CI_CBCP_CB_PRE 3 /* Callback to a pre-specified or
+ administrator specified number */
+#define CI_CBCP_CB_ANY 4 /* Callback to any of a list of numbers */
+
+/*
+ * Options. (BACP)
+ */
+#define CI_BACP_FAVORED_PEER 1 /* Favored-Peer */
+
+/*
+ * Options. (BAP)
+ */
+#define CI_BAP_LINK_TYPE 1 /* Link Type */
+#define CI_BAP_PHONE_DELTA 2 /* Phone-Delta */
+#define CI_BAP_NO_PHONE_NUM_NEEDED 3 /* No Phone Number Needed */
+#define CI_BAP_REASON 4 /* Reason */
+#define CI_BAP_LINK_DISC 5 /* Link Discriminator */
+#define CI_BAP_CALL_STATUS 6 /* Call Status */
+
+static int dissect_ppp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
+
+static const value_string pap_vals[] = {
+ {CONFREQ, "Authenticate-Request"},
+ {CONFACK, "Authenticate-Ack"},
+ {CONFNAK, "Authenticate-Nak"},
+ {0, NULL}
+};
+
+#define CHAP_CHAL 1 /* CHAP Challenge */
+#define CHAP_RESP 2 /* CHAP Response */
+#define CHAP_SUCC 3 /* CHAP Success */
+#define CHAP_FAIL 4 /* CHAP Failure */
+
+static const value_string chap_vals[] = {
+ {CHAP_CHAL, "Challenge"},
+ {CHAP_RESP, "Response"},
+ {CHAP_SUCC, "Success"},
+ {CHAP_FAIL, "Failure"},
+ {0, NULL}
+};
+
+static const value_string pppmuxcp_vals[] = {
+ {CONFREQ, "Configuration Request"},
+ {CONFACK, "Configuration Ack"},
+ {0, NULL}
+};
+
+/*
+ * PPPMuxCP options
+ */
+
+#define CI_DEFAULT_PID 1
+
+static const true_false_string tfs_pppmux_length_field = { "2 bytes", "1 byte" };
+
+/*
+ * Options. (IPv6CP)
+ */
+#define CI_IPV6CP_IF_ID 1 /* Interface Identifier (RFC 2472) */
+#define CI_IPV6CP_COMPRESSTYPE 2 /* Compression Type (RFC 2472) */
+
+/*
+*******************************************************************************
+* DETAILS : Calculate a new FCS-16 given the current FCS-16 and the new data.
+*******************************************************************************
+*/
+static guint16
+fcs16(tvbuff_t *tvbuff)
+{
+ guint len = tvb_reported_length(tvbuff) - 2;
+
+ /* Check for Invalid Length */
+ if (len == 0)
+ return (0x0000);
+ return crc16_ccitt_tvb(tvbuff, len);
+}
+
+/*
+*******************************************************************************
+* DETAILS : Calculate a new FCS-32 given the current FCS-32 and the new data.
+*******************************************************************************
+*/
+static guint32
+fcs32(tvbuff_t *tvbuff)
+{
+ guint len = tvb_reported_length(tvbuff) - 4;
+
+ /* Check for invalid Length */
+ if (len == 0)
+ return (0x00000000);
+ return crc32_ccitt_tvb(tvbuff, len);
+}
+
+tvbuff_t *
+decode_fcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *fh_tree, int fcs_decode, int proto_offset)
+{
+ tvbuff_t *next_tvb;
+ gint len, reported_len;
+
+ /*
+ * Remove the FCS, if any, from the packet data.
+ */
+ switch (fcs_decode) {
+
+ case NO_FCS:
+ next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
+ break;
+
+ case FCS_16:
+ /*
+ * Do we have the entire packet, and does it include a 2-byte FCS?
+ */
+ len = tvb_captured_length_remaining(tvb, proto_offset);
+ reported_len = tvb_reported_length_remaining(tvb, proto_offset);
+ if (reported_len < 2 || len < 0) {
+ /*
+ * The packet is claimed not to even have enough data for a 2-byte
+ * FCS, or we're already past the end of the captured data.
+ * Don't slice anything off.
+ */
+ next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
+ } else if (len < reported_len) {
+ /*
+ * The packet is claimed to have enough data for a 2-byte FCS, but
+ * we didn't capture all of the packet.
+ * Slice off the 2-byte FCS from the reported length, and trim the
+ * captured length so it's no more than the reported length; that
+ * will slice off what of the FCS, if any, is in the captured
+ * length.
+ */
+ reported_len -= 2;
+ if (len > reported_len)
+ len = reported_len;
+ next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
+ } else {
+ /*
+ * We have the entire packet, and it includes a 2-byte FCS.
+ * Slice it off.
+ */
+ len -= 2;
+ reported_len -= 2;
+ next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
+
+ /*
+ * Compute the FCS and put it into the tree.
+ */
+ proto_tree_add_checksum(fh_tree, tvb, proto_offset + len, hf_ppp_fcs_16, hf_ppp_fcs_status, &ei_ppp_fcs, pinfo, fcs16(tvb),
+ ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
+ }
+ break;
+
+ case FCS_32:
+ /*
+ * Do we have the entire packet, and does it include a 4-byte FCS?
+ */
+ len = tvb_captured_length_remaining(tvb, proto_offset);
+ reported_len = tvb_reported_length_remaining(tvb, proto_offset);
+ if (reported_len < 4) {
+ /*
+ * The packet is claimed not to even have enough data for a 4-byte
+ * FCS. Just pass on the tvbuff as is.
+ */
+ next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
+ } else if (len < reported_len) {
+ /*
+ * The packet is claimed to have enough data for a 4-byte FCS, but
+ * we didn't capture all of the packet.
+ * Slice off the 4-byte FCS from the reported length, and trim the
+ * captured length so it's no more than the reported length; that
+ * will slice off what of the FCS, if any, is in the captured
+ * length.
+ */
+ reported_len -= 4;
+ if (len > reported_len)
+ len = reported_len;
+ next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
+ } else {
+ /*
+ * We have the entire packet, and it includes a 4-byte FCS.
+ * Slice it off.
+ */
+ len -= 4;
+ reported_len -= 4;
+ next_tvb = tvb_new_subset_length_caplen(tvb, proto_offset, len, reported_len);
+
+ /*
+ * Compute the FCS and put it into the tree.
+ */
+ proto_tree_add_checksum(fh_tree, tvb, proto_offset + len, hf_ppp_fcs_32, hf_ppp_fcs_status, &ei_ppp_fcs, pinfo, fcs32(tvb),
+ ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
+ }
+ break;
+
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ next_tvb = NULL;
+ break;
+ }
+
+ return next_tvb;
+}
+
+static gboolean
+capture_ppp_hdlc(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
+{
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2))
+ return FALSE;
+
+ if (pd[0] == CHDLC_ADDR_UNICAST || pd[0] == CHDLC_ADDR_MULTICAST)
+ return call_capture_dissector(chdlc_cap_handle, pd, offset, len, cpinfo, pseudo_header);
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, 4))
+ return FALSE;
+
+ return try_capture_dissector("ppp_hdlc", pntoh16(&pd[offset + 2]), pd, offset + 4, len, cpinfo, pseudo_header);
+}
+
+static int
+dissect_lcp_vendor_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *ti;
+ int offset = 0;
+ int len = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_vendor, ett_lcp_vendor_opt, 6,
+ &field_tree, &ti))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_lcp_opt_oui, tvb, offset + 2, 3, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(field_tree, hf_lcp_opt_kind, tvb, offset + 5, 1,
+ ENC_BIG_ENDIAN);
+ if (len > 6) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset + 6,
+ len - 6, ENC_NA);
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_mru_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *ti;
+ guint32 mru;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_mru, ett_lcp_mru_opt, 4,
+ &field_tree, &ti))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_mru, tvb, offset + 2, 2,
+ ENC_BIG_ENDIAN, &mru);
+ proto_item_append_text(ti, ": %u", mru);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_async_map_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf, *ti;
+ int offset = 0;
+ static int * const asyncmap_fields[] = {
+ &hf_lcp_opt_asyncmap_us, &hf_lcp_opt_asyncmap_rs,
+ &hf_lcp_opt_asyncmap_gs, &hf_lcp_opt_asyncmap_fs,
+ &hf_lcp_opt_asyncmap_esc, &hf_lcp_opt_asyncmap_sub,
+ &hf_lcp_opt_asyncmap_em, &hf_lcp_opt_asyncmap_can,
+ &hf_lcp_opt_asyncmap_etb, &hf_lcp_opt_asyncmap_syn,
+ &hf_lcp_opt_asyncmap_nak, &hf_lcp_opt_asyncmap_dc4,
+ &hf_lcp_opt_asyncmap_dc3, &hf_lcp_opt_asyncmap_dc2,
+ &hf_lcp_opt_asyncmap_dc1, &hf_lcp_opt_asyncmap_dle,
+ &hf_lcp_opt_asyncmap_si, &hf_lcp_opt_asyncmap_so,
+ &hf_lcp_opt_asyncmap_cr, &hf_lcp_opt_asyncmap_ff,
+ &hf_lcp_opt_asyncmap_vt, &hf_lcp_opt_asyncmap_lf,
+ &hf_lcp_opt_asyncmap_ht, &hf_lcp_opt_asyncmap_bs,
+ &hf_lcp_opt_asyncmap_bel, &hf_lcp_opt_asyncmap_ack,
+ &hf_lcp_opt_asyncmap_enq, &hf_lcp_opt_asyncmap_eot,
+ &hf_lcp_opt_asyncmap_etx, &hf_lcp_opt_asyncmap_stx,
+ &hf_lcp_opt_asyncmap_soh, &hf_lcp_opt_asyncmap_nul,
+ NULL
+ };
+
+ static const char *ctrlchars[32] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1 (XON)", "DC2", "DC3 (XOFF)", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+
+ guint32 map;
+ gboolean anyctrlchars;
+ int i;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_async_map, ett_lcp_asyncmap_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ map = tvb_get_ntohl(tvb, offset + 2);
+ proto_item_append_text(tf, ": 0x%08x", map);
+
+ ti = proto_tree_add_bitmask(field_tree, tvb, offset + 2,
+ hf_lcp_opt_asyncmap, ett_lcp_asyncmap_opt, asyncmap_fields,
+ ENC_BIG_ENDIAN);
+
+ if (map == 0x00000000) {
+ proto_item_append_text(tf, " (None)");
+ proto_item_append_text(ti, " (None)");
+ } else if (map == 0xffffffff) {
+ proto_item_append_text(tf, " (All)");
+ proto_item_append_text(ti, " (All)");
+ } else {
+ for (anyctrlchars = FALSE, i = 31; i >= 0; i--) {
+ if (map & (1 << i)) {
+ if (anyctrlchars)
+ proto_item_append_text(tf, ", %s", ctrlchars[i]);
+ else {
+ anyctrlchars = TRUE;
+ proto_item_append_text(tf, "%s", ctrlchars[i]);
+ }
+ }
+ }
+ proto_item_append_text(tf, ")");
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_authprot_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *ti;
+ guint32 protocol;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_authprot, ett_lcp_authprot_opt, 4,
+ &field_tree, &ti))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_auth_protocol, tvb, offset + 2,
+ 2, ENC_BIG_ENDIAN, &protocol);
+ proto_item_append_text(ti, ": %s (0x%02x)", val_to_str_ext_const(protocol, &ppp_vals_ext, "Unknown"),
+ protocol);
+
+ if (length > 4) {
+ offset += 4;
+ length -= 4;
+ if (protocol == PPP_CHAP) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_algorithm, tvb, offset,
+ 1, ENC_BIG_ENDIAN);
+ if (length > 1) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb,
+ offset + 1, length - 1, ENC_NA);
+ }
+ } else {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
+ length, ENC_NA);
+ }
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_qualprot_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *ti;
+ guint32 protocol;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_qualprot, ett_lcp_qualprot_opt, 4,
+ &field_tree, &ti))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_quality_protocol, tvb, offset + 2,
+ 2, ENC_BIG_ENDIAN, &protocol);
+ proto_item_append_text(ti, ": %s (0x%02x)", val_to_str_ext_const(protocol, &ppp_vals_ext, "Unknown"),
+ protocol);
+
+ if (length > 4) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset + 4,
+ length + 4, ENC_NA);
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_magicnumber_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *ti;
+ guint32 magic_number;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_magicnumber, ett_lcp_magicnumber_opt, 6,
+ &field_tree, &ti))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_magic_number, tvb, offset + 2,
+ 4, ENC_BIG_ENDIAN, &magic_number);
+ proto_item_append_text(ti, ": 0x%08x", magic_number);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_linkqualmon_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *ti, *tf;
+ guint32 reportingperiod;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_linkqualmon, ett_lcp_linkqualmon_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ ti = proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_reportingperiod,
+ tvb, offset + 2, 4, ENC_BIG_ENDIAN, &reportingperiod);
+ proto_item_append_text(tf, ": %u microsecond%s", reportingperiod, plurality(reportingperiod, "", "s"));
+ if (reportingperiod == 0)
+ {
+ proto_item_append_text(ti, " [illegal]");
+ proto_item_append_text(tf, " [illegal]");
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_field_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_field_compress, ett_lcp_pcomp_opt);
+}
+
+static int
+dissect_lcp_addr_field_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_addr_field_compress, ett_lcp_acccomp_opt);
+}
+
+static int
+dissect_lcp_fcs_alternatives_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ static int * const fcs_alternatives_fields[] = {
+ &hf_lcp_opt_fcs_alternatives_ccitt32,
+ &hf_lcp_opt_fcs_alternatives_ccitt16,
+ &hf_lcp_opt_fcs_alternatives_null,
+ NULL
+ };
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_fcs_alternatives, ett_lcp_fcs_alternatives_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_bitmask(field_tree, tvb, offset + 2,
+ hf_lcp_opt_fcs_alternatives, ett_lcp_fcs_alternatives_opt,
+ fcs_alternatives_fields, ENC_NA);
+ proto_item_append_text(tf, ": 0x%02x", tvb_get_guint8(tvb, offset + 2));
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_self_describing_pad_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf, *ti;
+ guint32 maximum;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_self_desc_pad, ett_lcp_self_desc_pad_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ ti = proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_maximum, tvb,
+ offset + 2, 1, ENC_BIG_ENDIAN, &maximum);
+ proto_item_append_text(tf, ": %u octet%s", maximum, plurality(maximum, "", "s"));
+ if (maximum == 0)
+ {
+ proto_item_append_text(ti, " [invalid]");
+ proto_item_append_text(tf, " [invalid]");
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_numbered_mode_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf, *ti;
+ guint32 window;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_numbered_mode, ett_lcp_numbered_mode_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ ti = proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_window, tvb,
+ offset + 2, 1, ENC_BIG_ENDIAN, &window);
+ proto_item_append_text(tf, ": %u frame%s", window, plurality(window, "", "s"));
+ if (window == 0 || window > 127)
+ {
+ proto_item_append_text(ti, " [invalid]");
+ proto_item_append_text(tf, " [invalid]");
+ }
+ if (length > 3) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_hdlc_address, tvb,
+ offset + 3, length - 3, ENC_NA);
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+/* https://tools.ietf.org/html/rfc1570#section-2.3 only lists 0-4, but
+ * https://tools.ietf.org/html/draft-ietf-pppext-callback-ds-02 lists 5 as
+ * "E.165 number", rather than "unassigned", and
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cbcp/efee6372-3251-471e-a141-71d1e7fef21f
+ * does indicate 6 as below. Since 5 is only mentioned in the draft, leave it
+ * as "unassigned"?
+ */
+static const value_string callback_op_vals[] = {
+ {0, "Location is determined by user authentication"},
+ {1, "Message is dialing string"},
+ {2, "Message is location identifier"},
+ {3, "Message is E.164"},
+ {4, "Message is distinguished name"},
+ {5, "unassigned"}, /* "Message is E.165"? */
+ {6, "Location is determined during CBCP negotiation"},
+ {0, NULL}
+};
+
+static int
+dissect_lcp_callback_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint32 operation;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_callback, ett_lcp_callback_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_operation, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN, &operation);
+ proto_item_append_text(tf, ": %s", val_to_str_const(operation, callback_op_vals, "Unknown"));
+
+ if (length > 3) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_message, tvb, offset + 3,
+ length - 3, ENC_NA);
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_compound_frames_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_compound_frames, ett_lcp_compound_frames_opt);
+}
+
+static int
+dissect_lcp_nomdataencap_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_nomdataencap, ett_lcp_nomdataencap_opt);
+}
+
+/* https://tools.ietf.org/html/rfc1990#section-5.1.1 */
+static int
+dissect_lcp_multilink_mrru_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint32 mrru;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_multilink_mrru, ett_lcp_multilink_mrru_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_mrru, tvb, offset + 2, 2,
+ ENC_BIG_ENDIAN, &mrru);
+ proto_item_append_text(tf, ": %u", mrru);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_multilink_ssnh_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_multilink_ssnh, ett_lcp_multilink_ssnh_opt);
+}
+
+#define CLASS_NULL 0
+#define CLASS_LOCAL 1
+#define CLASS_IP 2
+#define CLASS_IEEE_802_1 3
+#define CLASS_PPP_MAGIC_NUMBER 4
+#define CLASS_PSDN_DIRECTORY_NUMBER 5
+
+static const value_string multilink_ep_disc_class_vals[] = {
+ {CLASS_NULL, "Null"},
+ {CLASS_LOCAL, "Locally assigned address"},
+ {CLASS_IP, "Internet Protocol (IP) address"},
+ {CLASS_IEEE_802_1, "IEEE 802.1 globally assigned MAC address"},
+ {CLASS_PPP_MAGIC_NUMBER, "PPP magic-number block"},
+ {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number"},
+ {0, NULL}
+};
+
+static int
+dissect_lcp_multilink_ep_disc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree, *magic_tree;
+ proto_item *tf, *tm;
+ guint32 ep_disc_class;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_multilink_ep_disc, ett_lcp_multilink_ep_disc_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_ep_disc_class, tvb, offset + 2,
+ 1, ENC_BIG_ENDIAN, &ep_disc_class);
+ proto_item_append_text(tf, ": Class: %s", val_to_str_const(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"));
+
+ if (length <= 3)
+ return tvb_captured_length(tvb);
+
+ length -= 3;
+ offset += 3;
+ switch (ep_disc_class) {
+ case CLASS_NULL:
+ break;
+
+ case CLASS_LOCAL:
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
+ length <= 20 ? length : 20, ENC_NA);
+ break;
+
+ case CLASS_IP:
+ if (length >= 4) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_ip_address, tvb, offset,
+ 4, ENC_BIG_ENDIAN);
+ } else {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
+ length, ENC_NA);
+ }
+ break;
+
+ case CLASS_IEEE_802_1:
+ if (length >= 6) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_802_1_address, tvb,
+ offset, 6, ENC_NA);
+ } else {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
+ length, ENC_NA);
+ }
+ break;
+
+ case CLASS_PPP_MAGIC_NUMBER:
+ if (length % 4) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
+ length, ENC_NA);
+ } else {
+ tm = proto_tree_add_item(field_tree, hf_lcp_opt_magic_block, tvb,
+ offset, length <= 20 ? length : 20, ENC_NA);
+ magic_tree = proto_item_add_subtree(tm, ett_lcp_magic_block);
+ for ( ; length >= 4; length -= 4, offset += 4) {
+ proto_tree_add_item(magic_tree, hf_lcp_opt_magic_number, tvb,
+ offset, 4, ENC_BIG_ENDIAN);
+ }
+ }
+ break;
+
+ case CLASS_PSDN_DIRECTORY_NUMBER:
+ proto_tree_add_item(field_tree, hf_lcp_opt_psndn, tvb, offset,
+ length > 15 ? 15 : length, ENC_NA);
+ break;
+
+ default:
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset, length,
+ ENC_NA);
+ break;
+ }
+ return tvb_captured_length(tvb);
+}
+
+static const value_string dce_id_mode_vals[] = {
+ {1, "Mode-1 (No Additional Negotiation)"},
+ {2, "Mode-2 (Full PPP Negotiation and State Machine)"},
+ {0, NULL}
+};
+
+static int
+dissect_lcp_dce_identifier_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ guint32 mode;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_dce_identifier, ett_lcp_dce_identifier_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_mode, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN, &mode);
+ proto_item_append_text(tf, ": %s", val_to_str_const(mode, dce_id_mode_vals, "Unknown"));
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_multilink_pp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_multilink_pp, ett_lcp_multilink_pp_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_lcp_opt_unused, tvb, offset + 2, 2, ENC_NA);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_bacp_link_discriminator_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ guint32 link_discrim;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_link_discrim, ett_lcp_bacp_link_discrim_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(field_tree, hf_lcp_opt_link_discrim, tvb, offset + 2,
+ 2, ENC_BIG_ENDIAN, &link_discrim);
+ proto_item_append_text(tf, ": %u (0x%04x)", link_discrim, link_discrim);
+ return tvb_captured_length(tvb);
+}
+
+/* Assuming it's this one:
+ * https://tools.ietf.org/html/draft-ietf-pppext-link-negot-00
+ */
+static int
+dissect_lcp_auth_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint32 id_len;
+ int offset = 0;
+ int length;
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_auth, ett_lcp_auth_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ offset += 2;
+ proto_tree_add_item_ret_length(field_tree, hf_lcp_opt_id, tvb, offset, 1, ENC_BIG_ENDIAN, &id_len);
+
+ length = tvb_reported_length_remaining(tvb, offset);
+ if ((int)id_len < length) {
+ length -= id_len;
+ offset += id_len;
+ proto_tree_add_item(field_tree, hf_lcp_opt_data, tvb, offset,
+ length, ENC_NA);
+ }
+ return tvb_captured_length(tvb);
+}
+
+/* Assuming it's this one:
+ * https://tools.ietf.org/html/draft-ietf-pppext-cobs-00
+ */
+static int
+dissect_lcp_cobs_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ static int * const cobs_flags_fields[] = {
+ &hf_lcp_opt_cobs_flags_res,
+ &hf_lcp_opt_cobs_flags_pre,
+ &hf_lcp_opt_cobs_flags_zxe,
+ NULL
+ };
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_cobs, ett_lcp_cobs_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_bitmask(field_tree, tvb, offset + 2, hf_lcp_opt_cobs_flags,
+ ett_lcp_cobs_opt, cobs_flags_fields, ENC_NA);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_prefix_elision_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint8 pre_len;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_prefix_elision, ett_lcp_prefix_elision_opt, 2,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ if (length > 2) {
+ length -= 2;
+ offset += 2;
+ while (length >= 2) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_class, tvb, offset, 1,
+ ENC_BIG_ENDIAN);
+ pre_len = tvb_get_guint8(tvb, offset + 1);
+ if (pre_len + 2 <= length) {
+ proto_tree_add_item(field_tree, hf_lcp_opt_prefix, tvb,
+ offset + 2, 1, ENC_NA);
+ length -= (2 + pre_len);
+ } else {
+ /* Prefix length doesn't make sense, so bail out */
+ length = 0;
+ }
+ }
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static const value_string ml_hdr_fmt_code_vals[] = {
+ {2, "Long sequence number fragment format with classes"},
+ {6, "Short sequence number fragment format with classes"},
+ {0, NULL}
+};
+
+static int
+dissect_lcp_multilink_hdr_fmt_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_lcp_fixed_opt(tvb, pinfo, tree,
+ proto_lcp_option_multilink_hdr_fmt, ett_multilink_hdr_fmt_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_lcp_opt_code, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_lcp_opt_max_susp_classes, tvb,
+ offset + 3, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+
+/* Character sets from https://www.iana.org/assignments/character-sets. */
+static const value_string charset_vals[] = {
+ {3, "ANSI_X3.4-1968"},
+ {4, "ISO_8859-1:1987"},
+ {5, "ISO_8859-2:1987"},
+ {6, "ISO_8859-3:1988"},
+ {7, "ISO_8859-4:1988"},
+ {8, "ISO_8859-5:1988"},
+ {9, "ISO_8859-6:1987"},
+ {10, "ISO_8859-7:1987"},
+ {11, "ISO_8859-8:1988"},
+ {12, "ISO_8859-9:1989"},
+ {13, "ISO-8859-10"},
+ {14, "ISO_6937-2-add"},
+ {15, "JIS_X0201"},
+ {16, "JIS_Encoding"},
+ {17, "Shift_JIS"},
+ {18, "Extended_UNIX_Code_Packed_Format_for_Japanese"},
+ {19, "Extended_UNIX_Code_Fixed_Width_for_Japanese"},
+ {20, "BS_4730"},
+ {21, "SEN_850200_C"},
+ {22, "IT"},
+ {23, "ES"},
+ {24, "DIN_66003"},
+ {25, "NS_4551-1"},
+ {26, "NF_Z_62-010"},
+ {27, "ISO-10646-UTF-1"},
+ {28, "ISO_646.basic:1983"},
+ {29, "INVARIANT"},
+ {30, "ISO_646.irv:1983"},
+ {31, "NATS-SEFI"},
+ {32, "NATS-SEFI-ADD"},
+ {33, "NATS-DANO"},
+ {34, "NATS-DANO-ADD"},
+ {35, "SEN_850200_B"},
+ {36, "KS_C_5601-1987"},
+ {37, "ISO-2022-KR"},
+ {38, "EUC-KR"},
+ {39, "ISO-2022-JP"},
+ {40, "ISO-2022-JP-2"},
+ {41, "JIS_C6220-1969-jp"},
+ {42, "JIS_C6220-1969-ro"},
+ {43, "PT"},
+ {44, "greek7-old"},
+ {45, "latin-greek"},
+ {46, "NF_Z_62-010_(1973)"},
+ {47, "Latin-greek-1"},
+ {48, "ISO_5427"},
+ {49, "JIS_C6226-1978"},
+ {50, "BS_viewdata"},
+ {51, "INIS"},
+ {52, "INIS-8"},
+ {53, "INIS-cyrillic"},
+ {54, "ISO_5427:1981"},
+ {55, "ISO_5428:1980"},
+ {56, "GB_1988-80"},
+ {57, "GB_2312-80"},
+ {58, "NS_4551-2"},
+ {59, "videotex-suppl"},
+ {60, "PT2"},
+ {61, "ES2"},
+ {62, "MSZ_7795.3"},
+ {63, "JIS_C6226-1983"},
+ {64, "greek7"},
+ {65, "ASMO_449"},
+ {66, "iso-ir-90"},
+ {67, "JIS_C6229-1984-a"},
+ {68, "JIS_C6229-1984-b"},
+ {69, "JIS_C6229-1984-b-add"},
+ {70, "JIS_C6229-1984-hand"},
+ {71, "JIS_C6229-1984-hand-add"},
+ {72, "JIS_C6229-1984-kana"},
+ {73, "ISO_2033-1983"},
+ {74, "ANSI_X3.110-1983"},
+ {75, "T.61-7bit"},
+ {76, "T.61-8bit"},
+ {77, "ECMA-cyrillic"},
+ {78, "CSA_Z243.4-1985-1"},
+ {79, "CSA_Z243.4-1985-2"},
+ {80, "CSA_Z243.4-1985-gr"},
+ {81, "ISO_8859-6-E"},
+ {82, "ISO_8859-6-I"},
+ {83, "T.101-G2"},
+ {84, "ISO_8859-8-E"},
+ {85, "ISO_8859-8-I"},
+ {86, "CSN_369103"},
+ {87, "JUS_I.B1.002"},
+ {88, "IEC_P27-1"},
+ {89, "JUS_I.B1.003-serb"},
+ {90, "JUS_I.B1.003-mac"},
+ {91, "greek-ccitt"},
+ {92, "NC_NC00-10:81"},
+ {93, "ISO_6937-2-25"},
+ {94, "GOST_19768-74"},
+ {95, "ISO_8859-supp"},
+ {96, "ISO_10367-box"},
+ {97, "latin-lap"},
+ {98, "JIS_X0212-1990"},
+ {99, "DS_2089"},
+ {100, "us-dk"},
+ {101, "dk-us"},
+ {102, "KSC5636"},
+ {103, "UNICODE-1-1-UTF-7"},
+ {104, "ISO-2022-CN"},
+ {105, "ISO-2022-CN-EXT"},
+ {106, "UTF-8"},
+ {109, "ISO-8859-13"},
+ {110, "ISO-8859-14"},
+ {111, "ISO-8859-15"},
+ {112, "ISO-8859-16"},
+ {113, "GBK"},
+ {114, "GB18030"},
+ {115, "OSD_EBCDIC_DF04_15"},
+ {116, "OSD_EBCDIC_DF03_IRV"},
+ {117, "OSD_EBCDIC_DF04_1"},
+ {118, "ISO-11548-1"},
+ {119, "KZ-1048"},
+ {1000, "ISO-10646-UCS-2"},
+ {1001, "ISO-10646-UCS-4"},
+ {1002, "ISO-10646-UCS-Basic"},
+ {1003, "ISO-10646-Unicode-Latin1"},
+ {1004, "ISO-10646-J-1"},
+ {1005, "ISO-Unicode-IBM-1261"},
+ {1006, "ISO-Unicode-IBM-1268"},
+ {1007, "ISO-Unicode-IBM-1276"},
+ {1008, "ISO-Unicode-IBM-1264"},
+ {1009, "ISO-Unicode-IBM-1265"},
+ {1010, "UNICODE-1-1"},
+ {1011, "SCSU"},
+ {1012, "UTF-7"},
+ {1013, "UTF-16BE"},
+ {1014, "UTF-16LE"},
+ {1015, "UTF-16"},
+ {1016, "CESU-8"},
+ {1017, "UTF-32"},
+ {1018, "UTF-32BE"},
+ {1019, "UTF-32LE"},
+ {1020, "BOCU-1"},
+ {2000, "ISO-8859-1-Windows-3.0-Latin-1"},
+ {2001, "ISO-8859-1-Windows-3.1-Latin-1"},
+ {2002, "ISO-8859-2-Windows-Latin-2"},
+ {2003, "ISO-8859-9-Windows-Latin-5"},
+ {2004, "hp-roman8"},
+ {2005, "Adobe-Standard-Encoding"},
+ {2006, "Ventura-US"},
+ {2007, "Ventura-International"},
+ {2008, "DEC-MCS"},
+ {2009, "IBM850"},
+ {2010, "IBM852"},
+ {2011, "IBM437"},
+ {2012, "PC8-Danish-Norwegian"},
+ {2013, "IBM862"},
+ {2014, "PC8-Turkish"},
+ {2015, "IBM-Symbols"},
+ {2016, "IBM-Thai"},
+ {2017, "HP-Legal"},
+ {2018, "HP-Pi-font"},
+ {2019, "HP-Math8"},
+ {2020, "Adobe-Symbol-Encoding"},
+ {2021, "HP-DeskTop"},
+ {2022, "Ventura-Math"},
+ {2023, "Microsoft-Publishing"},
+ {2024, "Windows-31J"},
+ {2025, "GB2312"},
+ {2026, "Big5"},
+ {2027, "macintosh"},
+ {2028, "IBM037"},
+ {2029, "IBM038"},
+ {2030, "IBM273"},
+ {2031, "IBM274"},
+ {2032, "IBM275"},
+ {2033, "IBM277"},
+ {2034, "IBM278"},
+ {2035, "IBM280"},
+ {2036, "IBM281"},
+ {2037, "IBM284"},
+ {2038, "IBM285"},
+ {2039, "IBM290"},
+ {2040, "IBM297"},
+ {2041, "IBM420"},
+ {2042, "IBM423"},
+ {2043, "IBM424"},
+ {2044, "IBM500"},
+ {2045, "IBM851"},
+ {2046, "IBM855"},
+ {2047, "IBM857"},
+ {2048, "IBM860"},
+ {2049, "IBM861"},
+ {2050, "IBM863"},
+ {2051, "IBM864"},
+ {2052, "IBM865"},
+ {2053, "IBM868"},
+ {2054, "IBM869"},
+ {2055, "IBM870"},
+ {2056, "IBM871"},
+ {2057, "IBM880"},
+ {2058, "IBM891"},
+ {2059, "IBM903"},
+ {2060, "IBM904"},
+ {2061, "IBM905"},
+ {2062, "IBM918"},
+ {2063, "IBM1026"},
+ {2064, "EBCDIC-AT-DE"},
+ {2065, "EBCDIC-AT-DE-A"},
+ {2066, "EBCDIC-CA-FR"},
+ {2067, "EBCDIC-DK-NO"},
+ {2068, "EBCDIC-DK-NO-A"},
+ {2069, "EBCDIC-FI-SE"},
+ {2070, "EBCDIC-FI-SE-A"},
+ {2071, "EBCDIC-FR"},
+ {2072, "EBCDIC-IT"},
+ {2073, "EBCDIC-PT"},
+ {2074, "EBCDIC-ES"},
+ {2075, "EBCDIC-ES-A"},
+ {2076, "EBCDIC-ES-S"},
+ {2077, "EBCDIC-UK"},
+ {2078, "EBCDIC-US"},
+ {2079, "UNKNOWN-8BIT"},
+ {2080, "MNEMONIC"},
+ {2081, "MNEM"},
+ {2082, "VISCII"},
+ {2083, "VIQR"},
+ {2084, "KOI8-R"},
+ {2085, "HZ-GB-2312"},
+ {2086, "IBM866"},
+ {2087, "IBM775"},
+ {2088, "KOI8-U"},
+ {2089, "IBM00858"},
+ {2090, "IBM00924"},
+ {2091, "IBM01140"},
+ {2092, "IBM01141"},
+ {2093, "IBM01142"},
+ {2094, "IBM01143"},
+ {2095, "IBM01144"},
+ {2096, "IBM01145"},
+ {2097, "IBM01146"},
+ {2098, "IBM01147"},
+ {2099, "IBM01148"},
+ {2100, "IBM01149"},
+ {2101, "Big5-HKSCS"},
+ {2102, "IBM1047"},
+ {2103, "PTCP154"},
+ {2104, "Amiga-1251"},
+ {2105, "KOI7-switched"},
+ {2106, "BRF"},
+ {2107, "TSCII"},
+ {2108, "CP51932"},
+ {2109, "windows-874"},
+ {2250, "windows-1250"},
+ {2251, "windows-1251"},
+ {2252, "windows-1252"},
+ {2253, "windows-1253"},
+ {2254, "windows-1254"},
+ {2255, "windows-1255"},
+ {2256, "windows-1256"},
+ {2257, "windows-1257"},
+ {2258, "windows-1258"},
+ {2259, "TIS-620"},
+ {2260, "CP50220"},
+ {0, NULL}
+};
+static value_string_ext charset_vals_ext = VALUE_STRING_EXT_INIT(charset_vals);
+
+static int
+dissect_lcp_internationalization_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_lcp_var_opt(tvb, pinfo, tree, proto_lcp_option_internationalization, ett_lcp_internationalization_opt, 7,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_lcp_opt_MIBenum, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_lcp_opt_language_tag, tvb, offset + 6,
+ length - 6, ENC_ASCII);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_lcp_sonet_sdh_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_lcp_simple_opt(tvb, pinfo, tree, proto_lcp_option_sonet_sdh, ett_lcp_sonet_sdh_opt);
+}
+
+static void
+dissect_ipcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_ipcp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_ipcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_ipcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_ipcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+/* https://tools.ietf.org/html/rfc1172#section-5.1 */
+static int
+dissect_ipcp_addrs_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_addrs , ett_ipcp_ipaddrs_opt, 10,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_src_address, tvb, offset + 2,
+ 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ipcp_opt_dst_address, tvb, offset + 6,
+ 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static const true_false_string tfs_comp_slot_id = {
+ "The slot identifier may be compressed",
+ "The slot identifier must not be compressed"
+};
+
+/* https://tools.ietf.org/html/rfc1332#section-3.2 */
+static int
+dissect_ipcp_compress_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+ guint16 us;
+
+ tf = proto_tree_add_item(tree, proto_ipcp_option_compress, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_ipcp_compress_opt);
+
+ dissect_ipcp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_ipcp_option_compress));
+ proto_tree_add_item(field_tree, hf_ipcp_opt_compress_proto, tvb,
+ offset + 2, 2, ENC_BIG_ENDIAN);
+ us = tvb_get_ntohs(tvb, offset + 2);
+ switch (us) {
+ case IPCP_ROHC:
+ proto_tree_add_item(field_tree, hf_ipcp_opt_max_cid, tvb, offset + 4,
+ 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ipcp_opt_mrru, tvb, offset + 6, 2,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ipcp_opt_max_header, tvb,
+ offset + 8, 2, ENC_BIG_ENDIAN);
+
+ if (length > 10) {
+ proto_tree *subopt_tree;
+
+ /* suboptions */
+ offset += 10;
+ length -= 10;
+ subopt_tree = proto_tree_add_subtree_format(field_tree, tvb, offset, length,
+ ett_ipcp_compress_opt, NULL, "Suboptions: (%u byte%s)", length, plurality(length, "", "s"));
+
+ ppp_dissect_options(tvb, offset, length, ipcp_rohc_suboption_table, pinfo, subopt_tree);
+ }
+ break;
+
+ case IPCP_COMPRESS_VJ_1172:
+ case IPCP_COMPRESS_VJ:
+ proto_tree_add_item(field_tree, hf_ipcp_opt_max_slot_id, tvb,
+ offset + 4, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ipcp_opt_comp_slot_id, tvb,
+ offset + 5, 1, ENC_NA);
+ break;
+
+ case IPCP_COMPRESS_IPHC:
+ proto_tree_add_item(field_tree, hf_ipcp_opt_tcp_space, tvb, offset + 4,
+ 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ipcp_opt_non_tcp_space, tvb,
+ offset + 6, 2, ENC_BIG_ENDIAN);
+ us = tvb_get_ntohs(tvb, offset + 8);
+ proto_tree_add_uint_format_value(field_tree, hf_ipcp_opt_f_max_period,
+ tvb, offset + 8, 2, us, "%u%s", us,
+ (us == 0) ? " (infinity)" : "");
+ us = tvb_get_ntohs(tvb, offset + 10);
+ proto_tree_add_uint_format_value(field_tree, hf_ipcp_opt_f_max_time,
+ tvb, offset + 10, 2, us, "%u%s", us,
+ (us == 0) ? " (infinity)" : "");
+ proto_tree_add_item(field_tree, hf_ipcp_opt_max_header, tvb,
+ offset + 12, 2, ENC_BIG_ENDIAN);
+
+ if ( length > 14 ) {
+ proto_tree *subopt_tree;
+
+ /* suboptions */
+ offset += 14;
+ length -= 14;
+ subopt_tree = proto_tree_add_subtree_format(field_tree, tvb, offset, length,
+ ett_ipcp_compress_opt, NULL, "Suboptions: (%u byte%s)", length, plurality(length, "", "s"));
+ ppp_dissect_options(tvb, offset, length, ipcp_iphc_suboption_table, pinfo, subopt_tree);
+ }
+ break;
+
+ default:
+ if (length > 4) {
+ proto_tree_add_item(field_tree, hf_ipcp_data, tvb, offset + 4,
+ length - 4, ENC_NA);
+ }
+ break;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_ipcp_opt_rohc_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_ipcp_opt_rohc_type, tvb, offset,
+ 1, type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_ipcp_opt_rohc_length, tvb, offset + 1, 1,
+ ENC_BIG_ENDIAN);
+}
+
+static int
+dissect_ipcp_rohc_profiles_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int length = tvb_reported_length(tvb);
+ int offset = 0;
+
+ tf = proto_tree_add_item(tree, proto_ipcp_rohc_option_profiles, tvb, offset, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_ipcp_rohc_profiles_opt);
+
+ dissect_ipcp_opt_rohc_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_ipcp_rohc_option_profiles));
+ if (length <= 2)
+ return tvb_captured_length(tvb);
+
+ for (offset += 2, length -= 2; length >= 2; length -= 2, offset += 2) {
+ proto_tree_add_item(field_tree, hf_ipcp_opt_rohc_profile, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ }
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_ipcp_opt_iphc_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_ipcp_opt_iphc_type, tvb, offset,
+ 1, type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_ipcp_opt_iphc_length, tvb, offset + 1, 1,
+ ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_ipcp_iphc_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_ipcp_opt_iphc_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_ipcp_iphc_rtp_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+
+ dissect_ipcp_iphc_fixed_opt(tvb, pinfo, tree, proto_ipcp_iphc_option_rtp_compress, ett_ipcp_iphc_rtp_compress_opt, 2,
+ &field_tree, &tf);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_iphc_enhanced_rtp_compress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+
+ dissect_ipcp_iphc_fixed_opt(tvb, pinfo, tree, proto_ipcp_iphc_option_enhanced_rtp_compress, ett_ipcp_iphc_enhanced_rtp_compress_opt, 2,
+ &field_tree, &tf);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_iphc_neghdrcomp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_iphc_fixed_opt(tvb, pinfo, tree, proto_ipcp_iphc_option_neghdrcomp, ett_ipcp_iphc_neghdrcomp_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_iphc_param, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_addr_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_addr, ett_ipcp_ipaddr_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_ip_address, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_mobileipv4_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_mobileipv4, ett_ipcp_mobileipv4_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_mobilenodehomeaddr, tvb,
+ offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_pri_dns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_pri_dns, ett_ipcp_pridns_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_pri_dns_address, tvb,
+ offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_pri_nbns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_pri_nbns, ett_ipcp_prinbns_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_pri_nbns_address, tvb,
+ offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_sec_dns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_sec_dns, ett_ipcp_secdns_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_sec_dns_address, tvb,
+ offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_ipcp_sec_nbns_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ipcp_fixed_opt(tvb, pinfo, tree, proto_ipcp_option_sec_nbns, ett_ipcp_secnbns_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipcp_opt_sec_nbns_address, tvb,
+ offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_bcp_ncp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_bcp_ncp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ offset++;
+ proto_tree_add_item(tree, hf_bcp_ncp_opt_length, tvb, offset, 1,
+ ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_bcp_ncp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_bcp_ncp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+/*
+0 1 2 3
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length | LAN Segment Number |Bridge#|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+static int
+dissect_bcp_ncp_bridge_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_bridge_id, ett_bcp_ncp_bridge_id_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bcp_ncp_lan_seg_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_bcp_ncp_bridge_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
+
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1 2 3
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length | LAN Segment Number |Bridge#|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+static int
+dissect_bcp_ncp_line_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_line_id, ett_bcp_ncp_line_id_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bcp_ncp_lan_seg_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_bcp_ncp_bridge_no, tvb, offset+2, 2, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1 2
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length | MAC Type |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+MAC Type
+0: reserved
+1: IEEE 802.3/Ethernet with canonical addresses
+2: IEEE 802.4 with canonical addresses
+3: IEEE 802.5 with non-canonical addresses
+4: FDDI with non-canonical addresses
+5-10: reserved
+11: IEEE 802.5 with canonical addresses
+12: FDDI with canonical addresses
+
+*/
+static int
+dissect_bcp_ncp_mac_sup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_mac_sup, ett_bcp_ncp_mac_sup_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bcp_bpdu_mac_type, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1 2
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length | Enable/Disable|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+static int
+dissect_bcp_ncp_tinygram_comp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_tinygram_comp, ett_bcp_ncp_tinygram_comp_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bcp_ncp_tinygram_comp, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bcp_ncp_lan_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+
+ dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_lan_id, ett_bcp_ncp_lan_id_opt, 3,
+ &field_tree, &tf);
+ /* XXX - missing a field? */
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1 2 3
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length |MAC byte 1 |L|M| MAC byte 2 |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| MAC byte 3 | MAC byte 4 | MAC byte 5 | MAC byte 6 |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+static int
+dissect_bcp_ncp_mac_addr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_mac_addr, ett_bcp_ncp_mac_addr_opt, 8,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bcp_ncp_mac, tvb, offset+2, 6, ENC_NA);
+ proto_tree_add_item(field_tree, hf_bcp_ncp_mac_l, tvb, offset+2, 6, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_bcp_ncp_mac_m, tvb, offset+2, 6, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1 2 3
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+| Type | Length | Protocol 1 | Protocol 2 | ..
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+
+*/
+
+static const value_string bcp_ncp_stp_prot_vals[] = {
+ { 0, "Null (no Spanning Tree protocol supported)" },
+ { 1, "IEEE 802.1D spanning tree" },
+ { 2, "IEEE 802.1G extended spanning tree protocol" },
+ { 3, "IBM Source Route Spanning tree protocol" },
+ { 4, "DEC LANbridge 100 Spanning tree protocol" },
+ { 0, NULL }
+};
+
+static int
+dissect_bcp_ncp_stp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ tf = proto_tree_add_item(tree, proto_bcp_ncp_option_stp, tvb, offset, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_bcp_ncp_stp_opt);
+
+ dissect_bcp_ncp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_bcp_ncp_option_stp));
+ offset += 2;
+ length -= 2;
+
+ while (length != 0) {
+ proto_tree_add_item(field_tree, hf_bcp_ncp_stp_prot, tvb, offset, 1, ENC_BIG_ENDIAN);
+ length--;
+ offset++;
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1 2
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length | Enable/Disable|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+static int
+dissect_bcp_ncp_ieee_802_tagged_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_ieee_802_tagged_frame,
+ ett_bcp_ncp_ieee_802_tagged_frame_opt, 3, &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bcp_ncp_ieee_802_tagged_frame, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+static int
+dissect_bcp_ncp_management_inline(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+
+ dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_management_inline, ett_bcp_ncp_management_inline_opt, 3,
+ &field_tree, &tf);
+ return tvb_captured_length(tvb);
+}
+
+/*
+0 1
+0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Type | Length |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+static int
+dissect_bcp_ncp_bcp_ncp_bcp_ind(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+
+ dissect_bcp_ncp_fixed_opt(tvb, pinfo, tree, proto_bcp_ncp_option_bcp_ind, ett_bcp_ncp_bcp_ind_opt, 3,
+ &field_tree, &tf);
+ return tvb_captured_length(tvb);
+}
+
+
+static void
+dissect_osinlcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_osinlcp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_osinlcp_opt_length, tvb, offset + 1, 1,
+ ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_osinlcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_osinlcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_osinlcp_align_npdu_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_osinlcp_fixed_opt(tvb, pinfo, tree, proto_osinlcp_option_align_npdu, ett_osinlcp_align_npdu_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_osinlcp_opt_alignment, tvb, offset + 2,
+ 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_pppmuxcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_pppmuxcp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_pppmuxcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_pppmuxcp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_pppmuxcp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_pppmuxcp_def_pid_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_pppmuxcp_fixed_opt(tvb, pinfo, tree, proto_pppmuxcp_option_def_pid, ett_pppmuxcp_def_pid_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item_ret_uint(tree, hf_pppmux_def_prot_id, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &pppmux_def_prot_id);
+ return tvb_captured_length(tvb);
+}
+
+
+static void
+dissect_ccp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_ccp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_ccp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_ccp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_ccp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static gboolean
+dissect_ccp_var_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ int len = tvb_reported_length(tvb);
+
+ if (len < expected_length) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto)),
+ len, plurality(len, "", "s"), expected_length);
+ return FALSE;
+ }
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, -1, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_ccp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+
+/* https://tools.ietf.org/html/rfc1962 */
+static int dissect_ccp_oui_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_ccp_var_opt(tvb, pinfo, tree, proto_ccp_option_oui, ett_ccp_oui_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_oui, tvb, offset + 2, 3, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_subtype, tvb, offset + 5, 1,
+ ENC_BIG_ENDIAN);
+ if (length > 6) {
+ proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 6,
+ length - 6, ENC_NA);
+ }
+ return tvb_captured_length(tvb);
+}
+
+/* The following configuration option types are mentioned at
+ * https://www.iana.org/assignments/ppp-numbers/ppp-numbers.xhtml as referencing RFC1962; however,
+ * RFC1962 only mentions Proprietary Compression OUI in section 4.1. These
+ * others are therefore being treated as section 4.2 "Other Compression Types",
+ * in terms of how they are dissected:
+ * 1) Predictor type 1
+ * 2) Predictor type 2
+ * 3) Puddle Jumper
+ * 16) Hewlett-Packard PPC
+ * 20) V.42bis compression
+ */
+static int dissect_ccp_other_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int proto, int ett)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ tf = proto_tree_add_item(tree, proto, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett);
+
+ dissect_ccp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto));
+
+ if (length > 2) {
+ proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 2,
+ length - 2, ENC_NA);
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int dissect_ccp_predict1_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_predict1, ett_ccp_predict1_opt);
+}
+
+static int dissect_ccp_predict2_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_predict2, ett_ccp_predict2_opt);
+}
+
+static int dissect_ccp_puddle_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_puddle, ett_ccp_puddle_opt);
+}
+
+static int dissect_ccp_hpppc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_hpppc, ett_ccp_hpppc_opt);
+}
+
+/* https://tools.ietf.org/html/rfc1974 */
+static int
+dissect_ccp_stac_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+ static int * const check_mode_fields[] = {
+ &hf_ccp_opt_cm_reserved,
+ &hf_ccp_opt_cm_check_mode,
+ NULL
+ };
+
+ /* In RFC 1974, this is a fixed-length field of size 5, but in
+ * Ascend Proprietary STAC compression this field is 6 octets. */
+
+ if (!dissect_ccp_var_opt(tvb, pinfo, tree,
+ (length == 6) ? proto_ccp_option_stac_ascend : proto_ccp_option_stac,
+ ett_ccp_stac_opt, 5, &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+
+ if (length == 6) {
+ /* We don't know how to decode the following 4 octets, since
+ there are no public documents that describe their usage. */
+ proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 2,
+ length - 2, ENC_NA);
+ } else {
+ proto_tree_add_item(field_tree, hf_ccp_opt_history_count, tvb,
+ offset + 2, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_bitmask(field_tree, tvb, offset + 4, hf_ccp_opt_cm,
+ ett_ccp_stac_opt_check_mode, check_mode_fields, ENC_NA);
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * Microsoft Point-To-Point Compression (MPPC) and Encryption (MPPE)
+ * supported bits.
+ */
+#define MPPC_SUPPORTED_BITS_C 0x00000001 /* MPPC negotiation */
+#define MPPE_SUPPORTED_BITS_D 0x00000010 /* Obsolete */
+#define MPPE_SUPPORTED_BITS_L 0x00000020 /* 40-bit encryption */
+#define MPPE_SUPPORTED_BITS_S 0x00000040 /* 128-bit encryption */
+#define MPPE_SUPPORTED_BITS_M 0x00000080 /* 56-bit encryption */
+#define MPPE_SUPPORTED_BITS_H 0x01000000 /* stateless mode */
+
+static const true_false_string ccp_mppe_h_tfs = {
+ "Stateless mode ON",
+ "Stateless mode OFF"
+};
+static const true_false_string ccp_mppe_m_tfs = {
+ "56-bit encryption ON",
+ "56-bit encryption OFF"
+};
+static const true_false_string ccp_mppe_s_tfs = {
+ "128-bit encryption ON",
+ "128-bit encryption OFF"
+};
+static const true_false_string ccp_mppe_l_tfs = {
+ "40-bit encryption ON",
+ "40-bit encryption OFF"
+};
+static const true_false_string ccp_mppe_d_tfs = {
+ "Obsolete (should NOT be 1)",
+ "Obsolete (should ALWAYS be 0)"
+};
+static const true_false_string ccp_mppe_c_tfs = {
+ "Desire to negotiate MPPC",
+ "No desire to negotiate MPPC"
+};
+
+/* https://tools.ietf.org/html/rfc2118,
+ * https://tools.ietf.org/html/rfc3078 */
+static int
+dissect_ccp_mppe_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ static int * const supported_bits_fields[] = {
+ &hf_ccp_opt_supported_bits_h,
+ &hf_ccp_opt_supported_bits_m,
+ &hf_ccp_opt_supported_bits_s,
+ &hf_ccp_opt_supported_bits_l,
+ &hf_ccp_opt_supported_bits_d,
+ &hf_ccp_opt_supported_bits_c,
+ NULL
+ };
+
+ if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_mppe, ett_ccp_mppe_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_bitmask(field_tree, tvb, offset + 2,
+ hf_ccp_opt_supported_bits, ett_ccp_mppe_opt_supp_bits,
+ supported_bits_fields, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/* https://tools.ietf.org/html/rfc1993 */
+static int dissect_ccp_gfza_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_ccp_var_opt(tvb, pinfo, tree, proto_ccp_option_gfza, ett_ccp_gfza_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_history, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN);
+
+ if (length > 3) {
+ proto_tree_add_item(field_tree, hf_ccp_opt_version, tvb, offset + 3,
+ length - 3, ENC_NA);
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int dissect_ccp_v42bis_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_ccp_other_opt(tvb, pinfo, tree, proto_ccp_option_v42bis, ett_ccp_v42bis_opt);
+}
+
+/* https://tools.ietf.org/html/rfc1977 */
+static int
+dissect_ccp_bsdcomp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ static int * const vd_fields[] = {
+ &hf_ccp_opt_vd_vers,
+ &hf_ccp_opt_vd_dict,
+ NULL
+ };
+
+ if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_bsdcomp, ett_ccp_bsdcomp_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_bitmask(field_tree, tvb, offset + 2, hf_ccp_opt_vd,
+ ett_ccp_bsdcomp_opt, vd_fields, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/* https://tools.ietf.org/html/rfc1967 */
+static int
+dissect_ccp_lzsdcp_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_lzsdcp, ett_ccp_lzsdcp_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_history_count, tvb,
+ offset + 2, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ccp_opt_check_mode, tvb, offset + 4, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ccp_opt_process_mode, tvb, offset + 5,
+ 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/* https://tools.ietf.org/html/rfc1975 */
+static int
+dissect_ccp_mvrca_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_mvrca, ett_ccp_mvrca_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_fe, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ccp_opt_p, tvb, offset + 2, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_ccp_opt_History, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ccp_opt_contexts, tvb, offset + 3, 1,
+ ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+/* https://tools.ietf.org/html/rfc1976 */
+static int
+dissect_ccp_dce_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_dce, ett_ccp_dce_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_mode, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static const value_string deflate_method_vals[] = {
+ {8, "zlib compression"},
+ {0, NULL}
+};
+
+static const value_string deflate_chk_vals[] = {
+ {0, "sequence number check method"},
+ {0, NULL}
+};
+
+/* https://tools.ietf.org/html/rfc1979 */
+static int
+dissect_ccp_deflate_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ guint8 window;
+
+ /* RFC1979 says the length is 3 but it's actually 4. */
+ if (!dissect_ccp_fixed_opt(tvb, pinfo, tree, proto_ccp_option_deflate, ett_ccp_deflate_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ window = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_uint_format_value(field_tree, hf_ccp_opt_window, tvb,
+ offset + 2, 1, window, "%u", 1 << (hi_nibble(window) + 8));
+ proto_tree_add_item(field_tree, hf_ccp_opt_method, tvb, offset + 2, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ccp_opt_mbz, tvb, offset + 3, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_ccp_opt_chk, tvb, offset + 3, 1,
+ ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static const range_string v44lzjh_mode_dict_rvals[] = {
+ {0, 0, "Datagram Mode (one dictionary and no history)"},
+ {1, 1, "Multi-Datagram Mode (one dictionary with history)"},
+ {2, G_MAXUINT16, "Individual Link Mode" /* "(and proposed number of
+ dictionaries each with a
+ corresponding history" */},
+ {0, 0, NULL}
+};
+
+/* https://tools.ietf.org/html/draft-heath-ppp-v44-01 */
+static int dissect_ccp_v44lzjh_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_ccp_var_opt(tvb, pinfo, tree, proto_ccp_option_v44lzjh, ett_ccp_v44lzjh_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ccp_opt_mode_dictcount, tvb, offset + 2,
+ 2, ENC_BIG_ENDIAN);
+
+ if (length > 4) {
+ proto_tree_add_item(field_tree, hf_ccp_opt_dict_size, tvb, offset + 4,
+ 2, ENC_BIG_ENDIAN);
+ if (length > 6) {
+ proto_tree_add_item(field_tree, hf_ccp_opt_history_length, tvb,
+ offset + 6, 2, ENC_BIG_ENDIAN);
+ }
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_cbcp_callback_opt_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int length)
+{
+ proto_tree *addr_tree;
+ proto_item *ti;
+ guint8 addr_type;
+ guint addr_len;
+
+ proto_tree_add_item(tree, hf_cbcp_callback_delay, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
+ offset += 3;
+ length -= 3;
+
+ while (length > 0) {
+ addr_tree = proto_tree_add_subtree(tree, tvb, offset, length,
+ ett_cbcp_callback_opt_addr, NULL, "Callback Address");
+ addr_type = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_uint_format_value(addr_tree, hf_cbcp_address_type, tvb, offset, 1, addr_type,
+ "%s (%u)", ((addr_type == 1) ? "PSTN/ISDN" : "Other"), addr_type);
+ offset++;
+ length--;
+ addr_len = tvb_strsize(tvb, offset);
+ if (addr_len > (guint)length) {
+ expert_add_info(pinfo, ti, &ei_cbcp_address);
+ break;
+ }
+ proto_tree_add_item(addr_tree, hf_cbcp_address, tvb, offset, addr_len, ENC_NA|ENC_ASCII);
+ offset += addr_len;
+ length -= addr_len;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_cbcp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_cbcp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_cbcp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static int
+dissect_cbcp_no_callback_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ tf = proto_tree_add_item(tree, proto_cbcp_option_no_callback, tvb, offset, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_cbcp_no_callback);
+
+ dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_no_callback));
+ proto_tree_add_item(field_tree, hf_cbcp_no_callback, tvb, offset+2, length-2, ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_cbcp_callback_user_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (length < 4) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto_cbcp_option_callback_user)),
+ length, plurality(length, "", "s"), 4);
+ return tvb_captured_length(tvb);
+ }
+
+ tf = proto_tree_add_item(tree, proto_cbcp_option_callback_user, tvb, offset, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_cbcp_callback_user);
+
+ dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_callback_user));
+
+ return dissect_cbcp_callback_opt_common(tvb, pinfo, tree, 0, tvb_reported_length(tvb));
+}
+
+static int
+dissect_cbcp_callback_admin_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto_cbcp_option_callback_admin, tvb_reported_length(tvb), 4))
+ return tvb_captured_length(tvb);
+
+ tf = proto_tree_add_item(tree, proto_cbcp_option_callback_admin, tvb, offset, -1, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_cbcp_callback_admin);
+
+ dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_callback_admin));
+
+ return dissect_cbcp_callback_opt_common(tvb, pinfo, tree, 0, tvb_reported_length(tvb));
+}
+
+static int
+dissect_cbcp_callback_list_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (length < 4) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto_cbcp_option_callback_list)),
+ length, plurality(length, "", "s"), 4);
+ return tvb_captured_length(tvb);
+ }
+
+ tf = proto_tree_add_item(tree, proto_cbcp_option_callback_list, tvb, offset, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_cbcp_callback_list);
+
+ dissect_cbcp_opt_type_len(tvb, offset, field_tree, proto_registrar_get_name(proto_cbcp_option_callback_list));
+
+ return dissect_cbcp_callback_opt_common(tvb, pinfo, tree, 0, tvb_reported_length(tvb));
+}
+
+static void
+dissect_bacp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_bacp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_bacp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_bacp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_bacp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_bacp_favored_peer_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bacp_fixed_opt(tvb, pinfo, tree, proto_bacp_option_favored_peer, ett_bacp_favored_peer_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bacp_magic_number, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_bap_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_bap_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_bap_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_bap_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_bap_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static gboolean
+dissect_bap_var_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ int len = tvb_reported_length(tvb);
+
+ if (len < expected_length) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, len,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto)),
+ len, plurality(len, "", "s"), expected_length);
+ return FALSE;
+ }
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, -1, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_bap_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_bap_link_type_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_link_type, ett_bap_link_type_opt, 5,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bacp_link_speed, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_bacp_link_type, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bap_phone_delta_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_tree *suboption_tree;
+ proto_item *tf, *ti;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+ guint8 subopt_type;
+ guint8 subopt_len;
+
+ if (!dissect_bap_var_opt(tvb, pinfo, tree, proto_bap_option_phone_delta, ett_bap_phone_delta_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ offset += 2;
+ length -= 2;
+
+ while (length > 0) {
+ subopt_type = tvb_get_guint8(tvb, offset);
+ subopt_len = tvb_get_guint8(tvb, offset + 1);
+ suboption_tree = proto_tree_add_subtree_format(field_tree, tvb, offset, subopt_len,
+ ett_bap_phone_delta_subopt, NULL, "Sub-Option (%u byte%s)", subopt_len,
+ plurality(subopt_len, "", "s"));
+
+ proto_tree_add_item(suboption_tree, hf_bap_sub_option_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ ti = proto_tree_add_item(suboption_tree, hf_bap_sub_option_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+
+ if (subopt_len < 2) {
+ expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
+ "Sub-Option Length invalid, must be >= 2");
+ break;
+ }
+ if (subopt_len > length) {
+ expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
+ "Sub-Option Length invalid, must be <= length remaining in option %u)", length);
+ break;
+ }
+
+ switch (subopt_type) {
+ case BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT:
+ if (subopt_len == 3) {
+ proto_tree_add_item(suboption_tree, hf_bap_unique_digit, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
+ } else {
+ expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
+ "Invalid suboption length: %u (must be == 3)", subopt_len);
+ }
+ break;
+ case BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM:
+ if (subopt_len > 2) {
+ proto_tree_add_item(suboption_tree, hf_bap_subscriber_number, tvb, offset + 2, subopt_len - 2, ENC_NA|ENC_ASCII);
+ } else {
+ expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
+ "Invalid suboption length: %u (must be > 2)", subopt_len);
+ }
+ break;
+ case BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR:
+ if (subopt_len > 2) {
+ proto_tree_add_item(suboption_tree, hf_bap_phone_number_sub_address, tvb, offset + 2, subopt_len - 2, ENC_NA|ENC_ASCII);
+ } else {
+ expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
+ "Invalid suboption length: %u (must be > 2)", subopt_len);
+ }
+ break;
+ default:
+ if (subopt_len > 2) {
+ proto_tree_add_item(suboption_tree, hf_bap_unknown_option_data, tvb, offset + 2, subopt_len - 2, ENC_NA);
+ } else {
+ expert_add_info_format(pinfo, ti, &ei_bap_sub_option_length,
+ "Invalid suboption length: %u (must be > 2)", subopt_len);
+ }
+ break;
+ }
+ offset += subopt_len;
+ length -= subopt_len;
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bap_no_phone_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+
+ dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_no_phone, ett_bap_no_phone_opt, 2,
+ &field_tree, &tf);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bap_reason_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (!dissect_bap_var_opt(tvb, pinfo, tree, proto_bap_option_reason, ett_bap_reason_opt, 2,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bap_reason, tvb, offset+2, length-2, ENC_NA|ENC_ASCII);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bap_link_disc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_link_disc, ett_bap_link_disc_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bap_link_discriminator, tvb, offset+2, 2, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bap_call_status_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_bap_fixed_opt(tvb, pinfo, tree, proto_bap_option_call_status, ett_bap_call_status_opt, 4,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_bap_call_status, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_bap_call_action, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_vsncp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_vsncp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_vsncp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_vsncp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_vsncp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_vsncp_pdnid_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
+ proto_vsncp_option_pdnid, ett_vsncp_pdnid_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_vsncp_pdn_identifier, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static const value_string vsncp_attach_vals[] = {
+ {1, "Initial Attach"},
+ {3, "Handover Attach"},
+ {0, NULL}
+};
+
+static int
+dissect_vsncp_attachtype_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
+ proto_vsncp_option_attachtype, ett_vsncp_attachtype_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_vsncp_attach_type, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static const value_string vsncp_pdntype_vals[] = {
+ {0, "Initial Request by UE"},
+ {1, "IPv4"},
+ {2, "IPv6"},
+ {3, "IPv6/IPv4"},
+ {0, NULL}
+};
+
+static int
+dissect_vsncp_pdntype_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
+ proto_vsncp_option_pdntype, ett_vsncp_pdntype_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_vsncp_pdn_type, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static const value_string vsncp_errorcode_vals[] = {
+ {0, "General Error"},
+ {1, "Unauthorized APN"},
+ {2, "PDN Limit Exceeded"},
+ {3, "NO PG-W Available"},
+ {4, "P-GW Unreachable"},
+ {5, "P-GW Reject"},
+ {6, "Insufficient Parameters"},
+ {7, "Resource Unavailable"},
+ {8, "Admin Prohibited"},
+ {9, "PDN-ID Already in Use"},
+ {10, "Subscription Limitation"},
+ {11, "PDN connection already exists for APN"},
+ {12, "Emergency services not supported"},
+ {13, "Reconnect to this APN not allowed"},
+ {14, "APN congested"},
+ {0, NULL}
+};
+
+static int
+dissect_vsncp_errorcode_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ if (length < 3) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto_vsncp_option_errorcode )),
+ length, plurality(length, "", "s"), 3);
+ return tvb_captured_length(tvb);
+ }
+
+ tf = proto_tree_add_item(tree, proto_vsncp_option_errorcode, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_vsncp_errorcode_opt);
+
+ dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_pdnaddress));
+
+ proto_tree_add_item(field_tree, hf_vsncp_error_code, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsncp_pdnaddress_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+ guint32 pdnaddtype;
+
+ if (length < 3) {
+ /* Bogus - option length isn't what it's supposed to be for this option. */
+ proto_tree_add_expert_format(tree, pinfo, &ei_ppp_opt_len_invalid, tvb, 0, length,
+ "%s (with option length = %u byte%s; should be at least %u)",
+ proto_get_protocol_short_name(find_protocol_by_id(proto_vsncp_option_pdnaddress )),
+ length, plurality(length, "", "s"), 3);
+ return tvb_captured_length(tvb);
+ }
+
+ tf = proto_tree_add_item(tree, proto_vsncp_option_pdnaddress, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_vsncp_pdnaddress_opt);
+
+ dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_pdnaddress));
+
+ proto_tree_add_item_ret_uint(field_tree, hf_vsncp_pdn_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN, &pdnaddtype);
+
+ switch (pdnaddtype) {
+ case 1:
+ proto_tree_add_ipv4_format(field_tree, hf_vsncp_pdn_ipv4, tvb, offset + 3, 4,
+ tvb_get_ntohl(tvb, offset + 3), "%s: %s",
+ val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 3));
+ break;
+
+ case 2:
+ {
+ ws_in6_addr *ad = wmem_new0(pinfo->pool,ws_in6_addr);
+ address addr;
+
+ tvb_memcpy(tvb, &ad->bytes[8], offset + 3, 8);
+ set_address(&addr, AT_IPv6, 16, ad->bytes);
+ proto_tree_add_ipv6_format(field_tree, hf_vsncp_pdn_ipv6, tvb, offset + 3, length - 3, ad,
+ "%s: %s", val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
+ address_to_str(pinfo->pool, &addr));
+ break;
+ }
+
+ case 3:
+ {
+ ws_in6_addr *ad = wmem_new0(pinfo->pool, ws_in6_addr);
+ address addr;
+
+ tvb_memcpy(tvb, &ad->bytes[8], offset + 3, 8);
+ set_address(&addr, AT_IPv6, 16, ad->bytes);
+ proto_tree_add_ipv6_format(field_tree, hf_vsncp_pdn_ipv6, tvb, offset + 3, length - 3, ad,
+ "%s: %s", val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
+ address_to_str(pinfo->pool, &addr));
+ proto_tree_add_ipv4_format(field_tree, hf_vsncp_pdn_ipv4, tvb, offset + 11, length - 11,
+ tvb_get_ntohl(tvb, offset + 11), "%s: %s", val_to_str_const(pdnaddtype, vsncp_pdntype_vals, "Unknown"),
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 11));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsncp_ipv4address_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
+ proto_vsncp_option_ipv4address, ett_vsncp_ipv4address_opt, 6,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_vsncp_default_router_address, tvb, offset+2, 4, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsncp_apname_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ tf = proto_tree_add_item(tree, proto_vsncp_option_apname, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_vsncp_apname_opt);
+
+ dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_apname));
+
+ if (length > 2) {
+ guint8 i = 0;
+ guint8 j = 1;
+ guint8 lengthofapn;
+ int off = offset + 2;
+
+ while (i < (length - 2)) {
+ lengthofapn = tvb_get_guint8(tvb, off++);
+ proto_tree_add_string_format(field_tree, hf_vsncp_access_point_name, tvb, off, lengthofapn,
+ tvb_get_string_enc(pinfo->pool, tvb, off, lengthofapn, ENC_ASCII),
+ "Label%d (%d byte%s): %s", j++, lengthofapn,
+ plurality(lengthofapn, "", "s"),
+ tvb_format_text(pinfo->pool, tvb, off, lengthofapn));
+ off += lengthofapn;
+ i += lengthofapn + 1;
+ }
+ }
+ return tvb_captured_length(tvb);
+}
+
+static const value_string vsncp_alloc_vals[] = {
+ {0, "Null Value (Attach or Handover)"},
+ {18, "New PDN type due to network preference"},
+ {255, "Success"},
+ {0, NULL}
+};
+
+static int
+dissect_vsncp_addressalloc_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
+ proto_vsncp_option_addressalloc, ett_vsncp_addressalloc_opt, 3,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_vsncp_address_allocation_cause, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsncp_apn_ambr_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+ int length = tvb_reported_length(tvb);
+
+ tf = proto_tree_add_item(tree, proto_vsncp_option_apn_ambr, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_vsncp_apn_ambr_opt);
+
+ dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_apn_ambr ));
+ proto_tree_add_item(field_tree, hf_vsncp_ambr_data, tvb, offset+2, length-2, ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsncp_ipv6_hsgw_lla_iid_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ int offset = 0;
+
+ if (!dissect_vsncp_fixed_opt(tvb, pinfo, tree,
+ proto_vsncp_option_ipv6_hsgw_lla_iid, ett_vsncp_ipv6_hsgw_lla_iid_opt, 10,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_vsncp_ipv6_interface_identifier, tvb, offset+2, 8, ENC_NA);
+ return tvb_captured_length(tvb);
+}
+
+/* Ch 10.5.6.3 3GPP TS 24.008 version 11.5.0 Release 11 */
+static const value_string vsncp_pco_vals[] = {
+ {0x8021, "IPCP (DNS Address Request)"},
+ {0x0001, "P-CSCF Address Request (IPv6)"},
+ {0x0005, "MS Support of Network Requested Bearer Control indicator"},
+ {0x0003, "DNS Server Address (IPv6)"},
+ {0x000A, "IP address allocation via NAS signalling"},
+ {0x000B, "IPv4 address allocation via DHCPv4"},
+ {0x000D, "DNS Server IPv4 Address Request"},
+ {0, NULL}
+};
+
+static int
+dissect_vsncp_pco_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
+{
+ guint8 len;
+ proto_tree *field_tree;
+ proto_item *tf;
+ int length = tvb_reported_length(tvb);
+ int offset = 3;
+ guint8 i = 0;
+
+ tf = proto_tree_add_item(tree, proto_vsncp_option_pco, tvb, 0, length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_vsncp_pco_opt);
+
+ dissect_vsncp_opt_type_len(tvb, 0, field_tree, proto_registrar_get_name(proto_vsncp_option_pco));
+
+ while (i < (length - 3)) {
+ len = tvb_get_guint8(tvb, (offset + 2));
+ proto_tree_add_item(field_tree, hf_vsncp_protocol, tvb, offset, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(field_tree, hf_vsncp_protocol_configuration_length, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
+ if (len > 0) {
+ proto_tree_add_item(field_tree, hf_vsncp_protocol_configuration_data, tvb, offset + 3, len, ENC_NA);
+ }
+
+ offset += 3 + len;
+ i += 3 + len;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_cp(tvbuff_t *tvb, int proto_id, int proto_subtree_index,
+ const value_string *proto_vals, int options_subtree_index,
+ dissector_table_t option_table, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *fh_tree;
+ guint8 code;
+ int length, offset;
+ guint32 oui;
+ const gchar *manuf;
+ guint32 secs_remaining;
+
+ code = tvb_get_guint8(tvb, 0);
+ length = tvb_get_ntohs(tvb, 2);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ proto_get_protocol_short_name(find_protocol_by_id(proto_id)));
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str_const(code, proto_vals, "Unknown"));
+
+ ti = proto_tree_add_item(tree, proto_id, tvb, 0, length, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
+ proto_tree_add_uint_format_value(fh_tree, hf_ppp_code, tvb, 0, 1, code,
+ "%s (%u)", val_to_str_const(code, proto_vals, "Unknown"), code);
+ proto_tree_add_item(fh_tree, hf_ppp_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_ppp_length, tvb, 2, 2, ENC_BIG_ENDIAN);
+
+ offset = 4;
+ length -= 4;
+
+ switch (code) {
+ case VNDRSPCFC:
+ proto_tree_add_item(fh_tree, hf_ppp_magic_number, tvb, offset, 4,
+ ENC_BIG_ENDIAN);
+ oui = tvb_get_ntoh24(tvb, offset + 4);
+ ti = proto_tree_add_uint_format_value(fh_tree, hf_ppp_oui, tvb,
+ offset + 4, 3, oui, "%02x:%02x:%02x", (oui >> 16) & 0xff,
+ (oui >> 8) & 0xff, oui & 0xff);
+ manuf = uint_get_manuf_name_if_known(oui);
+ if (manuf){
+ proto_item_append_text(ti, "(%s)", manuf);
+ }
+ proto_tree_add_item(fh_tree, hf_ppp_kind, tvb, offset + 7, 1,
+ ENC_BIG_ENDIAN);
+ if (length > 8) {
+ proto_tree_add_item(fh_tree, hf_ppp_data, tvb, offset + 8,
+ length - 8, ENC_NA);
+ }
+ break;
+
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ if (length > 0) {
+ proto_tree *field_tree;
+
+ field_tree = proto_tree_add_subtree_format(fh_tree, tvb, offset, length,
+ options_subtree_index, NULL, "Options: (%d byte%s)", length, plurality(length, "", "s"));
+ ppp_dissect_options(tvb, offset, length, option_table, pinfo, field_tree);
+ }
+ break;
+
+ case CODEREJ:
+ if (length > 0) {
+ /* TODO: Decode the rejected packet here ... but wait until we have
+ * a valid capture file with a CODEREJ, since the only capture file
+ * with CODEREJ packets in it that I know of is pppoe.dump.gz from
+ * the menagerie, and that file appears to have malformed CODEREJ
+ * packets as they don't include the Code, Identifier or Length
+ * fields so it's impossible to do the decode. */
+ proto_tree_add_bytes_format(fh_tree, hf_ppp_data, tvb, offset,
+ length, NULL, "Rejected Packet (%d byte%s): %s", length,
+ plurality(length, "", "s"),
+ tvb_bytes_to_str(pinfo->pool, tvb, offset, length));
+ }
+ break;
+
+ case PROTREJ: /* LCP only: RFC 1661 */
+ proto_tree_add_item(fh_tree, hf_lcp_rej_proto, tvb, offset, 2,
+ ENC_BIG_ENDIAN);
+ if (length > 2) {
+ gboolean save_in_error_pkt;
+ tvbuff_t *next_tvb;
+ guint16 protocol;
+
+ protocol = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ length -= 2;
+
+ /*
+ * Save the current value of the "we're inside an error packet"
+ * flag, and set that flag; subdissectors may treat packets that
+ * are the payload of error packets differently from "real"
+ * packets.
+ */
+ save_in_error_pkt = pinfo->flags.in_error_pkt;
+ pinfo->flags.in_error_pkt = TRUE;
+
+ /* Decode the rejected packet. */
+ next_tvb = tvb_new_subset_length(tvb, offset, length);
+ if (!dissector_try_uint(ppp_subdissector_table, protocol, next_tvb,
+ pinfo, fh_tree)) {
+ call_data_dissector(next_tvb, pinfo, fh_tree);
+ }
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->flags.in_error_pkt = save_in_error_pkt;
+ }
+ break;
+
+ case ECHOREQ: /* All 3 are LCP only: RFC 1661 */
+ case ECHOREP:
+ case DISCREQ:
+ proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4,
+ ENC_BIG_ENDIAN);
+ if (length > 4) {
+ proto_tree_add_item(fh_tree, hf_lcp_data, tvb, offset + 4,
+ length - 4, ENC_NA);
+ }
+ break;
+
+ case IDENT: /* LCP only: RFC 1570 */
+ proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4,
+ ENC_BIG_ENDIAN);
+ if (length > 4) {
+ proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 4,
+ length - 4, ENC_ASCII);
+ }
+ break;
+
+ case TIMEREMAIN: /* LCP only: RFC 1570 */
+ proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4,
+ ENC_BIG_ENDIAN);
+ secs_remaining = tvb_get_ntohl(tvb, offset + 4);
+ proto_tree_add_uint_format_value(fh_tree, hf_lcp_secs_remaining,
+ tvb, offset + 4, 4, secs_remaining, "%u %s", secs_remaining,
+ (secs_remaining == 0xffffffff) ? "(forever)" : "seconds");
+ if (length > 8) {
+ proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 8,
+ length - 8, ENC_ASCII);
+ }
+ break;
+
+ case TERMREQ:
+ case TERMACK:
+ case RESETREQ: /* RESETREQ and RESETACK are CCP only: RFC 1962 */
+ case RESETACK:
+ default:
+ if (length > 0) {
+ proto_tree_add_item(fh_tree, hf_ppp_data, tvb, offset, length,
+ ENC_NA);
+ }
+ break;
+ }
+}
+
+/* Protocol field compression */
+#define PFC_BIT 0x01
+
+static void
+dissect_ppp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *fh_tree, proto_item *ti, int proto_offset)
+{
+ guint16 ppp_prot;
+ int proto_len;
+ tvbuff_t *next_tvb;
+
+ /* Make direction information filterable */
+ if (pinfo->p2p_dir == P2P_DIR_RECV || pinfo->p2p_dir == P2P_DIR_SENT) {
+ proto_item *direction_ti = proto_tree_add_uint(fh_tree, hf_ppp_direction,
+ tvb, 0, 0, pinfo->p2p_dir);
+ proto_item_set_generated(direction_ti);
+ }
+
+ ppp_prot = tvb_get_guint8(tvb, 0);
+ if (ppp_prot & PFC_BIT) {
+ /* Compressed protocol field - just the byte we fetched. */
+ proto_len = 1;
+ } else {
+ /* Uncompressed protocol field - fetch all of it. */
+ ppp_prot = tvb_get_ntohs(tvb, 0);
+ proto_len = 2;
+ }
+
+ /* If "ti" is not null, it refers to the top-level "proto_ppp" item
+ for PPP, and proto_offset is the length of any stuff in the header
+ preceding the protocol type, e.g. an HDLC header; add the length
+ of the protocol type field to it, and set the length of that item
+ to the result. */
+ proto_item_set_len(ti, proto_offset + proto_len);
+
+ proto_tree_add_uint(fh_tree, hf_ppp_protocol, tvb, 0, proto_len,
+ ppp_prot);
+
+ next_tvb = tvb_new_subset_remaining(tvb, proto_len);
+
+ /* do lookup with the subdissector table */
+ if (!dissector_try_uint(ppp_subdissector_table, ppp_prot, next_tvb, pinfo,
+ tree)) {
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ppp_prot);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)",
+ val_to_str_ext_const(ppp_prot, &ppp_vals_ext, "Unknown"),
+ ppp_prot);
+ call_data_dissector(next_tvb, pinfo, tree);
+ }
+}
+
+static int
+dissect_lcp_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ ppp_dissect_options(tvb, 0, tvb_reported_length(tvb), lcp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC's 1661, 2153 and 1570.
+ */
+static int
+dissect_lcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_lcp, ett_lcp, lcp_vals, ett_lcp_options, lcp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *fh_tree;
+ proto_tree *field_tree;
+ guint8 code;
+ int length, offset;
+
+ code = tvb_get_guint8(tvb, 0);
+ length = tvb_get_ntohs(tvb, 2);
+ vsnp_oui = tvb_get_guint24(tvb, 4, ENC_NA);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSNCP");
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str_const(code, cp_vals, "Unknown"));
+
+ ti = proto_tree_add_item(tree, proto_vsncp, tvb, 0, length, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, ett_vsncp);
+ proto_tree_add_item(fh_tree, hf_vsncp_code, tvb, 0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_vsncp_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_vsncp_length, tvb, 2, 2, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_ppp_oui, tvb, 4, 3, ENC_BIG_ENDIAN);
+
+ offset = 7;
+ length -= 7;
+
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ case TERMREQ:
+ case TERMACK:
+ if (length > 0) {
+ field_tree = proto_tree_add_subtree_format(fh_tree, tvb, offset, length,
+ ett_vsncp_options, NULL, "Options: (%d byte%s)", length,
+ plurality(length, "", "s"));
+ ppp_dissect_options(tvb, offset, length, vsncp_option_table, pinfo, field_tree);
+ }
+ break;
+
+ default:
+ /* TODO? */
+ break;
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_vsnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *vsnp_item;
+ proto_tree *vsnp_tree;
+
+ int offset = 0;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSNP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ vsnp_item = proto_tree_add_item(tree, proto_vsnp, tvb, 0, -1, ENC_NA);
+ vsnp_tree = proto_item_add_subtree(vsnp_item, ett_vsnp);
+
+ switch (vsnp_oui) {
+ case OUI_BBF:
+ col_set_str(pinfo->cinfo, COL_INFO, "Broadband Forum Session Data");
+ /* TO DO: Add support for Broadband Forum's VSNP */
+ break;
+ case OUI_3GPP:
+ col_set_str(pinfo->cinfo, COL_INFO, "3GPP Session Data");
+ tvbuff_t *next_tvb;
+
+ /* dissect 3GPP packet */
+ proto_tree_add_item(vsnp_tree, hf_vsnp_3gpp_pdnid, tvb, offset, 1, ENC_BIG_ENDIAN);
+ next_tvb = tvb_new_subset_remaining(tvb, 1);
+ if (!dissector_try_uint(ppp_subdissector_table, PPP_IP, next_tvb, pinfo, tree)) {
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", PPP_IP);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)",
+ val_to_str_ext_const(PPP_IP, &ppp_vals_ext, "Unknown"), PPP_IP);
+ call_data_dissector(next_tvb, pinfo, tree);
+ }
+ break;
+ default:
+ break;
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 1332.
+ */
+static int
+dissect_ipcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_ipcp, ett_ipcp, cp_vals, ett_ipcp_options, ipcp_option_table,
+ pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 3518
+ */
+#define BCP_FCS_PRESENT 0x80
+#define BCP_ZEROPAD 0x20
+#define BCP_IS_BCONTROL 0x10
+#define BCP_PADS_MASK 0x0f
+
+#define BCP_MACT_ETHERNET 1
+#define BCP_MACT_802_4 2
+#define BCP_MACT_802_5_NONCANON 3
+#define BCP_MACT_FDDI_NONCANON 4
+#define BCP_MACT_802_5_CANON 11
+#define BCP_MACT_FDDI_CANON 12
+
+static const value_string bcp_bpdu_mac_type_vals[] = {
+ {BCP_MACT_ETHERNET, "IEEE 802.3/Ethernet"},
+ {BCP_MACT_802_4, "IEEE 802.4"},
+ {BCP_MACT_802_5_NONCANON, "IEEE 802.5, non-canonical addresses"},
+ {BCP_MACT_FDDI_NONCANON, "FDDI, non-canonical addresses"},
+ {BCP_MACT_802_5_CANON, "IEEE 802.5, canonical addresses"},
+ {BCP_MACT_FDDI_CANON, "FDDI, canonical addresses"},
+ {0, NULL}
+};
+
+static int
+dissect_bcp_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *bcp_bpdu_tree;
+ int offset = 0;
+ guint8 flags;
+ guint8 mac_type;
+ gint captured_length, reported_length, pad_length;
+ tvbuff_t *next_tvb;
+ static int * const bcp_bpdu_flags[] = {
+ &hf_bcp_bpdu_fcs_present,
+ &hf_bcp_bpdu_zeropad,
+ &hf_bcp_bpdu_bcontrol,
+ &hf_bcp_bpdu_pads,
+ NULL
+ };
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP BCP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ti = proto_tree_add_item(tree, proto_bcp_bpdu, tvb, 0, -1, ENC_NA);
+ bcp_bpdu_tree = proto_item_add_subtree(ti, ett_bcp_bpdu);
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (flags & BCP_IS_BCONTROL) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Bridge control");
+ }
+
+ proto_tree_add_bitmask(bcp_bpdu_tree, tvb, offset, hf_bcp_bpdu_flags, ett_bcp_bpdu_flags, bcp_bpdu_flags, ENC_NA);
+ offset++;
+
+ mac_type = tvb_get_guint8(tvb, offset);
+ if (!(flags & BCP_IS_BCONTROL)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(mac_type, bcp_bpdu_mac_type_vals,
+ "Unknown MAC type %u"));
+ }
+ proto_tree_add_uint(bcp_bpdu_tree, hf_bcp_bpdu_mac_type, tvb, offset, 1, mac_type);
+ offset++;
+
+ switch (mac_type) {
+
+ case BCP_MACT_802_4:
+ case BCP_MACT_802_5_NONCANON:
+ case BCP_MACT_FDDI_NONCANON:
+ case BCP_MACT_802_5_CANON:
+ case BCP_MACT_FDDI_CANON:
+ proto_tree_add_item(bcp_bpdu_tree, hf_bcp_bpdu_pad, tvb, offset, 1, ENC_NA);
+ offset++;
+ break;
+
+ default:
+ /* TODO? */
+ break;
+ }
+
+ proto_item_set_len(ti, offset);
+
+ if (!(flags & BCP_IS_BCONTROL)) {
+ captured_length = tvb_captured_length_remaining(tvb, offset);
+ reported_length = tvb_reported_length_remaining(tvb, offset);
+ pad_length = flags & BCP_PADS_MASK;
+ if (reported_length >= pad_length) {
+ reported_length -= pad_length;
+ if (captured_length > reported_length)
+ captured_length = reported_length;
+ next_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_length,
+ reported_length);
+ switch (mac_type) {
+
+ case BCP_MACT_ETHERNET:
+ if (flags & BCP_FCS_PRESENT) {
+ call_dissector(eth_withfcs_handle, next_tvb, pinfo, tree);
+ } else {
+ call_dissector(eth_withoutfcs_handle, next_tvb, pinfo,
+ tree);
+ }
+ break;
+
+ case BCP_MACT_802_4:
+ case BCP_MACT_802_5_NONCANON:
+ case BCP_MACT_FDDI_NONCANON:
+ case BCP_MACT_802_5_CANON:
+ case BCP_MACT_FDDI_CANON:
+ break;
+
+ default:
+ call_data_dissector(next_tvb, pinfo, tree);
+ break;
+ }
+ }
+ }
+ return tvb_captured_length(tvb);
+}
+
+/* RFC 3518
+ * 4. A PPP Network Control Protocol for Bridging
+ * :
+ * The Bridging Control Protocol is exactly the same as the Link Control
+ * Protocol [6] with the following exceptions...
+ * :
+ * ---the PPP Protocol field indicates type hex 8031 (BCP).
+ */
+static int
+dissect_bcp_ncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_bcp_ncp, ett_bcp_ncp, lcp_vals, ett_bcp_ncp_options,
+ bcp_ncp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 1377.
+ */
+static int
+dissect_osinlcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_osinlcp, ett_osinlcp, cp_vals, ett_osinlcp_options, osinlcp_option_table,
+ pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 1962.
+ */
+static int
+dissect_ccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_ccp, ett_ccp, ccp_vals, ett_ccp_options, ccp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * Callback Control Protocol - see
+ *
+ * https://tools.ietf.org/html/draft-gidwani-ppp-callback-cp-00
+ */
+static int
+dissect_cbcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_cbcp, ett_cbcp, cbcp_vals, ett_cbcp_options,
+ cbcp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 2125 (BACP and BAP).
+ */
+static int
+dissect_bacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_bacp, ett_bacp, cp_vals, ett_bacp_options, bacp_option_table,
+ pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_bap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *fh_tree;
+ proto_tree *field_tree;
+ guint8 type;
+ int length, offset;
+
+ type = tvb_get_guint8(tvb, 0);
+ length = tvb_get_ntohs(tvb, 2);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP BAP");
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str_const(type, bap_vals, "Unknown"));
+
+ ti = proto_tree_add_item(tree, proto_bap, tvb, 0, length, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, ett_bap_options);
+ proto_tree_add_item(fh_tree, hf_bap_type, tvb, 0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_bap_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_bap_length, tvb, 2, 2, ENC_BIG_ENDIAN);
+
+ offset = 4;
+ length -= 4;
+
+ if (type == BAP_CRES || type == BAP_CBRES ||
+ type == BAP_LDQRES || type == BAP_CSRES) {
+ proto_tree_add_item(fh_tree, hf_bap_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ length--;
+ }
+
+ if (length > 0) {
+ field_tree = proto_tree_add_subtree_format(fh_tree, tvb, offset, length,
+ ett_bap_options, NULL, "Data (%d byte%s)", length, plurality(length, "", "s"));
+ ppp_dissect_options(tvb, offset, length, bap_option_table, pinfo, field_tree);
+ }
+ return tvb_captured_length(tvb);
+}
+
+#if 0 /* TODO? */
+static int
+dissect_comp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *comp_data_tree;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP Comp");
+ col_set_str(pinfo->cinfo, COL_INFO, "Compressed data");
+
+ ti = proto_tree_add_item(tree, proto_comp_data, tvb, 0, -1, ENC_NA);
+ comp_data_tree = proto_item_add_subtree(ti, ett_comp_data);
+
+ return tvb_captured_length(tvb);
+}
+#else
+static int
+dissect_comp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP Comp");
+ col_set_str(pinfo->cinfo, COL_INFO, "Compressed data");
+
+ proto_tree_add_item(tree, proto_comp_data, tvb, 0, -1, ENC_NA);
+ return tvb_captured_length(tvb);
+}
+#endif
+
+/*
+ * RFC 3153 (both PPPMuxCP and PPPMux).
+ */
+static int
+dissect_pppmuxcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_pppmuxcp, ett_pppmuxcp, pppmuxcp_vals,
+ ett_pppmuxcp_options, pppmuxcp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+#define PPPMUX_FLAGS_MASK 0xc0
+#define PPPMUX_PFF_BIT_SET 0x80
+#define PPPMUX_LXT_BIT_SET 0x40
+
+static int
+dissect_pppmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *mux_tree, *hdr_tree, *sub_tree;
+ proto_tree *info_tree;
+ proto_item *ti = NULL;
+ guint8 flags, byte;
+ guint16 length;
+ static guint16 pid;
+ tvbuff_t *next_tvb;
+ int offset = 0, length_remaining;
+ int length_field, pid_field, hdr_length;
+ static int * const subframe_flags[] = {
+ &hf_pppmux_flags_pid,
+ &hf_pppmux_flags_field_length,
+ NULL
+ };
+
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "PPP PPPMux");
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Multiplexing");
+
+ length_remaining = tvb_reported_length(tvb);
+
+ ti = proto_tree_add_item(tree, proto_pppmux, tvb, 0, -1, ENC_NA);
+ mux_tree = proto_item_add_subtree(ti, ett_pppmux);
+
+ while (length_remaining > 0) {
+ flags = tvb_get_guint8(tvb,offset) & PPPMUX_FLAGS_MASK;
+
+ if (flags & PPPMUX_LXT_BIT_SET) {
+ length = tvb_get_ntohs(tvb,offset) & 0x3fff;
+ length_field = 2;
+ } else {
+ length = tvb_get_guint8(tvb,offset) & 0x3f;
+ length_field = 1;
+ }
+
+ if (flags & PPPMUX_PFF_BIT_SET) {
+ byte = tvb_get_guint8(tvb,offset + length_field);
+ if (byte & PFC_BIT) { /* Compressed PID field */
+ pid = byte;
+ pid_field = 1;
+ } else { /* PID field is 2 bytes */
+ pid = tvb_get_ntohs(tvb,offset + length_field);
+ pid_field = 2;
+ }
+ } else {
+ pid_field = 0; /* PID field is 0 bytes */
+ if (!pid) { /* No Last PID, hence use the default */
+ if (pppmux_def_prot_id)
+ pid = pppmux_def_prot_id;
+ }
+ }
+
+ hdr_length = length_field + pid_field;
+
+ sub_tree = proto_tree_add_subtree(mux_tree, tvb, offset, length + length_field,
+ ett_pppmux_subframe, NULL, "PPPMux Sub-frame");
+ hdr_tree = proto_tree_add_subtree(sub_tree, tvb, offset, hdr_length,
+ ett_pppmux_subframe_hdr, NULL, "Header field");
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_pppmux_flags, ett_pppmux_subframe_flags, subframe_flags, ENC_BIG_ENDIAN);
+ proto_tree_add_uint(hdr_tree, hf_pppmux_sub_frame_length, tvb,offset, length_field, length);
+
+ ti = proto_tree_add_uint(hdr_tree, hf_pppmux_protocol, tvb,
+ offset + length_field, pid_field, pid);
+
+ /* if protocol is not present in the sub-frame */
+ if (!(flags & PPPMUX_PFF_BIT_SET)) {
+ /* mark this item as generated */
+ proto_item_set_generated(ti);
+ }
+
+ offset += hdr_length;
+ length_remaining -= hdr_length;
+ length -= pid_field;
+
+ tvb_ensure_bytes_exist (tvb, offset, length);
+ info_tree = proto_tree_add_subtree(sub_tree, tvb,offset, length,
+ ett_pppmux_subframe_info, NULL, "Information Field");
+ next_tvb = tvb_new_subset_length(tvb, offset, length);
+
+ if (!dissector_try_uint(ppp_subdissector_table, pid, next_tvb, pinfo,
+ info_tree)) {
+ call_data_dissector(next_tvb, pinfo, info_tree);
+ }
+ offset += length;
+ length_remaining -= length;
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 2507 / RFC 2508 Internet Protocol Header Compression
+ */
+#define IPHC_CRTP_FH_FLAG_MASK 0xc0
+#define IPHC_CRTP_FH_CIDLEN_FLAG 0x80
+#define IPHC_CRTP_FH_DATA_FLAG 0x40
+
+#define IPHC_CRTP_CS_CID8 1
+#define IPHC_CRTP_CS_CID16 2
+
+static int * const iphc_crtp_fh_flags_fields[] = {
+ &hf_iphc_crtp_fh_cidlenflag,
+ &hf_iphc_crtp_fh_dataflag,
+ NULL
+};
+
+static const true_false_string iphc_crtp_fh_cidlenflag = {
+ "16-bit",
+ "8-bit"
+};
+
+static const value_string iphc_crtp_cs_flags[] = {
+ {IPHC_CRTP_CS_CID8, "8-bit Context Id"},
+ {IPHC_CRTP_CS_CID16, "16-bit Context Id"},
+ {0, NULL}
+};
+
+static const crumb_spec_t iphc_crtp_cntcp_cid16_crumbs[] = {
+ {0, 8},
+ {16, 8},
+ {0, 0}
+};
+
+/*
+ * 0x61 Packets: Full IP/UDP Header
+ */
+static int
+dissect_iphc_crtp_fh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *fh_tree, *info_tree;
+ proto_item *ti;
+ guint ip_hdr_len, flags, seq;
+ guint length;
+ guint hdr_len;
+ tvbuff_t *next_tvb;
+ int offset_seq;
+ int offset_cid;
+ guint8 ip_version;
+ guint8 next_protocol;
+ guchar *ip_packet;
+
+ length = tvb_reported_length(tvb);
+
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
+ col_set_str(pinfo->cinfo, COL_INFO, "Full Header");
+
+ /* only dissect IPv4 and UDP */
+ ip_version = tvb_get_guint8(tvb, 0) >> 4;
+ flags = (tvb_get_guint8(tvb, 2) & IPHC_CRTP_FH_FLAG_MASK);
+ next_protocol = tvb_get_guint8(tvb, 9);
+
+ ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
+ "%s", val_to_str_ext_const(PPP_RTP_FH, &ppp_vals_ext, "Unknown"));
+ fh_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
+
+ proto_tree_add_bitmask_with_flags(fh_tree, tvb, 2, hf_iphc_crtp_fh_flags,
+ ett_iphc_crtp_fh_flags, iphc_crtp_fh_flags_fields, ENC_BIG_ENDIAN,
+ BMT_NO_FLAGS);
+ proto_tree_add_item(fh_tree, hf_iphc_crtp_gen, tvb, 2, 1,
+ ENC_BIG_ENDIAN);
+
+ /* calculate length of IP header, assume IPv4 */
+ ip_hdr_len = (tvb_get_guint8(tvb, 0) & 0x0f) * 4;
+
+ /* calculate total hdr length, assume UDP */
+ hdr_len = ip_hdr_len + 8;
+
+ if (ip_version != 4) {
+ proto_tree_add_expert_format(fh_tree, pinfo, &ei_iphc_crtp_ip_version, tvb, 3, -1,
+ "IP version is %u: the only supported version is 4",
+ ip_version);
+ return 1;
+ }
+
+ if (next_protocol != IP_PROTO_UDP) {
+ proto_tree_add_expert_format(fh_tree, pinfo, &ei_iphc_crtp_next_protocol, tvb, 3, -1,
+ "Next protocol is %s (%u): the only supported protocol is UDP",
+ ipprotostr(next_protocol), next_protocol);
+ return 1;
+ }
+
+ /* context id and sequence fields */
+ if (flags & IPHC_CRTP_FH_CIDLEN_FLAG) {
+ offset_seq = 3;
+ offset_cid = ip_hdr_len + 4;
+ if (flags & IPHC_CRTP_FH_DATA_FLAG) {
+ proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq, 1,
+ ENC_BIG_ENDIAN);
+ } else {
+ seq = tvb_get_guint8(tvb, offset_seq);
+ if (seq != 0) {
+ ti = proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq,
+ 1, ENC_BIG_ENDIAN);
+ expert_add_info(pinfo, ti, &ei_iphc_crtp_seq_nonzero);
+ }
+ }
+ proto_tree_add_item(fh_tree, hf_iphc_crtp_cid16, tvb, offset_cid,
+ 2, ENC_BIG_ENDIAN);
+ } else {
+ offset_cid = 3;
+ offset_seq = ip_hdr_len + 5;
+ proto_tree_add_item(fh_tree, hf_iphc_crtp_cid8, tvb, offset_cid, 1,
+ ENC_BIG_ENDIAN);
+ if (flags & IPHC_CRTP_FH_DATA_FLAG) {
+ proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq, 1,
+ ENC_BIG_ENDIAN);
+ } else {
+ seq = tvb_get_guint8(tvb, offset_seq);
+ if (seq != 0) {
+ ti = proto_tree_add_item(fh_tree, hf_iphc_crtp_seq, tvb, offset_seq,
+ 1, ENC_BIG_ENDIAN);
+ expert_add_info(pinfo, ti, &ei_iphc_crtp_seq_nonzero);
+ }
+ }
+ }
+
+ /* information field */
+ info_tree = proto_tree_add_subtree(fh_tree, tvb, 0, length, ett_iphc_crtp_info, NULL, "Information Field");
+
+ /* XXX: 1: May trap above; 2: really only need to check for ip_hdr_len+6 ?? */
+ tvb_ensure_bytes_exist (tvb, 0, hdr_len); /* ip_hdr_len + 8 */
+
+ /* allocate a copy of the IP packet */
+ ip_packet = (guchar *)tvb_memdup(pinfo->pool, tvb, 0, length);
+
+ /* restore the proper values to the IP and UDP length fields */
+ ip_packet[2] = length >> 8;
+ ip_packet[3] = length;
+
+ ip_packet[ip_hdr_len + 4] = (length - ip_hdr_len) >> 8;
+ ip_packet[ip_hdr_len + 5] = (length - ip_hdr_len);
+
+ next_tvb = tvb_new_child_real_data(tvb, ip_packet, length, length);
+ add_new_data_source(pinfo, next_tvb, "Decompressed Data");
+
+ if (!dissector_try_uint(ppp_subdissector_table, PPP_IP, next_tvb, pinfo,
+ info_tree)) {
+ call_data_dissector(next_tvb, pinfo, info_tree);
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * 0x2067 Packets: Compressed UDP with 16-bit Context Identifier
+ */
+static int
+dissect_iphc_crtp_cudp16(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *cudp_tree;
+ proto_item *ti;
+ guint length;
+ guint hdr_length;
+ int offset = 0;
+
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
+ col_set_str(pinfo->cinfo, COL_INFO, "Compressed UDP 16");
+
+ length = tvb_reported_length(tvb);
+
+ ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
+ "%s",
+ val_to_str_ext_const(PPP_RTP_CUDP16, &ppp_vals_ext, "Unknown"));
+ cudp_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
+
+ hdr_length = 3;
+
+ proto_tree_add_item(cudp_tree, hf_iphc_crtp_cid16, tvb, 0, 2,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(cudp_tree, hf_iphc_crtp_seq, tvb, 2, 1,
+ ENC_BIG_ENDIAN);
+
+ offset += hdr_length;
+ length -= hdr_length;
+
+ proto_tree_add_item(cudp_tree, hf_iphc_crtp_data, tvb, offset, length, ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * 0x67 Packets: Compressed UDP with 8-bit Context Identifier
+ */
+static int
+dissect_iphc_crtp_cudp8(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *cudp_tree;
+ proto_item *ti;
+ guint length;
+ guint hdr_length;
+ int offset = 0;
+
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
+ col_set_str(pinfo->cinfo, COL_INFO, "Compressed UDP 8");
+
+ length = tvb_reported_length(tvb);
+
+ ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
+ "%s",
+ val_to_str_ext_const(PPP_RTP_CUDP8, &ppp_vals_ext, "Unknown"));
+ cudp_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
+
+ hdr_length = 2;
+
+ proto_tree_add_item(cudp_tree, hf_iphc_crtp_cid8, tvb, 0, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(cudp_tree, hf_iphc_crtp_seq, tvb, 1, 1,
+ ENC_BIG_ENDIAN);
+
+ offset += hdr_length;
+ length -= hdr_length;
+
+ proto_tree_add_item(cudp_tree, hf_iphc_crtp_data, tvb, offset, length, ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+
+/*
+ * 0x2065 Packets: Context State
+ */
+static int
+dissect_iphc_crtp_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *cs_tree;
+ proto_item *ti = NULL;
+ guint8 flags, cnt;
+ guint length, cid_size;
+ guint offset = 2, hf;
+
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
+ col_set_str(pinfo->cinfo, COL_INFO, "Context State");
+
+ ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
+ "%s", val_to_str_ext_const(PPP_RTP_CS, &ppp_vals_ext, "Unknown"));
+
+ cs_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
+
+ proto_tree_add_item(cs_tree, hf_iphc_crtp_cs_flags, tvb, 0, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(cs_tree, hf_iphc_crtp_cs_cnt, tvb, 1, 1,
+ ENC_BIG_ENDIAN);
+
+ /* calculate required length */
+ flags = tvb_get_guint8(tvb, 0);
+ cnt = tvb_get_guint8(tvb, 1);
+
+ if (flags == IPHC_CRTP_CS_CID8) {
+ hf = hf_iphc_crtp_cid8;
+ cid_size = 1;
+ length = 3 * cnt;
+ } else {
+ hf = hf_iphc_crtp_cid16;
+ cid_size = 2;
+ length = 4 * cnt;
+ }
+
+ while (offset < length) {
+ proto_tree_add_item(cs_tree, hf, tvb, offset, cid_size,
+ ENC_BIG_ENDIAN);
+ offset += cid_size;
+ proto_tree_add_item(cs_tree, hf_iphc_crtp_cs_invalid, tvb, offset,
+ 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(cs_tree, hf_iphc_crtp_seq, tvb, offset, 1,
+ ENC_BIG_ENDIAN);
+ ++offset;
+ proto_tree_add_item(cs_tree, hf_iphc_crtp_gen, tvb, offset, 1,
+ ENC_BIG_ENDIAN);
+ ++offset;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * 0x65 Packets: Compressed Non TCP
+ */
+static int
+dissect_iphc_crtp_cntcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *cntcp_tree;
+ proto_item *ti;
+ guint length, flags;
+ guint hdr_length;
+ int offset = 0;
+
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "CRTP");
+ col_set_str(pinfo->cinfo, COL_INFO, "Compressed Non TCP");
+
+ length = tvb_reported_length(tvb);
+
+ flags = (tvb_get_guint8(tvb, 1) & IPHC_CRTP_FH_FLAG_MASK);
+
+ ti = proto_tree_add_protocol_format(tree, proto_iphc_crtp, tvb, 0, -1,
+ "%s",
+ val_to_str_ext_const(PPP_RTP_CNTCP, &ppp_vals_ext, "Unknown"));
+ cntcp_tree = proto_item_add_subtree(ti, ett_iphc_crtp);
+
+ if (flags & IPHC_CRTP_FH_CIDLEN_FLAG) {
+ /* RFC 2507 6. Compressed Header Formats
+ * d) Compressed non-TCP header, 16 bit CID:
+ * 0 7
+ * +-+-+-+-+-+-+-+-+
+ * | msb of CID |
+ * +-+-+-+-+-+-+-+-+
+ * |1|D| Generation|
+ * +-+-+-+-+-+-+-+-+
+ * | lsb of CID |
+ * +-+-+-+-+-+-+-+-+
+ * | data | (if D=1)
+ * - - - - - - - -
+ * | RANDOM fields, if any (section 7) (implied)
+ */
+ hdr_length = 3;
+ proto_tree_add_split_bits_item_ret_val(cntcp_tree, hf_iphc_crtp_cid16, tvb, 0,
+ iphc_crtp_cntcp_cid16_crumbs, NULL);
+ } else {
+ /* c) Compressed non-TCP header, 8 bit CID:
+ * 0 7
+ * +-+-+-+-+-+-+-+-+
+ * | CID |
+ * +-+-+-+-+-+-+-+-+
+ * |0|D| Generation|
+ * +-+-+-+-+-+-+-+-+
+ * | data | (if D=1)
+ * - - - - - - - -
+ * | RANDOM fields, if any (section 7) (implied)
+ * - - - - - - - -
+ */
+ hdr_length = 2;
+ proto_tree_add_item(cntcp_tree, hf_iphc_crtp_cid8, tvb, 0, 1,
+ ENC_BIG_ENDIAN);
+ }
+ proto_tree_add_bitmask_with_flags(cntcp_tree, tvb, 1, hf_iphc_crtp_fh_flags,
+ ett_iphc_crtp_fh_flags, iphc_crtp_fh_flags_fields, ENC_BIG_ENDIAN,
+ BMT_NO_FLAGS);
+ proto_tree_add_item(cntcp_tree, hf_iphc_crtp_gen, tvb, 1, 1,
+ ENC_BIG_ENDIAN);
+
+ if (flags & IPHC_CRTP_FH_DATA_FLAG) {
+ proto_tree_add_item(cntcp_tree, hf_iphc_crtp_seq, tvb, hdr_length++,
+ 1, ENC_BIG_ENDIAN);
+ }
+
+ offset += hdr_length;
+ length -= hdr_length;
+
+ /* The IPv4 Identification Field is RANDOM and thus included in a
+ * compressed Non TCP packet (RFC 2507 6a, 7.13a). Only IPv4 is
+ * supported in this dissector, so we don't worry about the IPv6
+ * case, which is different (RFC 2507 7.1)."
+ */
+ proto_tree_add_item(cntcp_tree, hf_iphc_crtp_ip_id, tvb, offset,
+ 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ length -= 2;
+
+ proto_tree_add_item(cntcp_tree, hf_iphc_crtp_data, tvb, offset, length, ENC_NA);
+
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 3032.
+ */
+static int
+dissect_mplscp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_mplscp, ett_mplscp, cp_vals, ett_mplscp_options,
+ NULL, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * Cisco Discovery Protocol Control Protocol.
+ * XXX - where is this documented?
+ */
+static int
+dissect_cdpcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_cdpcp, ett_cdpcp, cp_vals, ett_cdpcp_options, NULL,
+ pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+/* PPP Multilink Protcol (RFC 1990) and
+ * the Multiclass Extension to Multi-Link PPP (RFC 2686)
+ */
+static gboolean mp_short_seqno = FALSE; /* Default to long sequence numbers */
+static guint mp_max_fragments = 6;
+/* Maximum fragments to try to reassemble. This affects performance and
+ * memory use significantly. */
+static guint mp_fragment_aging = 4000; /* Short sequence numbers only 12 bit */
+
+#define MP_FRAG_MASK 0xFF
+#define MP_FRAG_MASK_SHORT 0xF0
+#define MP_FRAG_FIRST 0x80
+#define MP_FRAG_LAST 0x40
+#define MP_FRAG_CLS 0x3C
+#define MP_FRAG_RESERVED 0x03
+#define MP_FRAG_CLS_SHORT 0x30
+
+/* According to RFC 1990, the length the MP header isn't indicated anywhere
+ in the header itself. It starts out at four bytes and can be
+ negotiated down to two using LCP. We currently have a preference
+ to select short headers. - gcc & gh
+*/
+
+static int
+dissect_mp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *mp_tree;
+ proto_item *ti;
+ gboolean save_fragmented;
+ guint8 flags;
+ guint32 cls; /* 32 bit since we shift it left and XOR with seqnum */
+ guint32 seqnum;
+ gint hdrlen;
+ fragment_head *frag_mp;
+ tvbuff_t *next_tvb;
+ static int * const mp_flags[] = {
+ &hf_mp_frag_first,
+ &hf_mp_frag_last,
+ &hf_mp_sequence_num_cls,
+ &hf_mp_sequence_num_reserved,
+ NULL
+ };
+ static int * const mp_short_flags[] = {
+ &hf_mp_frag_first,
+ &hf_mp_frag_last,
+ &hf_mp_short_sequence_num_cls,
+ NULL
+ };
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP MP");
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Multilink");
+
+ save_fragmented = pinfo->fragmented;
+ flags = tvb_get_guint8(tvb, 0);
+
+ ti = proto_tree_add_item(tree, proto_mp, tvb, 0,
+ mp_short_seqno ? 2 : 4, ENC_NA);
+ mp_tree = proto_item_add_subtree(ti, ett_mp);
+
+ if (mp_short_seqno) {
+ proto_tree_add_bitmask(mp_tree, tvb, 0, hf_mp_frag_short, ett_mp_flags, mp_short_flags, ENC_NA);
+ proto_tree_add_item_ret_uint(mp_tree, hf_mp_short_sequence_num, tvb, 0, 2, ENC_BIG_ENDIAN, &seqnum);
+ } else {
+ proto_tree_add_bitmask(mp_tree, tvb, 0, hf_mp_frag, ett_mp_flags, mp_flags, ENC_NA);
+ proto_tree_add_item_ret_uint(mp_tree, hf_mp_sequence_num, tvb, 1, 3, ENC_BIG_ENDIAN, &seqnum);
+ }
+
+ hdrlen = mp_short_seqno ? 2 : 4;
+ if (mp_short_seqno) {
+ cls = (flags & MP_FRAG_CLS_SHORT) >> 4;
+ } else {
+ cls = (flags & MP_FRAG_CLS) >> 2;
+ }
+ if (tvb_reported_length_remaining(tvb, hdrlen) > 0) {
+ pinfo->fragmented = TRUE;
+ frag_mp = NULL;
+ if (!pinfo->fd->visited) {
+ frag_mp = fragment_add_seq_single_aging(&mp_reassembly_table,
+ tvb, hdrlen, pinfo, seqnum ^ (cls << 24), NULL,
+ tvb_captured_length_remaining(tvb, hdrlen),
+ flags & MP_FRAG_FIRST, flags & MP_FRAG_LAST,
+ mp_max_fragments, mp_fragment_aging);
+ } else {
+ frag_mp = fragment_get_reassembled_id(&mp_reassembly_table, pinfo, seqnum ^ (cls << 24));
+ }
+ next_tvb = process_reassembled_data(tvb, hdrlen, pinfo,
+ "Reassembled PPP MP payload", frag_mp, &mp_frag_items,
+ NULL, mp_tree);
+
+ if (frag_mp) {
+ if (next_tvb) {
+ dissect_ppp(next_tvb, pinfo, tree, NULL);
+ } else {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (PPP MP reassembled in packet %u)",
+ frag_mp->reassembled_in);
+ proto_tree_add_item(mp_tree, hf_mp_payload, tvb, hdrlen, -1, ENC_NA);
+ }
+ } else {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (PPP MP Unreassembled fragment %u)",
+ seqnum);
+ proto_tree_add_item(mp_tree, hf_mp_payload, tvb, hdrlen, -1, ENC_NA);
+ }
+ }
+
+ pinfo->fragmented = save_fragmented;
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * Handles PPP without HDLC framing, just a protocol field (RFC 1661).
+ */
+static int
+dissect_ppp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *fh_tree;
+
+ ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, ett_ppp);
+
+ dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti, 0);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_ppp_hdlc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *fh_tree;
+ guint8 byte0;
+ int proto_offset;
+ tvbuff_t *next_tvb;
+
+ byte0 = tvb_get_guint8(tvb, 0);
+
+ /* PPP HDLC encapsulation */
+ if (byte0 == 0xff)
+ proto_offset = 2;
+ else {
+ /* address and control are compressed (NULL) */
+ proto_offset = 0;
+ }
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, ett_ppp);
+ if (byte0 == 0xff) {
+ proto_tree_add_item(fh_tree, hf_ppp_address, tvb, 0, 1,
+ ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_ppp_control, tvb, 1, 1,
+ ENC_BIG_ENDIAN);
+ }
+
+ next_tvb = decode_fcs(tvb, pinfo, fh_tree, ppp_fcs_decode, proto_offset);
+ dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti, proto_offset);
+}
+
+/*
+ * Handles link-layer encapsulations where the frame might be
+ * a PPP in HDLC-like Framing frame (RFC 1662) or a Cisco HDLC frame.
+ */
+static int
+dissect_ppp_hdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ guint8 byte0;
+
+ byte0 = tvb_get_guint8(tvb, 0);
+ if (byte0 == CHDLC_ADDR_UNICAST || byte0 == CHDLC_ADDR_MULTICAST) {
+ /* Cisco HDLC encapsulation */
+ return call_dissector(chdlc_handle, tvb, pinfo, tree);
+ }
+
+ /*
+ * XXX - should we have an exported dissector that always dissects
+ * PPP-in-HDLC-like-framing, without checking for Cisco HDLC, for
+ * use when we know the packets are PPP, not Cisco HDLC?
+ */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ break;
+
+ case P2P_DIR_RECV:
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ break;
+
+ default:
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
+ break;
+ }
+
+ dissect_ppp_hdlc_common(tvb, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+static tvbuff_t*
+remove_escape_chars(tvbuff_t *tvb, packet_info *pinfo, int offset, int length)
+{
+ guint8 *buff;
+ int i;
+ int scanned_len = 0;
+ guint8 octet;
+ tvbuff_t *next_tvb;
+
+ buff = (guint8 *)wmem_alloc(pinfo->pool, length);
+ i = 0;
+ while (scanned_len < length) {
+ octet = tvb_get_guint8(tvb, offset);
+ if (octet == 0x7d) {
+ offset++;
+ scanned_len++;
+ if (scanned_len >= length)
+ break;
+ octet = tvb_get_guint8(tvb, offset);
+ buff[i] = octet ^ 0x20;
+ } else {
+ buff[i] = octet;
+ }
+ offset++;
+ scanned_len++;
+ i++;
+ }
+ if (i == 0) {
+ return NULL;
+ }
+ next_tvb = tvb_new_child_real_data(tvb, buff, i, i);
+
+ return next_tvb;
+}
+
+/*
+ * Handles link-layer encapsulations where we have a raw RFC 1662
+ * HDLC-like asynchronous framing byte stream, and have to
+ * break the byte stream into frames and remove escapes.
+ */
+static int
+dissect_ppp_raw_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ )
+{
+ proto_item *ti;
+ proto_tree *bs_tree;
+ gint offset, end_offset, data_offset;
+ int length, data_length;
+ tvbuff_t *ppp_tvb;
+ gboolean first = TRUE;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
+
+ ti = proto_tree_add_item(tree, proto_ppp_hdlc, tvb, 0, -1, ENC_NA);
+ bs_tree = proto_item_add_subtree(ti, ett_ppp_hdlc_data);
+
+ /*
+ * XXX - this needs to handle a PPP frame split over multiple higher-level
+ * packets.
+ */
+
+ /*
+ * Look for a frame delimiter.
+ */
+ offset = tvb_find_guint8(tvb, 0, -1, 0x7e);
+ if (offset == -1) {
+ /*
+ * None found - this is presumably continued from an earlier
+ * packet and continued in a later packet.
+ */
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Fragment");
+ proto_tree_add_item(bs_tree, hf_ppp_hdlc_fragment, tvb, offset, -1, ENC_NA);
+ offset++;
+ length = tvb_captured_length_remaining(tvb,offset);
+ ppp_tvb = remove_escape_chars(tvb, pinfo, offset,length);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
+ call_data_dissector(ppp_tvb, pinfo, tree);
+ }
+ return tvb_captured_length(tvb);
+ }
+ if (offset != 0) {
+ /*
+ * We have some data preceding the first PPP packet;
+ * mark it as a PPP fragment.
+ */
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Fragment");
+ length = offset;
+ proto_tree_add_item(bs_tree, hf_ppp_hdlc_fragment, tvb, 0, length, ENC_NA);
+ ppp_tvb = remove_escape_chars(tvb, pinfo, 0, length - 1);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
+ call_data_dissector(ppp_tvb, pinfo, tree);
+ }
+ }
+
+ /* These frames within the byte stream need to be treated like independent
+ * frames / PDUs, not encapsulated in each other, which means that much of
+ * the various information stored in the packet_info struct should be reset
+ * with each frame.
+ * In particular, the "most recent conservation" elements should be reset
+ * at the start of a new frame, if that frame is dissected, and possibly
+ * for fragments that are put on a reassembly table (if the reassembly
+ * functions use elements from the pinfo struct for matching). (#18278)
+ * On the other hand, we do want to keep the last set information for use
+ * in displaying the address of the packet, conversation filtering, etc.
+ */
+ gboolean save_use_conv_addr_port_endpoints;
+ struct conversation_addr_port_endpoints *save_conv_addr_port_endpoints;
+ struct conversation_element *save_conv_elements;
+
+ save_use_conv_addr_port_endpoints = pinfo->use_conv_addr_port_endpoints;
+ save_conv_addr_port_endpoints = pinfo->conv_addr_port_endpoints;
+ save_conv_elements = pinfo->conv_elements;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+
+ /*
+ * Look for the next frame delimiter.
+ */
+ end_offset = tvb_find_guint8(tvb, offset + 1, -1, 0x7e);
+ if (end_offset == -1) {
+ /*
+ * We didn't find one. This is probably continued in a later
+ * packet.
+ */
+ if (first)
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Fragment");
+ proto_tree_add_item(bs_tree, hf_ppp_hdlc_fragment, tvb, offset, -1, ENC_NA);
+ offset++;
+ length = tvb_captured_length_remaining(tvb, offset);
+ ppp_tvb = remove_escape_chars(tvb, pinfo, offset, length);
+ if (ppp_tvb != NULL) {
+ add_new_data_source(pinfo, ppp_tvb, "PPP Fragment");
+ call_data_dissector(ppp_tvb, pinfo, tree);
+ }
+ return tvb_captured_length(tvb);
+ }
+
+ data_offset = offset + 1; /* skip starting frame delimiter */
+ data_length = end_offset - data_offset;
+
+ /*
+ * Is that frame delimiter immediately followed by another one?
+ * Some PPP implementations put a frame delimiter at the
+ * beginning and the end of each frame, although RFC 1662
+ * appears only to require that there be one frame delimiter
+ * between adjacent frames:
+ *
+ * Each frame begins and ends with a Flag Sequence, which is the
+ * binary sequence 01111110 (hexadecimal 0x7e). All implementations
+ * continuously check for this flag, which is used for frame
+ * synchronization.
+ *
+ * Only one Flag Sequence is required between two frames. Two
+ * consecutive Flag Sequences constitute an empty frame, which is
+ * silently discarded, and not counted as a FCS error.
+ *
+ * If the delimiter at the end of this frame is followed by
+ * another delimiter, we consider the first delimiter part
+ * of this frame.
+ */
+ if (tvb_offset_exists(tvb, end_offset + 1) &&
+ tvb_get_guint8(tvb, end_offset+1) == 0x7e) {
+ end_offset++;
+ }
+ length = end_offset - offset;
+ proto_tree_add_item(bs_tree, hf_ppp_hdlc_data, tvb, offset, length, ENC_NA);
+ if (length > 1) {
+ ppp_tvb = remove_escape_chars(tvb, pinfo, data_offset, data_length);
+ if (ppp_tvb != NULL) {
+ pinfo->use_conv_addr_port_endpoints = save_use_conv_addr_port_endpoints;
+ pinfo->conv_addr_port_endpoints = save_conv_addr_port_endpoints;
+ pinfo->conv_elements = save_conv_elements;
+ add_new_data_source(pinfo, ppp_tvb, "PPP Message");
+ dissect_ppp_hdlc_common(ppp_tvb, pinfo, tree);
+ first = FALSE;
+ }
+ }
+ offset = end_offset;
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * At least for the PPP/USB captures I've seen, the data either starts with
+ * 0x7eff03 or 0x7eff7d23 or 0xff03, so this function performs that heuristic
+ * matching first before calling dissect_ppp_raw_hdlc(). Otherwise, if we call
+ * it directly for USB captures, some captures like the following will not be
+ * dissected correctly:
+ * https://gitlab.com/wireshark/wireshark/-/wikis/SampleCaptures#head-886e340c31ca977f321c921f81cbec4c21bb7738
+ */
+static gboolean
+dissect_ppp_usb( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
+{
+ /*
+ * In some cases, the 0x03 normally in byte 3 is escaped so we must look
+ * for the 2 byte sequence of 0x7d23 instead of 0x03. The 0x23 is
+ * generated by 0x20^0x03 per section 4.2 of:
+ * https://tools.ietf.org/html/rfc1662.html.
+ */
+ const guchar buf1[3] = {0x7e, 0xff, 0x03};
+ const guchar buf2[4] = {0x7e, 0xff, 0x7d, 0x23};
+ tvbuff_t *next_tvb;
+
+ if ((tvb_memeql(tvb, 0, buf2, sizeof(buf2)) == 0) ||
+ (tvb_memeql(tvb, 0, buf1, sizeof(buf1)) == 0)) {
+ dissect_ppp_raw_hdlc(tvb, pinfo, tree, data);
+ } else if ((tvb_memeql(tvb, 0, &buf1[1], sizeof(buf1) - 1) == 0) ||
+ (tvb_memeql(tvb, 0, &buf2[1], sizeof(buf2) - 1) == 0)) {
+ /* It's missing the 0x7e framing character. What TODO?
+ * Should we try faking it by sticking 0x7e in front? Or try telling
+ * dissect_ppp_raw_hdlc() NOT to look for the 0x7e frame deliminator?
+ * Or is this a bug in libpcap (used 1.1.0)?
+ * Or a bug in the Linux kernel (tested with 2.6.24.4) Or a bug in
+ * usbmon? Or is the data we're looking at really just part of the
+ * payload and not control data? Well, at least in my case it's
+ * definitely not, but not sure if this is always the case. Is this
+ * issue applicable only to PPP/USB or PPP/XYZ, in which case a more
+ * general solution should be found?
+ */
+ /* For now, just try skipping the framing I guess??? */
+ if (tvb_get_guint8(tvb, 1) == 0x03)
+ next_tvb = tvb_new_subset_remaining(tvb, 2);
+ else
+ next_tvb = tvb_new_subset_remaining(tvb, 3);
+ dissect_ppp(next_tvb, pinfo, tree, data);
+ } else if (tvb_get_guint8(tvb, 0) == 0x7e) {
+ /* Well, let's guess that since the 1st byte is 0x7e that it really is
+ * a PPP frame, and the address and control bytes are compressed (NULL)
+ * per https://tools.ietf.org/html/rfc1662, section 3.2, which means
+ * that they're omitted from the packet. */
+ next_tvb = tvb_new_subset_remaining(tvb, 1);
+ dissect_ppp_hdlc_common(next_tvb, pinfo, tree);
+ } else
+ return (FALSE);
+ return (TRUE);
+}
+
+void
+proto_register_ppp_raw_hdlc(void)
+{
+ static hf_register_info hf[] = {
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_ppp_hdlc_fragment, { "PPP Fragment", "ppp_hdlc.fragment", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_hdlc_data, { "PPP Data", "ppp_hdlc.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_ppp_hdlc_data
+ };
+
+ proto_ppp_hdlc = proto_register_protocol("PPP In HDLC-Like Framing", "PPP-HDLC", "ppp_hdlc");
+ ppp_raw_hdlc_handle = register_dissector("ppp_raw_hdlc", dissect_ppp_raw_hdlc, proto_ppp_hdlc);
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_ppp_hdlc, hf, array_length(hf));
+
+ register_capture_dissector_table("ppp_hdlc", "PPP-HDLC");
+ register_capture_dissector("ppp_hdlc", capture_ppp_hdlc, proto_ppp_hdlc);
+}
+
+void
+proto_reg_handoff_ppp_raw_hdlc(void)
+{
+ capture_dissector_handle_t ppp_hdlc_cap_handle;
+
+ dissector_add_uint("gre.proto", ETHERTYPE_CDMA2000_A10_UBS, ppp_raw_hdlc_handle);
+ dissector_add_uint("gre.proto", ETHERTYPE_3GPP2, ppp_raw_hdlc_handle);
+
+ /*
+ * The heuristic checks are rather weak. Each payload starting with
+ * 0x7e is accepted as a PPP over USB frame, this creates a lot of
+ * false positives. We disable the heuristic subdissector by
+ * default.
+ */
+ heur_dissector_add("usb.bulk", dissect_ppp_usb,
+ "PPP USB bulk endpoint", "ppp_usb_bulk", proto_ppp, HEURISTIC_DISABLE);
+
+ ppp_hdlc_cap_handle = find_capture_dissector("ppp_hdlc");
+ capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_cap_handle);
+ capture_dissector_add_uint("sll.ltype", LINUX_SLL_P_PPPHDLC, ppp_hdlc_cap_handle);
+ capture_dissector_add_uint("fr.nlpid", NLPID_PPP, ppp_hdlc_cap_handle);
+
+ chdlc_cap_handle = find_capture_dissector("chdlc");
+}
+
+/*
+ * Handles PAP just as a protocol field
+ */
+static int
+dissect_pap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti, *data_ti;
+ proto_tree *fh_tree, *data_tree = NULL;
+ guint8 code;
+ gchar *peer_id, *password, *message;
+ guint8 peer_id_length, password_length, message_length;
+ int offset = 0;
+
+ code = tvb_get_guint8(tvb, 0);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP PAP");
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str_const(code, pap_vals, "Unknown"));
+
+ ti = proto_tree_add_item(tree, proto_pap, tvb, 0, -1, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, ett_pap);
+
+ proto_tree_add_item(fh_tree, hf_pap_code, tvb, offset, 1,
+ ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(fh_tree, hf_pap_identifier, tvb, offset, 1,
+ ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(fh_tree, hf_pap_length, tvb, offset, 2,
+ ENC_BIG_ENDIAN);
+ offset += 2;
+
+ data_ti = proto_tree_add_item(fh_tree, hf_pap_data, tvb, offset, -1,
+ ENC_NA);
+ data_tree = proto_item_add_subtree(data_ti, ett_pap_data);
+
+ switch (code) {
+ case CONFREQ:
+ proto_tree_add_item(data_tree, hf_pap_peer_id_length, tvb, offset,
+ 1, ENC_BIG_ENDIAN);
+ peer_id_length = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ proto_tree_add_item(data_tree, hf_pap_peer_id, tvb, offset,
+ peer_id_length, ENC_ASCII);
+ peer_id = tvb_format_text(pinfo->pool, tvb, offset, peer_id_length);
+ offset += peer_id_length;
+
+ proto_tree_add_item(data_tree, hf_pap_password_length, tvb, offset,
+ 1, ENC_BIG_ENDIAN);
+ password_length = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ proto_tree_add_item(data_tree, hf_pap_password, tvb, offset,
+ password_length, ENC_ASCII);
+ password = tvb_format_text(pinfo->pool, tvb, offset, password_length);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (Peer-ID='%s', Password='%s')", peer_id, password);
+ break;
+
+ case CONFACK:
+ case CONFNAK:
+ proto_tree_add_item(data_tree, hf_pap_message_length, tvb, offset,
+ 1, ENC_BIG_ENDIAN);
+ message_length = tvb_get_guint8(tvb, offset);
+ offset +=1;
+
+ proto_tree_add_item(data_tree, hf_pap_message, tvb, offset,
+ message_length, ENC_ASCII);
+ message = tvb_format_text(pinfo->pool, tvb, offset, message_length);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Message='%s')",
+ message);
+ break;
+
+ default:
+ proto_tree_add_item(data_tree, hf_pap_stuff, tvb, offset, -1,
+ ENC_NA);
+ break;
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 1994
+ * Handles CHAP just as a protocol field
+ */
+static int
+dissect_chap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *fh_tree;
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 code, value_size;
+ guint32 length;
+ int offset;
+
+ code = tvb_get_guint8(tvb, 0);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP CHAP");
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str_const(code, chap_vals, "Unknown"));
+
+
+ /* Create CHAP protocol tree */
+ ti = proto_tree_add_item(tree, proto_chap, tvb, 0, -1, ENC_NA);
+ fh_tree = proto_item_add_subtree(ti, ett_chap);
+
+ proto_tree_add_item(fh_tree, hf_chap_code, tvb, 0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(fh_tree, hf_chap_identifier, tvb, 1, 1,
+ ENC_BIG_ENDIAN);
+
+ /* Length - make sure it's valid */
+ length = tvb_get_ntohs(tvb, 2);
+ if (length < 4) {
+ proto_tree_add_uint_format_value(fh_tree, hf_chap_length, tvb, 2, 2,
+ length, "%u (invalid, must be >= 4)", length);
+ return 4;
+ }
+ proto_item_set_len(ti, length);
+ proto_tree_add_item(fh_tree, hf_chap_length, tvb, 2, 2,
+ ENC_BIG_ENDIAN);
+
+ offset = 4; /* Offset moved to after length field */
+ length -= 4; /* Length includes previous 4 bytes, subtract */
+
+ switch (code) {
+ /* Challenge or Response data */
+ case CHAP_CHAL:
+ case CHAP_RESP:
+ if (length > 0) {
+ guint value_offset = 0;
+ guint name_offset = 0, name_size = 0;
+
+ /* Create data subtree */
+ tf = proto_tree_add_item(fh_tree, hf_chap_data, tvb, offset,
+ length, ENC_NA);
+ field_tree = proto_item_add_subtree(tf, ett_chap_data);
+ length--;
+
+ /* Value size */
+ value_size = tvb_get_guint8(tvb, offset);
+ if (value_size > length) {
+ proto_tree_add_uint_format_value(field_tree, hf_chap_value_size, tvb, offset, 1,
+ value_size, "%d byte%s (invalid, must be <= %u)",
+ value_size, plurality(value_size, "", "s"), length);
+ return offset;
+ }
+ proto_tree_add_item(field_tree, hf_chap_value_size, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ /* Value */
+ if (length > 0) {
+ value_offset = offset;
+ proto_tree_add_item(field_tree, hf_chap_value, tvb, offset,
+ value_size, ENC_NA);
+
+ /* Move along value_size bytes */
+ offset += value_size;
+ length -= value_size;
+
+ /* Find name in remaining bytes */
+ if (length > 0) {
+ proto_tree_add_item(field_tree, hf_chap_name, tvb,
+ offset, length, ENC_ASCII);
+ name_offset = offset;
+ name_size = length;
+ }
+
+ /* Show name and value in info column */
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (NAME='%s%s', VALUE=0x%s)",
+ tvb_format_text(pinfo->pool, tvb, name_offset,
+ (name_size > 20) ? 20 : name_size),
+ (name_size > 20) ? "..." : "",
+ (value_size > 0) ? tvb_bytes_to_str(pinfo->pool, tvb, value_offset, value_size) : "");
+ }
+ }
+ break;
+
+ /* Success or Failure data */
+ case CHAP_SUCC:
+ case CHAP_FAIL:
+ if (length > 0) {
+ proto_tree_add_item(fh_tree, hf_chap_message, tvb, offset,
+ length, ENC_ASCII);
+ }
+
+ /* Show message in info column */
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (MESSAGE='%s')",
+ tvb_format_text(pinfo->pool, tvb, offset, length));
+ break;
+
+ /* Code from unknown code type... */
+ default:
+ if (length > 0)
+ proto_tree_add_item(fh_tree, hf_chap_stuff, tvb, offset, length, ENC_NA);
+ break;
+ }
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * RFC 2472.
+ */
+static int
+dissect_ipv6cp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ dissect_cp(tvb, proto_ipv6cp, ett_ipv6cp, cp_vals, ett_ipv6cp_options, ipv6cp_option_table, pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_ipv6cp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *name)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format_value(tree, hf_ipv6cp_opt_type, tvb, offset, 1,
+ type, "%s (%u)", name, type);
+ proto_tree_add_item(tree, hf_ipv6cp_opt_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
+}
+
+static gboolean
+dissect_ipv6cp_fixed_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int proto, int ett, int expected_length,
+ proto_tree** ret_tree, proto_item** ret_item)
+{
+ if (!ppp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), expected_length))
+ return FALSE;
+
+ *ret_item = proto_tree_add_item(tree, proto, tvb, 0, expected_length, ENC_NA);
+ *ret_tree = proto_item_add_subtree(*ret_item, ett);
+
+ dissect_ipv6cp_opt_type_len(tvb, 0, *ret_tree, proto_registrar_get_name(proto));
+ return TRUE;
+}
+
+static int
+dissect_ipv6cp_if_id_opt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree* field_tree;
+ proto_item* tf;
+ int offset = 0;
+
+ if (!dissect_ipv6cp_fixed_opt(tvb, pinfo, tree, proto_ipv6cp_option_if_id, ett_ipv6cp_if_id_opt, 10,
+ &field_tree, &tf))
+ return tvb_captured_length(tvb);
+
+ proto_tree_add_item(field_tree, hf_ipv6cp_interface_identifier, tvb, offset+2, 8, ENC_NA);
+ return tvb_captured_length(tvb);
+}
+
+void
+proto_register_ppp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ppp_direction,
+ { "Direction", "ppp.direction", FT_UINT8, BASE_DEC,
+ VALS(ppp_direction_vals), 0x0, "PPP direction", HFILL }},
+ { &hf_ppp_address,
+ { "Address", "ppp.address", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_control,
+ { "Control", "ppp.control", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_protocol,
+ { "Protocol", "ppp.protocol", FT_UINT16, BASE_HEX|BASE_EXT_STRING,
+ &ppp_vals_ext, 0x0, NULL, HFILL }},
+ { &hf_ppp_code,
+ { "Code", "ppp.code", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_identifier,
+ { "Identifier", "ppp.identifier", FT_UINT8, BASE_DEC_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_length,
+ { "Length", "ppp.length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_magic_number,
+ { "Magic Number", "ppp.magic_number", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_oui,
+ { "OUI", "ppp.oui", FT_UINT24, BASE_OUI,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_kind,
+ { "Kind", "ppp.kind", FT_UINT8, BASE_DEC_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_data,
+ { "Data", "ppp.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_fcs_16,
+ { "FCS 16", "ppp.fcs_16", FT_UINT16, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_fcs_32,
+ { "FCS 32", "ppp.fcs_32", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ppp_fcs_status,
+ { "FCS Status", "ppp.fcs.status", FT_UINT8, BASE_NONE,
+ VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ppp,
+ &ett_ppp_opt_type,
+ &ett_ppp_unknown_opt
+ };
+ static ei_register_info ei[] = {
+ { &ei_ppp_opt_len_invalid, { "ppp.opt.len.invalid", PI_PROTOCOL, PI_WARN, "Invalid length for option", EXPFILL }},
+ { &ei_ppp_fcs, { "ppp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
+ };
+
+ module_t *ppp_module;
+ expert_module_t* expert_ppp;
+
+ proto_ppp = proto_register_protocol("Point-to-Point Protocol", "PPP", "ppp");
+ proto_register_field_array(proto_ppp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_ppp = expert_register_protocol(proto_ppp);
+ expert_register_field_array(expert_ppp, ei, array_length(ei));
+
+ /* subdissector code */
+ ppp_subdissector_table = register_dissector_table("ppp.protocol",
+ "PPP protocol", proto_ppp, FT_UINT16, BASE_HEX);
+
+ ppp_hdlc_handle = register_dissector("ppp_hdlc", dissect_ppp_hdlc, proto_ppp);
+ register_dissector("ppp_lcp_options", dissect_lcp_options, proto_ppp);
+ ppp_handle = register_dissector("ppp", dissect_ppp, proto_ppp);
+
+ /* Register the preferences for the ppp protocol */
+ ppp_module = prefs_register_protocol(proto_ppp, NULL);
+
+ prefs_register_enum_preference(ppp_module, "fcs_type",
+ "PPP Frame Checksum Type",
+ "The type of PPP frame checksum (none, 16-bit, 32-bit)",
+ &ppp_fcs_decode, fcs_options, FALSE);
+ prefs_register_obsolete_preference(ppp_module, "decompress_vj");
+ prefs_register_uint_preference(ppp_module, "default_proto_id",
+ "PPPMuxCP Default PID (in hex)",
+ "Default Protocol ID to be used for PPPMuxCP",
+ 16, &pppmux_def_prot_id);
+}
+
+void
+proto_reg_handoff_ppp(void)
+{
+ /*
+ * Get a handle for the CHDLC dissector.
+ */
+ chdlc_handle = find_dissector_add_dependency("chdlc", proto_ppp);
+
+ dissector_add_uint("fr.nlpid", NLPID_PPP, ppp_handle);
+
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_handle);
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP_WITH_PHDR,
+ ppp_hdlc_handle);
+ dissector_add_uint("sll.ltype", LINUX_SLL_P_PPPHDLC, ppp_hdlc_handle);
+ dissector_add_uint("osinl.excl", NLPID_PPP, ppp_handle);
+ dissector_add_uint("gre.proto", ETHERTYPE_PPP, ppp_hdlc_handle);
+ dissector_add_uint("juniper.proto", JUNIPER_PROTO_PPP, ppp_handle);
+ dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_PPP, ppp_hdlc_handle);
+ dissector_add_uint("l2tp.pw_type", L2TPv3_PW_PPP, ppp_hdlc_handle);
+}
+
+void
+proto_register_mp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mp_frag,
+ { "Fragment", "mp.frag", FT_UINT8, BASE_HEX,
+ NULL, MP_FRAG_MASK, NULL, HFILL }},
+ { &hf_mp_frag_short,
+ { "Fragment", "mp.frag", FT_UINT8, BASE_HEX,
+ NULL, MP_FRAG_MASK_SHORT, NULL, HFILL }},
+ { &hf_mp_frag_first,
+ { "First fragment", "mp.first", FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), MP_FRAG_FIRST, NULL, HFILL }},
+ { &hf_mp_frag_last,
+ { "Last fragment", "mp.last", FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), MP_FRAG_LAST, NULL, HFILL }},
+ { &hf_mp_sequence_num,
+ { "Sequence number", "mp.seq", FT_UINT24, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_mp_sequence_num_cls,
+ { "Class", "mp.sequence_num_cls", FT_UINT8, BASE_DEC,
+ NULL, MP_FRAG_CLS, NULL, HFILL }},
+ { &hf_mp_sequence_num_reserved,
+ { "Reserved", "mp.sequence_num_reserved", FT_BOOLEAN, 8,
+ NULL, MP_FRAG_RESERVED, NULL, HFILL }},
+ { &hf_mp_short_sequence_num,
+ { "Short Sequence number", "mp.sseq", FT_UINT16, BASE_DEC,
+ NULL, 0x0FFF, NULL, HFILL }},
+ { &hf_mp_short_sequence_num_cls,
+ { "Class", "mp.short_sequence_num_cls", FT_UINT8, BASE_DEC,
+ NULL, MP_FRAG_CLS_SHORT, NULL, HFILL }},
+ { &hf_mp_payload,
+ {"Payload", "mp.payload", FT_BYTES, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragments,
+ {"Message fragments", "mp.fragments", FT_NONE, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment,
+ {"Message fragment", "mp.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment_overlap,
+ {"Message fragment overlap", "mp.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment_overlap_conflicts,
+ {"Message fragment overlapping with conflicting data", "mp.fragment.overlap.conflicts",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment_multiple_tails,
+ {"Message has multiple tail fragments", "mp.fragment.multiple_tails",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment_too_long_fragment,
+ {"Message fragment too long", "mp.fragment.too_long_fragment",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment_error,
+ {"Message defragmentation error", "mp.fragment.error",
+ FT_FRAMENUM, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_fragment_count,
+ {"Message fragment count", "mp.fragment.count", FT_UINT32, BASE_DEC,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_reassembled_in,
+ {"Reassembled in", "mp.reassembled.in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x00, NULL, HFILL }},
+ { &hf_mp_reassembled_length,
+ {"Reassembled length", "mp.reassembled.length", FT_UINT32, BASE_DEC,
+ NULL, 0x00, NULL, HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_mp,
+ &ett_mp_flags,
+ &ett_mp_fragment,
+ &ett_mp_fragments
+ };
+
+ module_t *mp_module;
+
+ proto_mp = proto_register_protocol("PPP Multilink Protocol", "PPP MP", "mp");
+ mp_handle = register_dissector("mp", dissect_mp, proto_mp);
+ proto_register_field_array(proto_mp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ reassembly_table_register(&mp_reassembly_table,
+ &addresses_reassembly_table_functions);
+
+ /* Register the preferences for the PPP multilink protocol */
+ mp_module = prefs_register_protocol(proto_mp, NULL);
+
+ prefs_register_bool_preference(mp_module, "short_seqno",
+ "Short sequence numbers",
+ "Whether PPP Multilink frames use 12-bit sequence numbers",
+ &mp_short_seqno);
+ prefs_register_uint_preference(mp_module, "max_fragments",
+ "Maximum fragments",
+ "Maximum number of PPP Multilink fragments to try to reassemble into one frame",
+ 10, &mp_max_fragments);
+ prefs_register_uint_preference(mp_module, "fragment_aging",
+ "Max unreassembled fragment age",
+ "Age off unreassembled fragments after this many packets",
+ 10, &mp_fragment_aging);
+}
+
+void
+proto_reg_handoff_mp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_MP, mp_handle);
+}
+
+void
+proto_register_lcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lcp_magic_number,
+ { "Magic Number", "lcp.magic_number", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_data,
+ { "Data", "lcp.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_message,
+ { "Message", "lcp.message", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_secs_remaining,
+ { "Seconds Remaining", "lcp.secs_remaining", FT_UINT32, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_rej_proto,
+ { "Rejected Protocol", "lcp.rej_proto", FT_UINT16,
+ BASE_HEX | BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_type,
+ { "Type", "lcp.opt.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_length,
+ { "Length", "lcp.opt.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_oui,
+ { "OUI", "lcp.opt.oui", FT_UINT24, BASE_OUI,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_kind,
+ { "Kind", "lcp.opt.kind", FT_UINT8, BASE_DEC_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_data,
+ { "Data", "lcp.opt.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_mru,
+ { "Maximum Receive Unit", "lcp.opt.mru", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap,
+ { "Async Control Character Map", "lcp.opt.asyncmap", FT_UINT32,
+ BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_nul,
+ { "NUL", "lcp.opt.asyncmap.nul", FT_BOOLEAN, 32,
+ NULL, 0x00000001, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_soh,
+ { "SOH", "lcp.opt.asyncmap.soh", FT_BOOLEAN, 32,
+ NULL, 0x00000002, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_stx,
+ { "STX", "lcp.opt.asyncmap.stx", FT_BOOLEAN, 32,
+ NULL, 0x00000004, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_etx,
+ { "ETX", "lcp.opt.asyncmap.etx", FT_BOOLEAN, 32,
+ NULL, 0x00000008, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_eot,
+ { "EOT", "lcp.opt.asyncmap.eot", FT_BOOLEAN, 32,
+ NULL, 0x00000010, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_enq,
+ { "ENQ", "lcp.opt.asyncmap.enq", FT_BOOLEAN, 32,
+ NULL, 0x00000020, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_ack,
+ { "ACK", "lcp.opt.asyncmap.ack", FT_BOOLEAN, 32,
+ NULL, 0x00000040, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_bel,
+ { "BEL", "lcp.opt.asyncmap.bel", FT_BOOLEAN, 32,
+ NULL, 0x00000080, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_bs,
+ { "BS", "lcp.opt.asyncmap.bs", FT_BOOLEAN, 32,
+ NULL, 0x00000100, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_ht,
+ { "HT", "lcp.opt.asyncmap.ht", FT_BOOLEAN, 32,
+ NULL, 0x00000200, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_lf,
+ { "LF", "lcp.opt.asyncmap.lf", FT_BOOLEAN, 32,
+ NULL, 0x00000400, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_vt,
+ { "VT", "lcp.opt.asyncmap.vt", FT_BOOLEAN, 32,
+ NULL, 0x00000800, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_ff,
+ { "FF", "lcp.opt.asyncmap.ff", FT_BOOLEAN, 32,
+ NULL, 0x00001000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_cr,
+ { "CR", "lcp.opt.asyncmap.cr", FT_BOOLEAN, 32,
+ NULL, 0x00002000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_so,
+ { "SO", "lcp.opt.asyncmap.so", FT_BOOLEAN, 32,
+ NULL, 0x00004000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_si,
+ { "SI", "lcp.opt.asyncmap.si", FT_BOOLEAN, 32,
+ NULL, 0x00008000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_dle,
+ { "DLE", "lcp.opt.asyncmap.dle", FT_BOOLEAN, 32,
+ NULL, 0x00010000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_dc1,
+ { "DC1 (XON)", "lcp.opt.asyncmap.dc1", FT_BOOLEAN, 32,
+ NULL, 0x00020000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_dc2,
+ { "DC2", "lcp.opt.asyncmap.dc2", FT_BOOLEAN, 32,
+ NULL, 0x00040000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_dc3,
+ { "DC3 (XOFF)", "lcp.opt.asyncmap.dc3", FT_BOOLEAN, 32,
+ NULL, 0x00080000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_dc4,
+ { "DC4", "lcp.opt.asyncmap.dc4", FT_BOOLEAN, 32,
+ NULL, 0x00100000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_nak,
+ { "NAK", "lcp.opt.asyncmap.nak", FT_BOOLEAN, 32,
+ NULL, 0x00200000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_syn,
+ { "SYN", "lcp.opt.asyncmap.syn", FT_BOOLEAN, 32,
+ NULL, 0x00400000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_etb,
+ { "ETB", "lcp.opt.asyncmap.etb", FT_BOOLEAN, 32,
+ NULL, 0x00800000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_can,
+ { "CAN", "lcp.opt.asyncmap.can", FT_BOOLEAN, 32,
+ NULL, 0x01000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_em,
+ { "EM", "lcp.opt.asyncmap.em", FT_BOOLEAN, 32,
+ NULL, 0x02000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_sub,
+ { "SUB", "lcp.opt.asyncmap.sub", FT_BOOLEAN, 32,
+ NULL, 0x04000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_esc,
+ { "ESC", "lcp.opt.asyncmap.esc", FT_BOOLEAN, 32,
+ NULL, 0x08000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_fs,
+ { "FS", "lcp.opt.asyncmap.fs", FT_BOOLEAN, 32,
+ NULL, 0x10000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_gs,
+ { "GS", "lcp.opt.asyncmap.gs", FT_BOOLEAN, 32,
+ NULL, 0x20000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_rs,
+ { "RS", "lcp.opt.asyncmap.rs", FT_BOOLEAN, 32,
+ NULL, 0x40000000, NULL, HFILL }},
+ { &hf_lcp_opt_asyncmap_us,
+ { "US", "lcp.opt.asyncmap.us", FT_BOOLEAN, 32,
+ NULL, 0x80000000, NULL, HFILL }},
+ { &hf_lcp_opt_auth_protocol,
+ { "Authentication Protocol", "lcp.opt.auth_protocol", FT_UINT16,
+ BASE_HEX | BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_algorithm,
+ { "Algorithm", "lcp.opt.algorithm", FT_UINT8,
+ BASE_DEC | BASE_RANGE_STRING, &chap_alg_rvals,
+ 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_quality_protocol,
+ { "Quality Protocol", "lcp.opt.quality_protocol", FT_UINT16,
+ BASE_HEX | BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_magic_number,
+ { "Magic Number", "lcp.opt.magic_number", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_reportingperiod,
+ { "Reporting Period", "lcp.opt.reporting_period", FT_UINT32,
+ BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0,
+ "Maximum time in micro-seconds that the remote end should "
+ "wait between transmission of LCP Link-Quality-Report packets",
+ HFILL }},
+ { &hf_lcp_opt_fcs_alternatives,
+ { "FCS Alternatives", "lcp.opt.fcs_alternatives", FT_UINT8,
+ BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_fcs_alternatives_null,
+ { "NULL FCS", "lcp.opt.fcs_alternatives.null", FT_BOOLEAN, 8,
+ NULL, 0x01, NULL, HFILL }},
+ { &hf_lcp_opt_fcs_alternatives_ccitt16,
+ { "CCITT 16-bit", "lcp.opt.fcs_alternatives.ccitt16", FT_BOOLEAN,
+ 8, NULL, 0x02, NULL, HFILL }},
+ { &hf_lcp_opt_fcs_alternatives_ccitt32,
+ { "CCITT 32-bit", "lcp.opt.fcs_alternatives.ccitt32", FT_BOOLEAN,
+ 8, NULL, 0x04, NULL, HFILL }},
+ { &hf_lcp_opt_maximum,
+ { "Maximum", "lcp.opt.maximum", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0,
+ "The largest number of padding octets which may be added "
+ "to the frame.", HFILL }},
+ { &hf_lcp_opt_window,
+ { "Window", "lcp.opt.window", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_frame_frames, 0x0,
+ "The number of frames the receiver will buffer.", HFILL }},
+ { &hf_lcp_opt_hdlc_address,
+ { "Address", "lcp.opt.hdlc_address", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "An HDLC Address as specified in ISO 3309.", HFILL }},
+ { &hf_lcp_opt_operation,
+ { "Operation", "lcp.opt.operation", FT_UINT8, BASE_DEC,
+ VALS(callback_op_vals), 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_message,
+ { "Message", "lcp.opt.message", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_mrru,
+ { "MRRU", "lcp.opt.mrru", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum Receive Reconstructed Unit", HFILL }},
+ { &hf_lcp_opt_ep_disc_class,
+ { "Class", "lcp.opt.ep_disc_class", FT_UINT8, BASE_DEC,
+ VALS(multilink_ep_disc_class_vals), 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_ip_address,
+ { "IP Address", "lcp.opt.ip_address", FT_IPv4, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_802_1_address,
+ { "IEEE 802.1 Address", "lcp.opt.802_1_address", FT_ETHER,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_magic_block,
+ { "PPP Magic-Number Block", "lcp.opt.magic_block", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_psndn,
+ { "Public Switched Network Directory Number", "lcp.opt.psndn",
+ FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_mode,
+ { "Mode", "lcp.opt.mode", FT_UINT8, BASE_DEC,
+ VALS(dce_id_mode_vals), 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_unused,
+ { "Unused", "lcp.opt.unused", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_link_discrim,
+ { "Link Discriminator", "lcp.opt.link_discrim", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_id,
+ { "Identification", "lcp.opt.id", FT_UINT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_cobs_flags,
+ { "Flags", "lcp.opt.flags", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_cobs_flags_res,
+ { "Reserved", "lcp.opt.flags.reserved", FT_UINT8, BASE_HEX,
+ NULL, 0xFC, NULL, HFILL }},
+ { &hf_lcp_opt_cobs_flags_pre,
+ { "PRE", "lcp.opt.flags.pre", FT_BOOLEAN, 8,
+ NULL, 0x02, "Preemption", HFILL }},
+ { &hf_lcp_opt_cobs_flags_zxe,
+ { "ZXE", "lcp.opt.flags.zxe", FT_BOOLEAN, 8,
+ NULL, 0x01, "Zero pair/run elimination", HFILL }},
+ { &hf_lcp_opt_class,
+ { "Class", "lcp.opt.class", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_prefix,
+ { "Prefix", "lcp.opt.prefix", FT_UINT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_code,
+ { "Code", "lcp.opt.code", FT_UINT8, BASE_DEC,
+ VALS(ml_hdr_fmt_code_vals), 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_max_susp_classes,
+ { "Max suspendable classes", "lcp.opt.max_susp_classes",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_lcp_opt_MIBenum,
+ { "MIBenum", "lcp.opt.MIBenum", FT_UINT32,
+ BASE_DEC | BASE_EXT_STRING, &charset_vals_ext, 0x0,
+ "A unique integer value identifying a charset", HFILL }},
+ { &hf_lcp_opt_language_tag,
+ { "Language-Tag", "lcp.opt.language_tag", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_lcp,
+ &ett_lcp_options,
+ &ett_lcp_vendor_opt,
+ &ett_lcp_mru_opt,
+ &ett_lcp_asyncmap_opt,
+ &ett_lcp_authprot_opt,
+ &ett_lcp_qualprot_opt,
+ &ett_lcp_magicnumber_opt,
+ &ett_lcp_linkqualmon_opt,
+ &ett_lcp_pcomp_opt,
+ &ett_lcp_acccomp_opt,
+ &ett_lcp_fcs_alternatives_opt,
+ &ett_lcp_self_desc_pad_opt,
+ &ett_lcp_numbered_mode_opt,
+ &ett_lcp_callback_opt,
+ &ett_lcp_compound_frames_opt,
+ &ett_lcp_nomdataencap_opt,
+ &ett_lcp_multilink_mrru_opt,
+ &ett_lcp_multilink_ssnh_opt,
+ &ett_lcp_multilink_ep_disc_opt,
+ &ett_lcp_magic_block,
+ &ett_lcp_dce_identifier_opt,
+ &ett_lcp_multilink_pp_opt,
+ &ett_lcp_bacp_link_discrim_opt,
+ &ett_lcp_auth_opt,
+ &ett_lcp_cobs_opt,
+ &ett_lcp_prefix_elision_opt,
+ &ett_multilink_hdr_fmt_opt,
+ &ett_lcp_internationalization_opt,
+ &ett_lcp_sonet_sdh_opt
+ };
+
+ proto_lcp = proto_register_protocol("PPP Link Control Protocol", "PPP LCP", "lcp");
+ lcp_handle = register_dissector("lcp", dissect_lcp, proto_lcp);
+ proto_register_field_array(proto_lcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ lcp_option_table = register_dissector_table("lcp.option", "PPP LCP Options", proto_lcp, FT_UINT8, BASE_DEC);
+
+ /* Register LCP options as their own protocols so we can get the name of the option */
+ proto_lcp_option_vendor = proto_register_protocol_in_name_only("Vendor Specific", "Vendor Specific", "lcp.opt.vendor", proto_lcp, FT_BYTES);
+ proto_lcp_option_mru = proto_register_protocol_in_name_only("Maximum Receive Unit", "Maximum Receive Unit", "lcp.opt.mtu_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_async_map = proto_register_protocol_in_name_only("Async Control Character Map", "Async Control Character Map", "lcp.opt.asyncmap_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_authprot = proto_register_protocol_in_name_only("Authentication Protocol", "Authentication Protocol", "lcp.opt.auth_protocol_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_qualprot = proto_register_protocol_in_name_only("Quality Protocol", "Quality Protocol", "lcp.opt.quality_protocol_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_magicnumber = proto_register_protocol_in_name_only("Magic Number", "Magic Number", "lcp.opt.magic_number_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_linkqualmon = proto_register_protocol_in_name_only("Link Quality Monitoring", "Link Quality Monitoring", "lcp.opt.linkqualmon", proto_lcp, FT_BYTES);
+ proto_lcp_option_field_compress = proto_register_protocol_in_name_only("Protocol Field Compression", "Protocol Field Compression", "lcp.opt.field_compress", proto_lcp, FT_BYTES);
+ proto_lcp_option_addr_field_compress = proto_register_protocol_in_name_only("Address and Control Field Compression", "Address and Control Field Compression", "lcp.opt.addr_field_compress", proto_lcp, FT_BYTES);
+ proto_lcp_option_fcs_alternatives = proto_register_protocol_in_name_only("FCS Alternatives", "FCS Alternatives", "lcp.opt.fcs_alternatives_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_self_desc_pad = proto_register_protocol_in_name_only("Self Describing Pad", "Self Describing Pad", "lcp.opt.self_desc_pad", proto_lcp, FT_BYTES);
+ proto_lcp_option_numbered_mode = proto_register_protocol_in_name_only("Numbered Mode", "Numbered Mode", "lcp.opt.numbered_mode", proto_lcp, FT_BYTES);
+ /* TODO? CI_MULTILINK_PROC */
+ proto_lcp_option_callback = proto_register_protocol_in_name_only("Callback", "Callback", "lcp.opt.callback", proto_lcp, FT_BYTES);
+ /* TODO? CI_CONNECTTIME */
+ proto_lcp_option_compound_frames = proto_register_protocol_in_name_only("Compound Frames (Deprecated)", "Compound Frames (Deprecated)", "lcp.opt.compound_frames", proto_lcp, FT_BYTES);
+ proto_lcp_option_nomdataencap = proto_register_protocol_in_name_only("Nominal Data Encapsulation (Deprecated)", "Nominal Data Encapsulation (Deprecated)", "lcp.opt.nomdataencap", proto_lcp, FT_BYTES);
+ proto_lcp_option_multilink_mrru = proto_register_protocol_in_name_only("Multilink MRRU", "Multilink MRRU", "lcp.opt.multilink_mrru", proto_lcp, FT_BYTES);
+ proto_lcp_option_multilink_ssnh = proto_register_protocol_in_name_only("Multilink Short Sequence Number Header", "Multilink Short Sequence Number Header", "lcp.opt.multilink_ssnh", proto_lcp, FT_BYTES);
+ proto_lcp_option_multilink_ep_disc = proto_register_protocol_in_name_only("Multilink Endpoint Discriminator", "Multilink Endpoint Discriminator", "lcp.opt.multilink_ep_disc", proto_lcp, FT_BYTES);
+ /* TODO? CI_PROP_KEN: ken@funk.com: www.funk.com => www.juniper.net */
+ proto_lcp_option_dce_identifier = proto_register_protocol_in_name_only("DCE Identifier", "DCE Identifier", "lcp.opt.dce_identifier", proto_lcp, FT_BYTES);
+ proto_lcp_option_multilink_pp = proto_register_protocol_in_name_only("Multi Link Plus Procedure", "Multi Link Plus Procedure", "lcp.opt.multilink_pp", proto_lcp, FT_BYTES);
+ proto_lcp_option_link_discrim = proto_register_protocol_in_name_only("Link Discriminator for BACP", "Link Discriminator for BACP", "lcp.opt.link_discrim_bytes", proto_lcp, FT_BYTES);
+ proto_lcp_option_auth = proto_register_protocol_in_name_only("Authentication Option", "Authentication Option", "lcp.opt.auth", proto_lcp, FT_BYTES);
+ proto_lcp_option_cobs = proto_register_protocol_in_name_only("Consistent Overhead Byte Stuffing (COBS)", "Consistent Overhead Byte Stuffing (COBS)", "lcp.opt.cobs", proto_lcp, FT_BYTES);
+ proto_lcp_option_prefix_elision = proto_register_protocol_in_name_only("Prefix Elision", "Prefix Elision", "lcp.opt.prefix_elision", proto_lcp, FT_BYTES);
+ proto_lcp_option_multilink_hdr_fmt = proto_register_protocol_in_name_only("Multilink header format", "Multilink header format", "lcp.opt.multilink_hdr_fmt", proto_lcp, FT_BYTES);
+ proto_lcp_option_internationalization = proto_register_protocol_in_name_only("Internationalization", "Internationalization", "lcp.opt.internationalization", proto_lcp, FT_BYTES);
+ proto_lcp_option_sonet_sdh = proto_register_protocol_in_name_only("Simple Data Link on SONET/SDH", "Simple Data Link on SONET/SDH", "lcp.opt.sonet_sdh", proto_lcp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_lcp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_LCP, lcp_handle);
+
+ /*
+ * NDISWAN on Windows translates Ethernet frames from higher-level
+ * protocols into PPP frames to hand to the PPP driver, and translates
+ * PPP frames from the PPP driver to hand to the higher-level protocols.
+ *
+ * Apparently the PPP driver, on at least some versions of Windows,
+ * passes frames for internal-to-PPP protocols up through NDISWAN;
+ * the protocol type field appears to be passed through unchanged
+ * (unlike what's done with, for example, the protocol type field
+ * for IP, which is mapped from its PPP value to its Ethernet value).
+ *
+ * This means that we may see, on Ethernet captures, frames for
+ * protocols internal to PPP, so we register PPP_LCP with the
+ * "ethertype" dissector table as well as the PPP protocol dissector
+ * table.
+ */
+ dissector_add_uint("ethertype", PPP_LCP, lcp_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add_uint("sm_pco.protocol", PPP_LCP, lcp_handle);
+
+ /* Create dissection function handles for all LCP options */
+ dissector_add_uint("lcp.option", CI_VENDORSPECIFIC, create_dissector_handle( dissect_lcp_vendor_opt, proto_lcp_option_vendor ));
+ dissector_add_uint("lcp.option", CI_MRU, create_dissector_handle( dissect_lcp_mru_opt, proto_lcp_option_mru ));
+ dissector_add_uint("lcp.option", CI_ASYNCMAP, create_dissector_handle( dissect_lcp_async_map_opt, proto_lcp_option_async_map ));
+ dissector_add_uint("lcp.option", CI_AUTHPROT, create_dissector_handle( dissect_lcp_authprot_opt, proto_lcp_option_authprot ));
+ dissector_add_uint("lcp.option", CI_QUALITY, create_dissector_handle( dissect_lcp_qualprot_opt, proto_lcp_option_qualprot ));
+ dissector_add_uint("lcp.option", CI_MAGICNUMBER, create_dissector_handle( dissect_lcp_magicnumber_opt, proto_lcp_option_magicnumber ));
+ dissector_add_uint("lcp.option", CI_LINKQUALMON, create_dissector_handle( dissect_lcp_linkqualmon_opt, proto_lcp_option_linkqualmon ));
+ dissector_add_uint("lcp.option", CI_PCOMPRESSION, create_dissector_handle( dissect_lcp_field_compress, proto_lcp_option_field_compress ));
+ dissector_add_uint("lcp.option", CI_ACCOMPRESSION, create_dissector_handle( dissect_lcp_addr_field_compress, proto_lcp_option_addr_field_compress ));
+ dissector_add_uint("lcp.option", CI_FCS_ALTERNATIVES, create_dissector_handle( dissect_lcp_fcs_alternatives_opt, proto_lcp_option_fcs_alternatives ));
+ dissector_add_uint("lcp.option", CI_SELF_DESCRIBING_PAD, create_dissector_handle( dissect_lcp_self_describing_pad_opt, proto_lcp_option_self_desc_pad ));
+ dissector_add_uint("lcp.option", CI_NUMBERED_MODE, create_dissector_handle( dissect_lcp_numbered_mode_opt, proto_lcp_option_numbered_mode ));
+ /* TODO? CI_MULTILINK_PROC */
+ dissector_add_uint("lcp.option", CI_CALLBACK, create_dissector_handle( dissect_lcp_callback_opt, proto_lcp_option_callback ));
+ /* TODO? CI_CONNECTTIME */
+ dissector_add_uint("lcp.option", CI_COMPOUND_FRAMES, create_dissector_handle( dissect_lcp_compound_frames_opt, proto_lcp_option_compound_frames ));
+ dissector_add_uint("lcp.option", CI_NOMDATAENCAP, create_dissector_handle( dissect_lcp_nomdataencap_opt, proto_lcp_option_nomdataencap ));
+ dissector_add_uint("lcp.option", CI_MULTILINK_MRRU, create_dissector_handle( dissect_lcp_multilink_mrru_opt, proto_lcp_option_multilink_mrru ));
+ dissector_add_uint("lcp.option", CI_MULTILINK_SSNH, create_dissector_handle( dissect_lcp_multilink_ssnh_opt, proto_lcp_option_multilink_ssnh ));
+ dissector_add_uint("lcp.option", CI_MULTILINK_EP_DISC, create_dissector_handle( dissect_lcp_multilink_ep_disc_opt, proto_lcp_option_multilink_ep_disc ));
+ /* TODO? CI_PROP_KEN: ken@funk.com: www.funk.com => www.juniper.net */
+ dissector_add_uint("lcp.option", CI_DCE_IDENTIFIER, create_dissector_handle( dissect_lcp_dce_identifier_opt, proto_lcp_option_dce_identifier ));
+ dissector_add_uint("lcp.option", CI_MULTILINK_PLUS_PROC, create_dissector_handle( dissect_lcp_multilink_pp_opt, proto_lcp_option_multilink_pp ));
+ dissector_add_uint("lcp.option", CI_LINK_DISC_FOR_BACP, create_dissector_handle( dissect_lcp_bacp_link_discriminator_opt, proto_lcp_option_link_discrim ));
+ dissector_add_uint("lcp.option", CI_LCP_AUTHENTICATION, create_dissector_handle( dissect_lcp_auth_opt, proto_lcp_option_auth ));
+ dissector_add_uint("lcp.option", CI_COBS, create_dissector_handle( dissect_lcp_cobs_opt, proto_lcp_option_cobs ));
+ dissector_add_uint("lcp.option", CI_PREFIX_ELISION, create_dissector_handle( dissect_lcp_prefix_elision_opt, proto_lcp_option_prefix_elision ));
+ dissector_add_uint("lcp.option", CI_MULTILINK_HDR_FMT, create_dissector_handle( dissect_lcp_multilink_hdr_fmt_opt, proto_lcp_option_multilink_hdr_fmt ));
+ dissector_add_uint("lcp.option", CI_INTERNATIONALIZATION, create_dissector_handle( dissect_lcp_internationalization_opt, proto_lcp_option_internationalization ));
+ dissector_add_uint("lcp.option", CI_SDL_ON_SONET_SDH, create_dissector_handle( dissect_lcp_sonet_sdh_opt, proto_lcp_option_sonet_sdh ));
+}
+
+void
+proto_register_vsncp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_vsncp_opt_type, { "Type", "vsncp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_opt_length, { "Length", "vsncp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_vsncp_pdn_identifier, { "PDN Identifier", "vsncp.pdn_identifier", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_attach_type, { "Attach Type", "vsncp.attach_type", FT_UINT8, BASE_HEX, VALS(vsncp_attach_vals), 0x0, NULL, HFILL }},
+ { &hf_vsncp_pdn_type, { "PDN Type", "vsncp.pdn_type", FT_UINT8, BASE_HEX, VALS(vsncp_pdntype_vals), 0x0, NULL, HFILL }},
+ { &hf_vsncp_error_code, { "Error Code", "vsncp.error_code", FT_UINT8, BASE_HEX, VALS(vsncp_errorcode_vals), 0x0, NULL, HFILL }},
+ { &hf_vsncp_pdn_ipv4, { "PDN IPv4", "vsncp.pdn_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_pdn_ipv6, { "PDN IPv6", "vsncp.pdn_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_default_router_address, { "IPv4 Default Router Address", "vsncp.default_router_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_access_point_name, { "Access Point Name Label", "vsncp.access_point_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_address_allocation_cause, { "Address Allocation Cause", "vsncp.address_allocation_cause", FT_UINT8, BASE_HEX, VALS(vsncp_alloc_vals), 0x0, NULL, HFILL }},
+ { &hf_vsncp_ambr_data, { "AMBR Data", "vsncp.ambr_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_ipv6_interface_identifier, { "IPv6 interface identifier", "vsncp.ipv6_interface_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_protocol, { "Protocol", "vsncp.protocol", FT_UINT16, BASE_HEX, VALS(vsncp_pco_vals), 0x0, NULL, HFILL }},
+ { &hf_vsncp_protocol_configuration_length, { "Length", "vsncp.protocol_configuration_length", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_protocol_configuration_data, { "Data", "vsncp.protocol_configuration_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_code, { "Code", "vsncp.code", FT_UINT8, BASE_HEX, VALS(cp_vals), 0x0, NULL, HFILL }},
+ { &hf_vsncp_identifier, { "Identifier", "vsncp.identifier", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_vsncp_length, { "Length", "vsncp.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_vsncp,
+ &ett_vsncp_options,
+ &ett_vsncp_pdnid_opt,
+ &ett_vsncp_apname_opt,
+ &ett_vsncp_pdntype_opt,
+ &ett_vsncp_pdnaddress_opt,
+ &ett_vsncp_pco_opt,
+ &ett_vsncp_errorcode_opt,
+ &ett_vsncp_attachtype_opt,
+ &ett_vsncp_ipv4address_opt,
+ &ett_vsncp_addressalloc_opt,
+ &ett_vsncp_apn_ambr_opt,
+ &ett_vsncp_ipv6_hsgw_lla_iid_opt,
+ };
+
+ proto_vsncp = proto_register_protocol("Vendor Specific Control Protocol", "VSNCP", "vsncp");
+ vsncp_handle = register_dissector("vsncp", dissect_vsncp, proto_vsncp);
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_vsncp, hf, array_length(hf));
+
+ vsncp_option_table = register_dissector_table("vsncp.option", "PPP VSNCP Options", proto_vsncp, FT_UINT8, BASE_DEC);
+
+ /* Register VSNCP options as their own protocols so we can get the name of the option */
+ proto_vsncp_option_pdnid = proto_register_protocol_in_name_only("PDN Identifier", "PDN Identifier", "vsncp.opt.pdnid", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_apname = proto_register_protocol_in_name_only("Access Point Name", "Access Point Name", "vsncp.opt.apname", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_pdntype = proto_register_protocol_in_name_only("PDN Type", "PDN Type", "vsncp.opt.pdntype", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_pdnaddress = proto_register_protocol_in_name_only("PDN Address", "PDN Address", "vsncp.opt.pdnaddress", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_pco = proto_register_protocol_in_name_only("Protocol Configuration Options", "Protocol Configuration Options", "vsncp.opt.pco", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_errorcode = proto_register_protocol_in_name_only("Error Code", "Error Code", "vsncp.opt.errorcode", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_attachtype = proto_register_protocol_in_name_only("Attach Type", "Attach Type", "vsncp.opt.attachtype", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_ipv4address = proto_register_protocol_in_name_only("IPv4 Default Router Address", "IPv4 Default Router Address", "vsncp.opt.ipv4address", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_addressalloc = proto_register_protocol_in_name_only("Address Allocation Cause", "Address Allocation Cause", "vsncp.opt.addressalloc", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_apn_ambr = proto_register_protocol_in_name_only("APN Aggregate Maximum Bit Rate(APN-AMBR)", "APN Aggregate Maximum Bit Rate(APN-AMBR)", "vsncp.opt.apn_ambr", proto_vsncp, FT_BYTES);
+ proto_vsncp_option_ipv6_hsgw_lla_iid = proto_register_protocol_in_name_only("IPv6 HSGW Link Local Address IID", "IPv6 HSGW Link Local Address IID", "vsncp.opt.ipv6_hsgw_lla_iid", proto_vsncp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_vsncp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_VSNCP, vsncp_handle);
+
+ dissector_add_uint("vsncp.option", CI_PDN_IDENTIFIER, create_dissector_handle( dissect_vsncp_pdnid_opt, proto_vsncp_option_pdnid ));
+ dissector_add_uint("vsncp.option", CI_ACCESS_POINT_NM, create_dissector_handle( dissect_vsncp_apname_opt, proto_vsncp_option_apname ));
+ dissector_add_uint("vsncp.option", CI_PDN_TYPE, create_dissector_handle( dissect_vsncp_pdntype_opt, proto_vsncp_option_pdntype ));
+ dissector_add_uint("vsncp.option", CI_PDN_ADDRESS, create_dissector_handle( dissect_vsncp_pdnaddress_opt, proto_vsncp_option_pdnaddress ));
+ dissector_add_uint("vsncp.option", CI_PROTOCOL_CONFIG, create_dissector_handle( dissect_vsncp_pco_opt, proto_vsncp_option_pco ));
+ dissector_add_uint("vsncp.option", CI_ERROR_CODE, create_dissector_handle( dissect_vsncp_errorcode_opt, proto_vsncp_option_errorcode ));
+ dissector_add_uint("vsncp.option", CI_ATTACH_TYPE, create_dissector_handle( dissect_vsncp_attachtype_opt, proto_vsncp_option_attachtype ));
+ dissector_add_uint("vsncp.option", CI_IPv4DEFAULT_ROUTER, create_dissector_handle( dissect_vsncp_ipv4address_opt, proto_vsncp_option_ipv4address ));
+ dissector_add_uint("vsncp.option", CI_ADDRESS_ALLOC, create_dissector_handle( dissect_vsncp_addressalloc_opt, proto_vsncp_option_addressalloc ));
+ dissector_add_uint("vsncp.option", CI_APN_AMBR, create_dissector_handle( dissect_vsncp_apn_ambr_opt, proto_vsncp_option_apn_ambr ));
+ dissector_add_uint("vsncp.option", CI_IPv6_HSGW_LLA_IID, create_dissector_handle( dissect_vsncp_ipv6_hsgw_lla_iid_opt, proto_vsncp_option_ipv6_hsgw_lla_iid ));
+}
+
+void
+proto_register_vsnp(void)
+{
+ static gint *ett[] = {
+ &ett_vsnp
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_vsnp_3gpp_pdnid,
+ { "PDN ID", "vsnp.3gpp.pdnid", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }}
+ };
+
+ proto_vsnp = proto_register_protocol("Vendor Specific Network Protocol",
+ "PPP VSNP", "vsnp");
+ vsnp_handle = register_dissector("vsnp", dissect_vsnp, proto_vsnp);
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_vsnp, hf, array_length(hf));
+}
+
+void
+proto_reg_handoff_vsnp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_VSNP, vsnp_handle);
+}
+
+void
+proto_register_ipcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ipcp_opt_type,
+ { "Type", "ipcp.opt.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_length,
+ { "Length", "ipcp.opt.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_src_address,
+ { "Source IP Address", "ipcp.opt.src_address", FT_IPv4, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_dst_address,
+ { "Destination IP Address", "ipcp.opt.dst_address", FT_IPv4,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_compress_proto,
+ { "IP Compression Protocol", "ipcp.opt.compress_proto", FT_UINT16,
+ BASE_HEX, VALS(ipcp_compress_proto_vals), 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_max_cid,
+ { "Max CID", "ipcp.opt.max_cid", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Maximum value of a context identifier", HFILL }},
+ { &hf_ipcp_opt_mrru,
+ { "MRRU", "ipcp.opt.mrru", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Maximum Reconstructed Reception Unit", HFILL }},
+ { &hf_ipcp_opt_max_slot_id,
+ { "Max Slot ID", "ipcp.opt.max_slot_id", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_comp_slot_id,
+ { "Comp Slot ID", "ipcp.opt.comp_slot_id", FT_BOOLEAN, 8,
+ TFS(&tfs_comp_slot_id), 0x01, NULL, HFILL }},
+ { &hf_ipcp_opt_tcp_space,
+ { "TCP Space", "ipcp.opt.tcp_space", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_non_tcp_space,
+ { "Non TCP Space", "ipcp.opt.non_tcp_space", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_f_max_period,
+ { "F Max Period", "ipcp.opt.f_max_period", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Maximum interval between full headers", HFILL }},
+ { &hf_ipcp_opt_f_max_time,
+ { "F Max Time", "ipcp.opt.f_max_time", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "Maximum time interval between full headers", HFILL }},
+ { &hf_ipcp_opt_max_header,
+ { "Max Header", "ipcp.opt.max_header", FT_UINT16, BASE_DEC, NULL,
+ 0x0,
+ "The largest header size in octets that may be compressed",
+ HFILL }},
+ { &hf_ipcp_data,
+ { "Data", "ipcp.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_ip_address,
+ { "IP Address", "ipcp.opt.ip_address", FT_IPv4, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_mobilenodehomeaddr,
+ { "Mobile Node's Home Address", "ipcp.opt.mobilenodehomeaddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_pri_dns_address,
+ { "Primary DNS Address", "ipcp.opt.pri_dns_address",
+ FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_pri_nbns_address,
+ { "Primary NBNS Address", "ipcp.opt.pri_nbns_address",
+ FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_sec_dns_address,
+ { "Secondary DNS Address", "ipcp.opt.sec_dns_address",
+ FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_sec_nbns_address,
+ { "Secondary NBNS Address", "ipcp.opt.sec_nbns_address",
+ FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_rohc_type,
+ { "Type", "ipcp.opt.rohc.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_rohc_length,
+ { "Length", "ipcp.opt.rohc.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_rohc_profile,
+ { "Profile", "ipcp.opt.rohc.profile", FT_UINT16, BASE_HEX,
+ VALS(ipcp_rohc_profile_vals), 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_iphc_type,
+ { "Type", "ipcp.opt.iphc.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_iphc_length,
+ { "Length", "ipcp.opt.iphc.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ipcp_opt_iphc_param,
+ { "Parameter", "ipcp.opt.iphc.param", FT_UINT8, BASE_DEC,
+ VALS(ipcp_iphc_parameter_vals), 0x0, NULL, HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ipcp,
+ &ett_ipcp_options,
+ &ett_ipcp_ipaddrs_opt,
+ &ett_ipcp_compress_opt,
+ &ett_ipcp_ipaddr_opt,
+ &ett_ipcp_mobileipv4_opt,
+ &ett_ipcp_pridns_opt,
+ &ett_ipcp_secdns_opt,
+ &ett_ipcp_prinbns_opt,
+ &ett_ipcp_secnbns_opt,
+ &ett_ipcp_iphc_rtp_compress_opt,
+ &ett_ipcp_iphc_enhanced_rtp_compress_opt,
+ &ett_ipcp_iphc_neghdrcomp_opt,
+ &ett_ipcp_rohc_profiles_opt
+ };
+
+ proto_ipcp = proto_register_protocol("PPP IP Control Protocol", "PPP IPCP", "ipcp");
+ ipcp_handle = register_dissector("ipcp", dissect_ipcp, proto_ipcp);
+ proto_register_field_array(proto_ipcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ipcp_option_table = register_dissector_table("ipcp.option", "PPP IPCP Options", proto_ipcp, FT_UINT8, BASE_DEC);
+ ipcp_rohc_suboption_table = register_dissector_table("ipcp.rohc.option", "PPP IPCP ROHC Options", proto_ipcp, FT_UINT8, BASE_DEC);
+ ipcp_iphc_suboption_table = register_dissector_table("ipcp.iphc.option", "PPP IPCP IPHC Options", proto_ipcp, FT_UINT8, BASE_DEC);
+
+ /* Register IPCP options as their own protocols so we can get the name of the option */
+ proto_ipcp_option_addrs = proto_register_protocol_in_name_only("IP Addresses (deprecated)", "IP Addresses (deprecated)", "ipcp.opt.addrs", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_compress = proto_register_protocol_in_name_only("IP Compression Protocol", "IP Compression Protocol", "ipcp.opt.compress", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_addr = proto_register_protocol_in_name_only("IP Address", "IP Address", "ipcp.opt.addr", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_mobileipv4 = proto_register_protocol_in_name_only("Mobile Node's Home IP Address", "Mobile Node's Home IP Address", "ipcp.opt.mobileipv4", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_pri_dns = proto_register_protocol_in_name_only("Primary DNS Server IP Address", "Primary DNS Server IP Address", "ipcp.opt.pri_dns", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_pri_nbns = proto_register_protocol_in_name_only("Primary NBNS Server IP Address", "Primary NBNS Server IP Address", "ipcp.opt.pri_nbns", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_sec_dns = proto_register_protocol_in_name_only("Secondary DNS Server IP Address", "Secondary DNS Server IP Address", "ipcp.opt.sec_dns", proto_ipcp, FT_BYTES);
+ proto_ipcp_option_sec_nbns = proto_register_protocol_in_name_only("Secondary NBNS Server IP Address", "Secondary NBNS Server IP Address", "ipcp.opt.sec_nbns", proto_ipcp, FT_BYTES);
+
+ proto_ipcp_rohc_option_profiles = proto_register_protocol_in_name_only("Profiles (RFC3241)", "Profiles (RFC3241)", "ipcp.opt.rohc.profile_bytes", proto_ipcp, FT_BYTES);
+
+ proto_ipcp_iphc_option_rtp_compress = proto_register_protocol_in_name_only("RTP compression (RFC2508)", "RTP compression (RFC2508)", "ipcp.opt.iphc.rtp_compress", proto_ipcp, FT_BYTES);
+ proto_ipcp_iphc_option_enhanced_rtp_compress = proto_register_protocol_in_name_only("Enhanced RTP compression (RFC3545)", "Enhanced RTP compression (RFC3545)", "ipcp.opt.iphc.enhanced_rtp_compress", proto_ipcp, FT_BYTES);
+ proto_ipcp_iphc_option_neghdrcomp = proto_register_protocol_in_name_only("Negotiating header compression (RFC3545)", "Negotiating header compression (RFC3545)", "ipcp.opt.iphc.neghdrcomp", proto_ipcp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_ipcp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_IPCP, ipcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_IPCP, ipcp_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add_uint("sm_pco.protocol", PPP_IPCP, ipcp_handle);
+
+ dissector_add_uint("ipcp.option", CI_ADDRS, create_dissector_handle( dissect_ipcp_addrs_opt, proto_ipcp_option_addrs ));
+ dissector_add_uint("ipcp.option", CI_COMPRESS_PROTO, create_dissector_handle( dissect_ipcp_compress_opt, proto_ipcp_option_compress ));
+ dissector_add_uint("ipcp.option", CI_ADDR, create_dissector_handle( dissect_ipcp_addr_opt, proto_ipcp_option_addr ));
+ dissector_add_uint("ipcp.option", CI_MOBILE_IPv4, create_dissector_handle( dissect_ipcp_mobileipv4_opt, proto_ipcp_option_mobileipv4 ));
+ dissector_add_uint("ipcp.option", CI_PRI_DNS, create_dissector_handle( dissect_ipcp_pri_dns_opt, proto_ipcp_option_pri_dns ));
+ dissector_add_uint("ipcp.option", CI_PRI_NBNS, create_dissector_handle( dissect_ipcp_pri_nbns_opt, proto_ipcp_option_pri_nbns ));
+ dissector_add_uint("ipcp.option", CI_SEC_DNS, create_dissector_handle( dissect_ipcp_sec_dns_opt, proto_ipcp_option_sec_dns ));
+ dissector_add_uint("ipcp.option", CI_SEC_NBNS, create_dissector_handle( dissect_ipcp_sec_nbns_opt, proto_ipcp_option_sec_nbns ));
+
+ dissector_add_uint("ipcp.rohc.option", IPCP_ROHC_PROFILES, create_dissector_handle( dissect_ipcp_rohc_profiles_opt, proto_ipcp_rohc_option_profiles ));
+
+ dissector_add_uint("ipcp.iphc.option", IPCP_IPHC_CRTP, create_dissector_handle( dissect_ipcp_iphc_rtp_compress, proto_ipcp_iphc_option_rtp_compress ));
+ dissector_add_uint("ipcp.iphc.option", IPCP_IPHC_ECRTP, create_dissector_handle( dissect_ipcp_iphc_enhanced_rtp_compress, proto_ipcp_iphc_option_enhanced_rtp_compress ));
+ dissector_add_uint("ipcp.iphc.option", IPCP_IPHC_NEGHC, create_dissector_handle( dissect_ipcp_iphc_neghdrcomp_opt, proto_ipcp_iphc_option_neghdrcomp ));
+}
+
+void
+proto_register_bcp_bpdu(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bcp_bpdu_flags,
+ { "Flags", "bcp_bpdu.flags", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_bcp_bpdu_fcs_present,
+ { "LAN FCS present", "bcp_bpdu.flags.fcs_present", FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), BCP_FCS_PRESENT, NULL, HFILL }},
+ { &hf_bcp_bpdu_zeropad,
+ { "802.3 pad zero-filled", "bcp_bpdu.flags.zeropad", FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), BCP_ZEROPAD, NULL, HFILL }},
+ { &hf_bcp_bpdu_bcontrol,
+ { "Bridge control", "bcp_bpdu.flags.bcontrol", FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), BCP_IS_BCONTROL, NULL, HFILL }},
+ { &hf_bcp_bpdu_pads,
+ { "Pads", "bcp_bpdu.pads", FT_UINT8, BASE_DEC,
+ NULL, BCP_PADS_MASK, NULL, HFILL }},
+ { &hf_bcp_bpdu_mac_type,
+ { "MAC Type", "bcp_bpdu.mac_type", FT_UINT8, BASE_DEC,
+ VALS(bcp_bpdu_mac_type_vals), 0x0, NULL, HFILL }},
+ { &hf_bcp_bpdu_pad,
+ { "Pad", "bcp_bpdu.pad", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_bcp_bpdu,
+ &ett_bcp_bpdu_flags,
+ };
+
+ proto_bcp_bpdu = proto_register_protocol("PPP Bridging Control Protocol Bridged PDU",
+ "PPP BCP BPDU", "bcp_bpdu");
+ bcp_bpdu_handle = register_dissector("bcp_bpdu", dissect_bcp_bpdu, proto_bcp_bpdu);
+ proto_register_field_array(proto_bcp_bpdu, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_bcp_bpdu(void)
+{
+ eth_withfcs_handle = find_dissector_add_dependency("eth_withfcs", proto_bcp_bpdu);
+ eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_bcp_bpdu);
+
+ dissector_add_uint("ppp.protocol", PPP_BCP_BPDU, bcp_bpdu_handle);
+}
+
+void
+proto_register_bcp_ncp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bcp_ncp_opt_type,
+ { "Type", "bcp_ncp.lcp.opt.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL } },
+ { &hf_bcp_ncp_opt_length,
+ { "Length", "bcp_ncp.lcp.opt.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL } },
+ { &hf_bcp_ncp_lan_seg_no,
+ { "LAN Segment Number", "bcp_ncp.lcp.lan_seg_no", FT_UINT16, BASE_DEC,
+ NULL, 0xfff0, NULL, HFILL } },
+ { &hf_bcp_ncp_bridge_no,
+ { "Bridge Number", "bcp_ncp.lcp.bridge_no", FT_UINT16, BASE_DEC,
+ NULL, 0x000f, NULL, HFILL } },
+ { &hf_bcp_ncp_tinygram_comp,
+ { "Tinygram-Compression", "bcp_ncp.lcp.tinygram_comp", FT_BOOLEAN, 8,
+ TFS(&tfs_enabled_disabled), 0x0, NULL, HFILL } },
+ { &hf_bcp_ncp_mac,
+ { "MAC Address", "bcp_ncp.lcp.mac_addres", FT_ETHER, BASE_NONE,
+ NULL, 0x0, NULL, HFILL } },
+ { &hf_bcp_ncp_mac_l,
+ { "L bit", "bcp_ncp.lcp.mac_l", FT_UINT48, BASE_HEX,
+ NULL, G_GUINT64_CONSTANT(0x0200000000), NULL, HFILL } },
+ { &hf_bcp_ncp_mac_m,
+ { "M bit", "bcp_ncp.lcp.mac_addre", FT_UINT48, BASE_HEX,
+ NULL, G_GUINT64_CONSTANT(0x0100000000), NULL, HFILL } },
+ { &hf_bcp_ncp_stp_prot,
+ { "Protocol", "bcp_ncp.lcp.stp_protocol", FT_UINT8, BASE_DEC,
+ VALS(bcp_ncp_stp_prot_vals), 0x0, NULL, HFILL } },
+ { &hf_bcp_ncp_ieee_802_tagged_frame,
+ { "IEEE-802-Tagged-Frame", "bcp_ncp.ieee_802_tagged_frame", FT_BOOLEAN, 8,
+ TFS(&tfs_enabled_disabled), 0x0, NULL, HFILL } },
+
+ };
+
+ static gint *ett[] = {
+ &ett_bcp_ncp,
+ &ett_bcp_ncp_options,
+ &ett_bcp_ncp_ieee_802_tagged_frame_opt,
+ &ett_bcp_ncp_management_inline_opt,
+ &ett_bcp_ncp_bcp_ind_opt,
+ &ett_bcp_ncp_bridge_id_opt,
+ &ett_bcp_ncp_line_id_opt,
+ &ett_bcp_ncp_mac_sup_opt,
+ &ett_bcp_ncp_tinygram_comp_opt,
+ &ett_bcp_ncp_lan_id_opt,
+ &ett_bcp_ncp_mac_addr_opt,
+ &ett_bcp_ncp_stp_opt
+ };
+
+ proto_bcp_ncp = proto_register_protocol("PPP Bridging Control Protocol Network Control Protocol", "PPP BCP NCP", "bcp_ncp");
+ bcp_ncp_handle = register_dissector("bcp_ncp", dissect_bcp_ncp, proto_bcp_ncp);
+ proto_register_field_array(proto_bcp_ncp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ bcp_ncp_option_table = register_dissector_table("bcp_ncp.option", "PPP BCP NCP Options", proto_bcp_ncp, FT_UINT8, BASE_DEC);
+
+ /* Register BCP NCP options as their own protocols so we can get the name of the option */
+ proto_bcp_ncp_option_bridge_id = proto_register_protocol_in_name_only("Bridge-Identification", "Bridge-Identification", "bcp_ncp.opt.bridge_id", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_line_id = proto_register_protocol_in_name_only("Line-Identification", "Line-Identification", "bcp_ncp.opt.line_id", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_mac_sup = proto_register_protocol_in_name_only("MAC-Support", "MAC-Support", "bcp_ncp.opt.mac_sup", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_tinygram_comp = proto_register_protocol_in_name_only("Tinygram-Compression", "Tinygram-Compression", "bcp_ncp.opt.tinygram_comp", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_lan_id = proto_register_protocol_in_name_only("LAN-Identification (obsoleted)", "LAN-Identification (obsoleted)", "bcp_ncp.opt.lan_id", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_mac_addr = proto_register_protocol_in_name_only("MAC-Address", "MAC-Address", "bcp_ncp.opt.mac_addr", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_stp = proto_register_protocol_in_name_only("Spanning-Tree-Protocol (old formatted)", "Spanning-Tree-Protocol (old formatted)", "bcp_ncp.opt.stp", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_ieee_802_tagged_frame = proto_register_protocol_in_name_only("IEEE 802 Tagged Frame", "IEEE 802 Tagged Frame", "bcp_ncp.opt.ieee_802_tagged_frame", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_management_inline = proto_register_protocol_in_name_only("Management Inline", "Management Inline", "bcp_ncp.opt.management_inline", proto_bcp_ncp, FT_BYTES);
+ proto_bcp_ncp_option_bcp_ind = proto_register_protocol_in_name_only("Bridge Control Packet Indicator", "Bridge Control Packet Indicator", "bcp_ncp.opt.bcp_ind", proto_bcp_ncp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_bcp_ncp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_BCP_NCP, bcp_ncp_handle);
+
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_BRIDGE_ID, create_dissector_handle( dissect_bcp_ncp_bridge_id, proto_bcp_ncp_option_bridge_id ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_LINE_ID, create_dissector_handle( dissect_bcp_ncp_line_id, proto_bcp_ncp_option_line_id ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_MAC_SUPPORT, create_dissector_handle( dissect_bcp_ncp_mac_sup, proto_bcp_ncp_option_mac_sup ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_TINYGRAM_COMP, create_dissector_handle( dissect_bcp_ncp_tinygram_comp, proto_bcp_ncp_option_tinygram_comp ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_LAN_ID, create_dissector_handle( dissect_bcp_ncp_lan_id, proto_bcp_ncp_option_lan_id ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_MAC_ADDRESS, create_dissector_handle( dissect_bcp_ncp_mac_addr, proto_bcp_ncp_option_mac_addr ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_STP, create_dissector_handle( dissect_bcp_ncp_stp, proto_bcp_ncp_option_stp ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_IEEE_802_TAGGED_FRAME, create_dissector_handle( dissect_bcp_ncp_ieee_802_tagged_frame, proto_bcp_ncp_option_ieee_802_tagged_frame ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_MANAGEMENT_INLINE, create_dissector_handle( dissect_bcp_ncp_management_inline, proto_bcp_ncp_option_management_inline ));
+ dissector_add_uint("bcp_ncp.option", CI_BCPNCP_BCP_IND, create_dissector_handle( dissect_bcp_ncp_bcp_ncp_bcp_ind, proto_bcp_ncp_option_bcp_ind ));
+}
+
+void
+proto_register_osinlcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_osinlcp_opt_type,
+ { "Type", "osinlcp.opt.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL } },
+ { &hf_osinlcp_opt_length,
+ { "Length", "osinlcp.opt.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL } },
+ { &hf_osinlcp_opt_alignment,
+ { "Alignment", "osinlcp.opt.alignment", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL } }
+ };
+
+ static gint *ett[] = {
+ &ett_osinlcp,
+ &ett_osinlcp_options,
+ &ett_osinlcp_align_npdu_opt
+ };
+
+ proto_osinlcp = proto_register_protocol("PPP OSI Network Layer Control Protocol", "PPP OSINLCP", "osinlcp");
+ osinlcp_handle = register_dissector("osinlcp", dissect_osinlcp, proto_osinlcp);
+ proto_register_field_array(proto_osinlcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ osinlcp_option_table = register_dissector_table("osinlcp.option", "PPP OSINLCP Options", proto_osinlcp, FT_UINT8, BASE_DEC);
+
+ /* Register OSINLCP options as their own protocols so we can get the name of the option */
+ proto_osinlcp_option_align_npdu = proto_register_protocol_in_name_only("Align-NPDU", "Align-NPDU", "osinlcp.opt.def_pid", proto_osinlcp, FT_BYTES);
+}
+
+
+void
+proto_reg_handoff_osinlcp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_OSINLCP, osinlcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_OSINLCP, osinlcp_handle);
+
+ dissector_add_uint("osinlcp.option", CI_OSINLCP_ALIGN_NPDU, create_dissector_handle( dissect_osinlcp_align_npdu_opt, proto_osinlcp_option_align_npdu ));
+}
+
+void
+proto_register_ccp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ccp_opt_type,
+ { "Type", "ccp.opt.type", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_length,
+ { "Length", "ccp.opt.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_oui,
+ { "OUI", "ccp.opt.oui", FT_UINT24, BASE_OUI,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_subtype,
+ { "Subtype", "ccp.opt.subtype", FT_UINT8, BASE_DEC_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_history_count,
+ { "History Count", "ccp.opt.history_count", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "The maximum number of compression histories",
+ HFILL }},
+ { &hf_ccp_opt_cm,
+ { "Check Mode Field", "ccp.opt.cm", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_cm_reserved,
+ { "Reserved", "ccp.opt.cm.reserved", FT_UINT8, BASE_DEC,
+ NULL, 0xF8, NULL, HFILL }},
+ { &hf_ccp_opt_cm_check_mode,
+ { "Check Mode", "ccp.opt.cm.check_mode", FT_UINT8, BASE_DEC,
+ VALS(stac_checkmode_vals), 0x07, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits,
+ { "Supported Bits", "ccp.opt.supported_bits", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits_h,
+ { "H", "ccp.opt.supported_bits.h", FT_BOOLEAN, 32,
+ TFS(&ccp_mppe_h_tfs), MPPE_SUPPORTED_BITS_H, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits_m,
+ { "M", "ccp.opt.supported_bits.m", FT_BOOLEAN, 32,
+ TFS(&ccp_mppe_m_tfs), MPPE_SUPPORTED_BITS_M, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits_s,
+ { "S", "ccp.opt.supported_bits.s", FT_BOOLEAN, 32,
+ TFS(&ccp_mppe_s_tfs), MPPE_SUPPORTED_BITS_S, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits_l,
+ { "L", "ccp.opt.supported_bits.l", FT_BOOLEAN, 32,
+ TFS(&ccp_mppe_l_tfs), MPPE_SUPPORTED_BITS_L, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits_d,
+ { "D", "ccp.opt.supported_bits.d", FT_BOOLEAN, 32,
+ TFS(&ccp_mppe_d_tfs), MPPE_SUPPORTED_BITS_D, NULL, HFILL }},
+ { &hf_ccp_opt_supported_bits_c,
+ { "C", "ccp.opt.supported_bits.c", FT_BOOLEAN, 32,
+ TFS(&ccp_mppe_c_tfs), MPPC_SUPPORTED_BITS_C, NULL, HFILL }},
+ { &hf_ccp_opt_history,
+ { "History", "ccp.opt.history", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Maximum size of the compression history in powers of 2",
+ HFILL }},
+ { &hf_ccp_opt_version,
+ { "Version", "ccp.opt.version", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_vd,
+ { "Vers/Dict", "ccp.opt.vd", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_vd_vers,
+ { "Vers", "ccp.opt.vd.vers", FT_UINT8, BASE_DEC,
+ NULL, 0xE0, NULL, HFILL }},
+ { &hf_ccp_opt_vd_dict,
+ { "Dict", "ccp.opt.vd.dict", FT_UINT8, BASE_DEC, NULL,
+ 0x1F, "The size in bits of the largest code used", HFILL }},
+ { &hf_ccp_opt_check_mode,
+ { "Check Mode", "ccp.opt.check_mode", FT_UINT8, BASE_DEC,
+ VALS(lzsdcp_checkmode_vals), 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_process_mode,
+ { "Process Mode", "ccp.opt.process_mode", FT_UINT8, BASE_DEC,
+ VALS(lzsdcp_processmode_vals), 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_fe,
+ { "Features", "ccp.opt.fe", FT_UINT8, BASE_DEC,
+ NULL, 0xC0, NULL, HFILL }},
+ { &hf_ccp_opt_p,
+ { "Packet by Packet flag", "ccp.opt.p", FT_BOOLEAN, 8,
+ TFS(&tfs_enabled_disabled), 0x20, NULL, HFILL }},
+ { &hf_ccp_opt_History,
+ { "History", "ccp.opt.History", FT_UINT8, BASE_DEC,
+ NULL, 0x1F, NULL, HFILL }},
+ { &hf_ccp_opt_contexts,
+ { "# Contexts", "ccp.opt.contexts", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_mode,
+ { "Mode", "ccp.opt.mode", FT_UINT8, BASE_DEC,
+ VALS(dce_mode_vals), 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_window,
+ { "Window", "ccp.opt.window", FT_UINT8, BASE_DEC,
+ NULL, 0xF0, NULL, HFILL }},
+ { &hf_ccp_opt_method,
+ { "Method", "ccp.opt.method", FT_UINT8, BASE_DEC,
+ VALS(deflate_method_vals), 0x0F, NULL, HFILL }},
+ { &hf_ccp_opt_mbz,
+ { "MBZ", "ccp.opt.mbz", FT_UINT8, BASE_DEC,
+ NULL, 0xFC, NULL, HFILL }},
+ { &hf_ccp_opt_chk,
+ { "Chk", "ccp.opt.chk", FT_UINT8, BASE_DEC,
+ VALS(deflate_chk_vals), 0x03, NULL, HFILL }},
+ { &hf_ccp_opt_mode_dictcount,
+ { "Mode/Dictionary Count", "ccp.opt.mode_dictcount", FT_UINT16,
+ BASE_DEC | BASE_RANGE_STRING, RVALS(v44lzjh_mode_dict_rvals),
+ 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_dict_size,
+ { "Dictionary Size", "ccp.opt.dict_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_history_length,
+ { "History Length", "ccp.opt.history_length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_ccp_opt_data,
+ { "Data", "ccp.opt.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ccp,
+ &ett_ccp_options,
+ &ett_ccp_oui_opt,
+ &ett_ccp_predict1_opt,
+ &ett_ccp_predict2_opt,
+ &ett_ccp_puddle_opt,
+ &ett_ccp_hpppc_opt,
+ &ett_ccp_stac_opt,
+ &ett_ccp_stac_opt_check_mode,
+ &ett_ccp_mppe_opt,
+ &ett_ccp_mppe_opt_supp_bits,
+ &ett_ccp_gfza_opt,
+ &ett_ccp_v42bis_opt,
+ &ett_ccp_bsdcomp_opt,
+ &ett_ccp_lzsdcp_opt,
+ &ett_ccp_mvrca_opt,
+ &ett_ccp_dce_opt,
+ &ett_ccp_deflate_opt,
+ &ett_ccp_v44lzjh_opt
+ };
+
+ proto_ccp = proto_register_protocol("PPP Compression Control Protocol", "PPP CCP", "ccp");
+ ccp_handle = register_dissector("ccp", dissect_ccp, proto_ccp);
+ proto_register_field_array(proto_ccp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ccp_option_table = register_dissector_table("ccp.option", "PPP CCP Options", proto_ccp, FT_UINT8, BASE_DEC);
+
+ /* Register CCP options as their own protocols so we can get the name of the option */
+ proto_ccp_option_oui = proto_register_protocol_in_name_only("OUI", "OUI", "ccp.opt_oui", proto_ccp, FT_BYTES);
+ proto_ccp_option_predict1 = proto_register_protocol_in_name_only("Predictor type 1", "Predictor type 1", "ccp.opt.predict1", proto_ccp, FT_BYTES);
+ proto_ccp_option_predict2 = proto_register_protocol_in_name_only("Predictor type 2", "Predictor type 2", "ccp.opt.predict2", proto_ccp, FT_BYTES);
+ proto_ccp_option_puddle = proto_register_protocol_in_name_only("Puddle Jumper", "Puddle Jumper", "ccp.opt.puddle", proto_ccp, FT_BYTES);
+ proto_ccp_option_hpppc = proto_register_protocol_in_name_only("Hewlett-Packard PPC", "Hewlett-Packard PPC", "ccp.opt.hpppc", proto_ccp, FT_BYTES);
+ proto_ccp_option_stac = proto_register_protocol_in_name_only("Stac Electronics LZS", "Stac Electronics LZS", "ccp.opt.stac", proto_ccp, FT_BYTES);
+ proto_ccp_option_stac_ascend = proto_register_protocol_in_name_only("Stac Electronics LZS (Ascend Proprietary version)", "Stac Electronics LZS (Ascend Proprietary version)", "ccp.opt.stac_ascend", proto_ccp, FT_BYTES);
+ proto_ccp_option_mppe = proto_register_protocol_in_name_only("Microsoft PPE/PPC", "Microsoft PPE/PPC", "ccp.opt.mppe", proto_ccp, FT_BYTES);
+ proto_ccp_option_gfza = proto_register_protocol_in_name_only("Gandalf FZA", "Gandalf FZA", "ccp.opt.gfza", proto_ccp, FT_BYTES);
+ proto_ccp_option_v42bis = proto_register_protocol_in_name_only("V.42bis compression", "V.42bis compression", "ccp.opt.v42bis", proto_ccp, FT_BYTES);
+ proto_ccp_option_bsdcomp = proto_register_protocol_in_name_only("BSD LZW Compress", "BSD LZW Compress", "ccp.opt.bsdcomp", proto_ccp, FT_BYTES);
+ proto_ccp_option_lzsdcp = proto_register_protocol_in_name_only("LZS-DCP", "LZS-DCP", "ccp.opt.lzsdcp", proto_ccp, FT_BYTES);
+ proto_ccp_option_mvrca = proto_register_protocol_in_name_only("MVRCA (Magnalink)", "MVRCA (Magnalink)", "ccp.opt.mvrca", proto_ccp, FT_BYTES);
+ proto_ccp_option_dce = proto_register_protocol_in_name_only("PPP for Data Compression in Data Circuit-Terminating Equipment (DCE)", "PPP for Data Compression in Data Circuit-Terminating Equipment (DCE)", "ccp.opt.dce", proto_ccp, FT_BYTES);
+ proto_ccp_option_deflate = proto_register_protocol_in_name_only("Deflate", "Deflate", "ccp.opt.deflate", proto_ccp, FT_BYTES);
+ proto_ccp_option_v44lzjh = proto_register_protocol_in_name_only("V.44/LZJH compression", "V.44/LZJH compression", "ccp.opt.v44lzjh", proto_ccp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_ccp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_CCP, ccp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_CCP, ccp_handle);
+
+ dissector_add_uint("ccp.option", CI_CCP_OUI, create_dissector_handle( dissect_ccp_oui_opt, proto_ccp_option_oui ));
+ dissector_add_uint("ccp.option", CI_CCP_PREDICT1, create_dissector_handle( dissect_ccp_predict1_opt, proto_ccp_option_predict1 ));
+ dissector_add_uint("ccp.option", CI_CCP_PREDICT2, create_dissector_handle( dissect_ccp_predict2_opt, proto_ccp_option_predict2 ));
+ dissector_add_uint("ccp.option", CI_CCP_PUDDLE, create_dissector_handle( dissect_ccp_puddle_opt, proto_ccp_option_puddle ));
+ dissector_add_uint("ccp.option", CI_CCP_HPPPC, create_dissector_handle( dissect_ccp_hpppc_opt, proto_ccp_option_hpppc ));
+ dissector_add_uint("ccp.option", CI_CCP_STAC, create_dissector_handle( dissect_ccp_stac_opt, proto_ccp_option_stac ));
+ dissector_add_uint("ccp.option", CI_CCP_MPPE, create_dissector_handle( dissect_ccp_mppe_opt, proto_ccp_option_mppe ));
+ dissector_add_uint("ccp.option", CI_CCP_GFZA, create_dissector_handle( dissect_ccp_gfza_opt, proto_ccp_option_gfza ));
+ dissector_add_uint("ccp.option", CI_CCP_V42BIS, create_dissector_handle( dissect_ccp_v42bis_opt, proto_ccp_option_v42bis ));
+ dissector_add_uint("ccp.option", CI_CCP_BSDLZW, create_dissector_handle( dissect_ccp_bsdcomp_opt, proto_ccp_option_bsdcomp ));
+ dissector_add_uint("ccp.option", CI_CCP_LZSDCP, create_dissector_handle( dissect_ccp_lzsdcp_opt, proto_ccp_option_lzsdcp ));
+ dissector_add_uint("ccp.option", CI_CCP_MVRCA, create_dissector_handle( dissect_ccp_mvrca_opt, proto_ccp_option_mvrca ));
+ dissector_add_uint("ccp.option", CI_CCP_DCE, create_dissector_handle( dissect_ccp_dce_opt, proto_ccp_option_dce ));
+ dissector_add_uint("ccp.option", CI_CCP_DEFLATE, create_dissector_handle( dissect_ccp_deflate_opt, proto_ccp_option_deflate ));
+ dissector_add_uint("ccp.option", CI_CCP_V44LZJH, create_dissector_handle( dissect_ccp_v44lzjh_opt, proto_ccp_option_v44lzjh ));
+}
+
+void
+proto_register_cbcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cbcp_opt_type, { "Type", "cbcp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_cbcp_opt_length, { "Length", "cbcp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_cbcp_callback_delay, { "Callback delay", "cbcp.callback_delay", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_cbcp_address_type, { "Address Type", "cbcp.address_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_cbcp_address, { "Address", "cbcp.address", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_cbcp_no_callback, { "No callback", "cbcp.no_callback", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_cbcp,
+ &ett_cbcp_options,
+ &ett_cbcp_callback_opt,
+ &ett_cbcp_callback_opt_addr,
+ &ett_cbcp_no_callback,
+ &ett_cbcp_callback_user,
+ &ett_cbcp_callback_admin,
+ &ett_cbcp_callback_list,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_cbcp_address, { "cbcp.address.malformed", PI_MALFORMED, PI_ERROR, "Address runs past end of option", EXPFILL }},
+ };
+
+ expert_module_t* expert_cbcp;
+
+ proto_cbcp = proto_register_protocol("PPP Callback Control Protocol", "PPP CBCP", "cbcp");
+ cbcp_handle = register_dissector("cbcp", dissect_cbcp, proto_cbcp);
+ proto_register_field_array(proto_cbcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_cbcp = expert_register_protocol(proto_cbcp);
+ expert_register_field_array(expert_cbcp, ei, array_length(ei));
+
+ cbcp_option_table = register_dissector_table("cbcp.option", "PPP CBCP Options", proto_cbcp, FT_UINT8, BASE_DEC);
+
+ /* Register CBCP options as their own protocols so we can get the name of the option */
+ proto_cbcp_option_no_callback = proto_register_protocol_in_name_only("No callback", "No callback", "cbcp.opt.no_callback", proto_cbcp, FT_BYTES);
+ proto_cbcp_option_callback_user = proto_register_protocol_in_name_only("Callback to a user-specified number", "Callback to a user-specified number", "cbcp.opt.callback_user", proto_cbcp, FT_BYTES);
+ proto_cbcp_option_callback_admin = proto_register_protocol_in_name_only("Callback to a pre-specified or admin-specified number", "Callback to a pre-specified or admin-specified number", "cbcp.opt.callback_admin", proto_cbcp, FT_BYTES);
+ proto_cbcp_option_callback_list = proto_register_protocol_in_name_only("Callback to any of a list of numbers", "Callback to any of a list of numbers", "cbcp.opt.callback_list", proto_cbcp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_cbcp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_CBCP, cbcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_CBCP, cbcp_handle);
+
+ dissector_add_uint("cbcp.option", CI_CBCP_NO_CALLBACK, create_dissector_handle( dissect_cbcp_no_callback_opt, proto_cbcp_option_no_callback ));
+ dissector_add_uint("cbcp.option", CI_CBCP_CB_USER, create_dissector_handle( dissect_cbcp_callback_user_opt, proto_cbcp_option_callback_user ));
+ dissector_add_uint("cbcp.option", CI_CBCP_CB_PRE, create_dissector_handle( dissect_cbcp_callback_admin_opt, proto_cbcp_option_callback_admin ));
+ dissector_add_uint("cbcp.option", CI_CBCP_CB_ANY, create_dissector_handle( dissect_cbcp_callback_list_opt, proto_cbcp_option_callback_list ));
+}
+
+void
+proto_register_bacp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bacp_opt_type, { "Type", "bacp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_bacp_opt_length, { "Length", "bacp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_bacp_magic_number, { "Magic number", "bacp.magic_number", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_bacp_link_speed, { "Link Speed", "bacp.link_speed", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_kbps, 0x0, NULL, HFILL }},
+ { &hf_bacp_link_type, { "Link Type", "bacp.link_type", FT_UINT8, BASE_DEC, VALS(bap_link_type_vals), 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_bacp,
+ &ett_bacp_options,
+ &ett_bacp_favored_peer_opt
+ };
+
+ proto_bacp = proto_register_protocol("PPP Bandwidth Allocation Control Protocol", "PPP BACP", "bacp");
+ bacp_handle = register_dissector("bacp", dissect_bacp, proto_bacp);
+ proto_register_field_array(proto_bacp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ bacp_option_table = register_dissector_table("bacp.option", "PPP BACP Options", proto_bacp, FT_UINT8, BASE_DEC);
+
+ /* Register BACP options as their own protocols so we can get the name of the option */
+ proto_bacp_option_favored_peer = proto_register_protocol_in_name_only("Favored-Peer", "Favored-Peer", "bacp.opt.favored_peer", proto_bacp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_bacp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_BACP, bacp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_BACP, bacp_handle);
+
+ dissector_add_uint("bacp.option", CI_BACP_FAVORED_PEER, create_dissector_handle( dissect_bacp_favored_peer_opt, proto_bacp_option_favored_peer ));
+}
+
+void
+proto_register_bap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bap_opt_type, { "Type", "bap.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_opt_length, { "Length", "bap.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_bap_sub_option_type, { "Sub-Option Type", "bap.sub_option_type", FT_UINT8, BASE_DEC, VALS(bap_phone_delta_subopt_vals), 0x0, NULL, HFILL }},
+ { &hf_bap_sub_option_length, { "Sub-Option Length", "bap.sub_option_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_unique_digit, { "Unique Digit", "bap.unique_digit", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_subscriber_number, { "Subscriber Number", "bap.subscriber_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_phone_number_sub_address, { "Phone Number Sub Address", "bap.phone_number_sub_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_unknown_option_data, { "Unknown", "bap.unknown_option_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_reason, { "Reason", "bap.reason", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_link_discriminator, { "Link Discriminator", "bap.link_discriminator", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_call_status, { "Status", "bap.call_status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &q931_cause_code_vals_ext, 0x0, NULL, HFILL }},
+ { &hf_bap_call_action, { "Action", "bap.call_action", FT_UINT8, BASE_HEX, VALS(bap_call_status_opt_action_vals), 0x0, NULL, HFILL }},
+ { &hf_bap_type, { "Type", "bap.type", FT_UINT8, BASE_HEX, VALS(bap_vals), 0x0, NULL, HFILL }},
+ { &hf_bap_identifier, { "Identifier", "bap.identifier", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_length, { "Length", "bap.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_bap_response_code, { "Response Code", "bap.response_code", FT_UINT8, BASE_HEX, VALS(bap_resp_code_vals), 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_bap,
+ &ett_bap_options,
+ &ett_bap_link_type_opt,
+ &ett_bap_phone_delta_opt,
+ &ett_bap_phone_delta_subopt,
+ &ett_bap_call_status_opt,
+ &ett_bap_no_phone_opt,
+ &ett_bap_reason_opt,
+ &ett_bap_link_disc_opt,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_bap_sub_option_length, { "bap.sub_option_length.invalid", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
+ };
+
+ expert_module_t* expert_bap;
+
+ proto_bap = proto_register_protocol("PPP Bandwidth Allocation Protocol", "PPP BAP", "bap");
+ bap_handle = register_dissector("bap", dissect_bap, proto_bap);
+ proto_register_field_array(proto_bap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_bap = expert_register_protocol(proto_bap);
+ expert_register_field_array(expert_bap, ei, array_length(ei));
+
+ bap_option_table = register_dissector_table("bap.option", "PPP BAP Options", proto_bap, FT_UINT8, BASE_DEC);
+
+ /* Register BAP options as their own protocols so we can get the name of the option */
+ proto_bap_option_link_type = proto_register_protocol_in_name_only("Link Type", "Link Type", "bap.opt.link_type", proto_bap, FT_BYTES);
+ proto_bap_option_phone_delta = proto_register_protocol_in_name_only("Phone Delta", "Phone Delta", "bap.opt.phone_delta", proto_bap, FT_BYTES);
+ proto_bap_option_no_phone = proto_register_protocol_in_name_only("No Phone Number Needed", "No Phone Number Needed", "bap.opt.no_phone", proto_bap, FT_BYTES);
+ proto_bap_option_reason = proto_register_protocol_in_name_only("Reason", "Reason", "bap.opt.reason", proto_bap, FT_BYTES);
+ proto_bap_option_link_disc = proto_register_protocol_in_name_only("Link Discriminator", "Link Discriminator", "bap.opt.link_disc", proto_bap, FT_BYTES);
+ proto_bap_option_call_status = proto_register_protocol_in_name_only("Call Status", "Call Status", "bap.opt.call_status", proto_bap, FT_BYTES);
+}
+
+void
+proto_reg_handoff_bap(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_BAP, bap_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_BAP, bap_handle);
+
+ dissector_add_uint("bap.option", CI_BAP_LINK_TYPE, create_dissector_handle( dissect_bap_link_type_opt, proto_bap_option_link_type ));
+ dissector_add_uint("bap.option", CI_BAP_PHONE_DELTA, create_dissector_handle( dissect_bap_phone_delta_opt, proto_bap_option_phone_delta ));
+ dissector_add_uint("bap.option", CI_BAP_NO_PHONE_NUM_NEEDED, create_dissector_handle( dissect_bap_no_phone_opt, proto_bap_option_no_phone ));
+ dissector_add_uint("bap.option", CI_BAP_REASON, create_dissector_handle( dissect_bap_reason_opt, proto_bap_option_reason ));
+ dissector_add_uint("bap.option", CI_BAP_LINK_DISC, create_dissector_handle( dissect_bap_link_disc_opt, proto_bap_option_link_disc ));
+ dissector_add_uint("bap.option", CI_BAP_CALL_STATUS, create_dissector_handle( dissect_bap_call_status_opt, proto_bap_option_call_status ));
+}
+
+void
+proto_register_comp_data(void)
+{
+#if 0 /* See dissect_comp_data() */
+ static gint *ett[] = {
+ &ett_comp_data
+ };
+#endif
+
+ proto_comp_data = proto_register_protocol("PPP Compressed Datagram",
+ "PPP Comp", "comp_data");
+ comp_data_handle = register_dissector("ppp_comp", dissect_comp_data,
+ proto_comp_data);
+#if 0
+ proto_register_subtree_array(ett, array_length(ett));
+#endif
+}
+
+void
+proto_reg_handoff_comp_data(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_COMP, comp_data_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_COMP, comp_data_handle);
+}
+
+void
+proto_register_pap(void)
+{
+ static gint *ett[] = {
+ &ett_pap,
+ &ett_pap_data
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_pap_code,
+ { "Code", "pap.code", FT_UINT8, BASE_DEC, VALS(pap_vals), 0x0,
+ "The Code field is one octet and identifies the type of PAP "
+ "packet", HFILL }},
+ { &hf_pap_identifier,
+ { "Identifier", "pap.identifier", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The Identifier field is one octet and aids in matching "
+ "requests and replies.", HFILL }},
+ { &hf_pap_length,
+ { "Length", "pap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The Length field is two octets and indicates the length of "
+ "the PAP packet", HFILL }},
+ { &hf_pap_data,
+ { "Data", "pap.data", FT_NONE, BASE_NONE, NULL, 0x0,
+ "The format of the Data field is determined by the Code field",
+ HFILL }},
+ { &hf_pap_peer_id_length,
+ { "Peer-ID-Length", "pap.peer_id.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The Peer-ID-Length field is one octet and indicates the "
+ "length of the Peer-ID field", HFILL }},
+ { &hf_pap_peer_id,
+ { "Peer-ID", "pap.peer_id", FT_STRING, BASE_NONE, NULL, 0x0,
+ "The Peer-ID field is zero or more octets and indicates the "
+ "name of the peer to be authenticated", HFILL }},
+ { &hf_pap_password_length,
+ { "Password-Length", "pap.password.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The Password-Length field is one octet and indicates the "
+ "length of the Password field", HFILL }},
+ { &hf_pap_password,
+ { "Password", "pap.password", FT_STRING, BASE_NONE, NULL, 0x0,
+ "The Password field is zero or more octets and indicates the "
+ "password to be used for authentication", HFILL }},
+ { &hf_pap_message_length,
+ { "Message-Length", "pap.message.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The Message-Length field is one octet and indicates the "
+ "length of the Message field", HFILL }},
+ { &hf_pap_message,
+ { "Message", "pap.message", FT_STRING, BASE_NONE, NULL, 0x0,
+ "The Message field is zero or more octets, and its contents "
+ "are implementation dependent.", HFILL }},
+ { &hf_pap_stuff,
+ { "stuff", "pap.stuff", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }}
+ };
+
+ proto_pap = proto_register_protocol("PPP Password Authentication Protocol",
+ "PPP PAP", "pap");
+ pap_handle = register_dissector("pap", dissect_pap, proto_pap);
+ proto_register_field_array(proto_pap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pap(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_PAP, pap_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_PAP, pap_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add_uint("sm_pco.protocol", PPP_PAP, pap_handle);
+}
+
+void
+proto_register_chap(void)
+{
+ static gint *ett[] = {
+ &ett_chap,
+ &ett_chap_data
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_chap_code,
+ { "Code", "chap.code", FT_UINT8, BASE_DEC, VALS(chap_vals), 0x0,
+ "CHAP code", HFILL }},
+ { &hf_chap_identifier,
+ { "Identifier", "chap.identifier", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "CHAP identifier", HFILL }},
+ { &hf_chap_length,
+ { "Length", "chap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "CHAP length", HFILL }},
+ { &hf_chap_data,
+ { "Data", "chap.data", FT_NONE, BASE_NONE, NULL, 0x0,
+ "CHAP Data", HFILL }},
+ { &hf_chap_value_size,
+ { "Value Size", "chap.value_size", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "CHAP value size", HFILL }},
+ { &hf_chap_value,
+ { "Value", "chap.value", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "CHAP value data", HFILL }},
+ { &hf_chap_name,
+ { "Name", "chap.name", FT_STRING, BASE_NONE, NULL, 0x0,
+ "CHAP name", HFILL }},
+ { &hf_chap_message,
+ { "Message", "chap.message", FT_STRING, BASE_NONE, NULL, 0x0,
+ "CHAP message", HFILL }},
+ { &hf_chap_stuff,
+ { "Stuff", "chap.stuff", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ };
+
+ proto_chap = proto_register_protocol("PPP Challenge Handshake Authentication Protocol", "PPP CHAP", "chap");
+ chap_handle = register_dissector("chap", dissect_chap,
+ proto_chap);
+ proto_register_field_array(proto_chap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_chap(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_CHAP, chap_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_CHAP, chap_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add_uint("sm_pco.protocol", PPP_CHAP, chap_handle);
+}
+
+void
+proto_register_pppmuxcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pppmux_flags_pid,
+ { "PID", "pppmuxcp.flags.pid", FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x80,
+ NULL, HFILL }},
+ { &hf_pppmux_flags_field_length,
+ { "Length field", "pppmuxcp.flags.field_length", FT_BOOLEAN, 8, TFS(&tfs_pppmux_length_field), 0x40,
+ NULL, HFILL }},
+ { &hf_pppmuxcp_opt_type,
+ { "Type", "pppmuxcp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_pppmuxcp_opt_length,
+ { "Length", "pppmuxcp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_pppmux_flags, { "PFF/LXT", "pppmuxcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_pppmux_sub_frame_length, { "Sub-frame Length", "pppmuxcp.sub_frame_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_pppmux_def_prot_id, { "Default Protocol ID", "pppmuxcp.def_prot_id", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ppp_vals_ext, 0x0, NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_pppmuxcp,
+ &ett_pppmuxcp_options,
+ &ett_pppmuxcp_def_pid_opt
+ };
+
+ proto_pppmuxcp = proto_register_protocol("PPPMux Control Protocol", "PPP PPPMuxCP", "pppmuxcp");
+ muxcp_handle = register_dissector("pppmuxcp", dissect_pppmuxcp, proto_pppmuxcp);
+ proto_register_field_array(proto_pppmuxcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ pppmuxcp_option_table = register_dissector_table("pppmuxcp.option", "PPP PPPMuxCP Options", proto_pppmuxcp, FT_UINT8, BASE_DEC);
+
+ /* Register PPPMuxCP options as their own protocols so we can get the name of the option */
+ proto_pppmuxcp_option_def_pid = proto_register_protocol_in_name_only("Default Protocol ID", "Default Protocol ID", "pppmuxcp.opt.def_pid", proto_pppmuxcp, FT_BYTES);
+}
+
+
+void
+proto_reg_handoff_pppmuxcp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_MUXCP, muxcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_MUXCP, muxcp_handle);
+
+ dissector_add_uint("pppmuxcp.option", CI_DEFAULT_PID, create_dissector_handle( dissect_pppmuxcp_def_pid_opt, proto_pppmuxcp_option_def_pid ));
+}
+
+
+void
+proto_register_pppmux(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pppmux_protocol,
+ { "Protocol", "pppmux.protocol", FT_UINT16,
+ BASE_HEX|BASE_EXT_STRING, &ppp_vals_ext, 0x0,
+ "The protocol of the sub-frame.", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_pppmux,
+ &ett_pppmux_subframe,
+ &ett_pppmux_subframe_hdr,
+ &ett_pppmux_subframe_flags,
+ &ett_pppmux_subframe_info
+ };
+
+ proto_pppmux = proto_register_protocol("PPP Multiplexing", "PPP PPPMux",
+ "pppmux");
+ pppmux_handle = register_dissector("pppmux", dissect_pppmux, proto_pppmux);
+ proto_register_field_array(proto_pppmux, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pppmux(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_MUX, pppmux_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_MUX, pppmux_handle);
+}
+
+void
+proto_register_mplscp(void)
+{
+ static gint *ett[] = {
+ &ett_mplscp,
+ &ett_mplscp_options
+ };
+
+ proto_mplscp = proto_register_protocol("PPP MPLS Control Protocol",
+ "PPP MPLSCP", "mplscp");
+ mplscp_handle = register_dissector("mplscp", dissect_mplscp, proto_mplscp);
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mplscp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_MPLSCP, mplscp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_MPLSCP, mplscp_handle);
+}
+
+void
+proto_register_cdpcp(void)
+{
+ static gint *ett[] = {
+ &ett_cdpcp,
+ &ett_cdpcp_options
+ };
+
+ proto_cdpcp = proto_register_protocol("PPP CDP Control Protocol",
+ "PPP CDPCP", "cdpcp");
+ cdpcp_handle = register_dissector("cdpcp", dissect_cdpcp, proto_cdpcp);
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cdpcp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_CDPCP, cdpcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_CDPCP, cdpcp_handle);
+}
+
+void
+proto_register_ipv6cp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ipv6cp_opt_type, { "Type", "ipv6cp.opt.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_ipv6cp_opt_length, { "Length", "ipv6cp.opt.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ /* Generated from convert_proto_tree_add_text.pl */
+ { &hf_ipv6cp_interface_identifier, { "Interface Identifier", "ipv6cp.interface_identifier", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ipv6cp,
+ &ett_ipv6cp_options,
+ &ett_ipv6cp_if_id_opt,
+ &ett_ipv6cp_compress_opt
+ };
+
+ proto_ipv6cp = proto_register_protocol("PPP IPv6 Control Protocol", "PPP IPV6CP", "ipv6cp");
+ ipv6cp_handle = register_dissector("ipv6cp", dissect_ipv6cp, proto_ipv6cp);
+ proto_register_field_array(proto_ipv6cp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ipv6cp_option_table = register_dissector_table("ipv6cp.option", "PPP IPV6CP Options", proto_ipv6cp, FT_UINT8, BASE_DEC);
+
+ /* Register IPV6CP options as their own protocols so we can get the name of the option */
+ proto_ipv6cp_option_if_id = proto_register_protocol_in_name_only("Interface Identifier", "Interface Identifier", "ipv6cp.opt.interface_identifier", proto_ipv6cp, FT_BYTES);
+ proto_ipv6cp_option_compress = proto_register_protocol_in_name_only("IPv6 compression", "IPv6 compression", "ipv6cp.opt.compress", proto_ipv6cp, FT_BYTES);
+}
+
+void
+proto_reg_handoff_ipv6cp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_IPV6CP, ipv6cp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_IPV6CP, ipv6cp_handle);
+
+ /*
+ * for GSM-A / MobileL3 / GPRS SM / PCO
+ */
+ dissector_add_uint("sm_pco.protocol", PPP_IPV6CP, ipv6cp_handle);
+
+ dissector_add_uint("ipv6cp.option", CI_IPV6CP_IF_ID, create_dissector_handle( dissect_ipv6cp_if_id_opt, proto_ipv6cp_option_if_id ));
+ dissector_add_uint("ipv6cp.option", CI_COMPRESS_PROTO, create_dissector_handle( dissect_ipcp_compress_opt, proto_ipv6cp_option_compress ));
+}
+
+void
+proto_register_iphc_crtp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_iphc_crtp_cid16,
+ { "Context Id", "crtp.cid", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The context identifier of the compressed packet.", HFILL }},
+ { &hf_iphc_crtp_cid8,
+ { "Context Id", "crtp.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The context identifier of the compressed packet.", HFILL }},
+ { &hf_iphc_crtp_gen,
+ { "Generation", "crtp.gen", FT_UINT8, BASE_DEC, NULL, 0x3f,
+ "The generation of the compressed packet.", HFILL }},
+ { &hf_iphc_crtp_seq,
+ { "Sequence (Data)", "crtp.seq", FT_UINT8, BASE_DEC, NULL, 0x0f,
+ "The sequence of the compressed packet.", HFILL }},
+ { &hf_iphc_crtp_fh_flags,
+ { "Flags", "crtp.fh_flags", FT_UINT8, BASE_HEX, NULL,
+ IPHC_CRTP_FH_FLAG_MASK,
+ "The flags of the full header packet.", HFILL }},
+ { &hf_iphc_crtp_fh_cidlenflag,
+ { "CID Length", "crtp.fh_flags.cidlen", FT_BOOLEAN, 8, TFS(&iphc_crtp_fh_cidlenflag),
+ IPHC_CRTP_FH_CIDLEN_FLAG, "A flag which is not set for 8-bit Context Ids and set for 16-bit Context Ids.", HFILL }},
+ { &hf_iphc_crtp_fh_dataflag,
+ { "Sequence (Data)", "crtp.fh_flags.data", FT_BOOLEAN, 8,
+ TFS(&tfs_present_absent), IPHC_CRTP_FH_DATA_FLAG,
+ "This indicates the presence of a nonzero data field, usually meaning the low nibble is a sequence number.", HFILL }},
+ { &hf_iphc_crtp_cs_flags,
+ { "Flags", "crtp.cs_flags", FT_UINT8, BASE_DEC, VALS(iphc_crtp_cs_flags),
+ 0x0, "The flags of the context state packet.", HFILL }},
+ { &hf_iphc_crtp_cs_cnt,
+ { "Count", "crtp.cnt", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The count of the context state packet.", HFILL }},
+ { &hf_iphc_crtp_cs_invalid,
+ { "Invalid", "crtp.invalid", FT_BOOLEAN, 8, NULL, 0x80,
+ "The invalid bit of the context state packet.", HFILL }},
+ { &hf_iphc_crtp_ip_id,
+ { "IP-ID", "crtp.ip-id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
+ "The IPv4 Identification Field is RANDOM and thus included in a compressed Non TCP packet (RFC 2507 6a, 7.13a). Only IPv4 is supported in this dissector.", HFILL }},
+ { &hf_iphc_crtp_data,
+ { "Data", "crtp.data", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_iphc_crtp,
+ &ett_iphc_crtp_hdr,
+ &ett_iphc_crtp_info,
+ &ett_iphc_crtp_fh_flags
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_iphc_crtp_ip_version, { "crtp.ip_version_unsupported", PI_PROTOCOL, PI_WARN, "IP version is unsupported", EXPFILL }},
+ { &ei_iphc_crtp_next_protocol, { "crtp.next_protocol_unsupported", PI_PROTOCOL, PI_WARN, "Next protocol is unsupported", EXPFILL }},
+ { &ei_iphc_crtp_seq_nonzero, { "crtp.seq_nonzero", PI_PROTOCOL, PI_WARN, "Sequence (Data) field is nonzero despite D bit not set", EXPFILL }}
+ };
+
+ expert_module_t* expert_iphc_crtp;
+
+ proto_iphc_crtp = proto_register_protocol("CRTP", "CRTP", "crtp");
+ fh_handle = register_dissector("crtp", dissect_iphc_crtp_fh, proto_iphc_crtp);
+ /* Created to remove Decode As confusion */
+ proto_iphc_crtp_cudp16 = proto_register_protocol_in_name_only("CRTP (CUDP 16)", "CRTP (CUDP 16)", "crtp_cudp16", proto_iphc_crtp, FT_PROTOCOL);
+ cudp16_handle = register_dissector("crtp_cudp16", dissect_iphc_crtp_cudp16, proto_iphc_crtp_cudp16);
+ proto_iphc_crtp_cudp8 = proto_register_protocol_in_name_only("CRTP (CUDP 8)", "CRTP (CUDP 8)", "crtp_cudp8", proto_iphc_crtp, FT_PROTOCOL);
+ cudp8_handle = register_dissector("crtp_cudp8", dissect_iphc_crtp_cudp8, proto_iphc_crtp_cudp8);
+ proto_iphc_crtp_cs = proto_register_protocol_in_name_only("CRTP (CS)", "CRTP (CS)", "crtp_cs", proto_iphc_crtp, FT_PROTOCOL);
+ cs_handle = register_dissector("crtp_cs", dissect_iphc_crtp_cs, proto_iphc_crtp_cs);
+ proto_iphc_crtp_cntcp = proto_register_protocol_in_name_only("CRTP (CNTCP)", "CRTP (CNTCP)", "crtp_cntcp", proto_iphc_crtp, FT_PROTOCOL);
+ cntcp_handle = register_dissector("crtp_cntcp", dissect_iphc_crtp_cntcp, proto_iphc_crtp_cntcp);
+
+ proto_register_field_array(proto_iphc_crtp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_iphc_crtp = expert_register_protocol(proto_iphc_crtp);
+ expert_register_field_array(expert_iphc_crtp, ei, array_length(ei));
+}
+
+void
+proto_reg_handoff_iphc_crtp(void)
+{
+ dissector_add_uint("ppp.protocol", PPP_RTP_FH, fh_handle);
+ dissector_add_uint("ppp.protocol", PPP_RTP_CUDP16, cudp16_handle);
+ dissector_add_uint("ppp.protocol", PPP_RTP_CUDP8, cudp8_handle);
+ dissector_add_uint("ppp.protocol", PPP_RTP_CS, cs_handle);
+ dissector_add_uint("ppp.protocol", PPP_RTP_CNTCP, cntcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add_uint("ethertype", PPP_RTP_FH, fh_handle);
+ dissector_add_uint("ethertype", PPP_RTP_CUDP16, cudp16_handle);
+ dissector_add_uint("ethertype", PPP_RTP_CUDP8, cudp8_handle);
+ dissector_add_uint("ethertype", PPP_RTP_CS, cs_handle);
+ dissector_add_uint("ethertype", PPP_RTP_CNTCP, cntcp_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */