X-Git-Url: http://git.samba.org/?p=metze%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=epan%2Fdissectors%2Fpacket-bootp.c;h=2bc1f50dba5e2d3a34a6fb3460dfd68409229a89;hp=02c2361585e3be0710db9165576a5a520e409e34;hb=692cef88c7f68af53e9487e3e2264de8d98b230b;hpb=ae59b09443706587aa78eefe6eb2f43da7815902 diff --git a/epan/dissectors/packet-bootp.c b/epan/dissectors/packet-bootp.c index 02c2361585..2bc1f50dba 100644 --- a/epan/dissectors/packet-bootp.c +++ b/epan/dissectors/packet-bootp.c @@ -7,18 +7,16 @@ * Added option field filters * Copyright 2011, Michael Mann * - * Added option 77 : RFC 3004 - The User Class Option for DHCP + * Added option 77 : RFC 3004 - The User Class Option for DHCP * Added option 117 : RFC 2937 - The Name Service Search Option for DHCP * Added option 119 : RFC 3397 - Dynamic Host Configuration Protocol (DHCP) Domain Search Option - * RFC 3396 - Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) + * RFC 3396 - Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) * Improved opt 120 : Add support of RFC 3396 - Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) - * Add support compression according to the encoding in Section 4.1.4 of RFC 1035 - DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION + * Add support compression according to the encoding in Section 4.1.4 of RFC 1035 - DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION * * * Copyright 2012, Jerome LAFORGE * - * $Id$ - * * The information used comes from: * RFC 951: Bootstrap Protocol * RFC 1035: Domain Names - Implementation And Specification @@ -45,6 +43,7 @@ * RFC 3825: Dynamic Host Configuration Protocol Option for Coordinate-based Location Configuration Information * RFC 3925: Vendor-Identifying Vendor Options for Dynamic Host Configuration Protocol version 4 (DHCPv4) * RFC 3942: Reclassifying DHCPv4 Options + * RFC 4174: The IPv4 Dynamic Host Configuration Protocol (DHCP) Option for the Internet Storage Name Service * RFC 4243: Vendor-Specific Information Suboption for the Dynamic Host Configuration Protocol (DHCP) Relay Agent Option * RFC 4361: Node-specific Client Identifiers for Dynamic Host Configuration Protocol Version Four (DHCPv4) * RFC 4388: Dynamic Host Configuration Protocol (DHCP) Leasequery @@ -53,6 +52,14 @@ * RFC 5223: Discovering Location-to-Service Translation (LoST) Servers Using the Dynamic Host Configuration Protocol (DHCP) * RFC 5417: CAPWAP Access Controller DHCP Option * RFC 5969: IPv6 Rapid Deployment on IPv4 Infrastructures (6rd) + * RFC 6225: Dynamic Host Configuration Protocol Options for Coordinate-Based Location Configuration Information + * RFC 6607: Virtual Subnet Selection Options for DHCPv4 and DHCPv6 + * RFC 6704: Forcerenew Nonce Authentication + * RFC 6731: Improved Recursive DNS Server Selection for Multi-Interfaced Nodes + * RFC 6926: DHCPv4 Bulk Leasequery + * RFC 7291: DHCP Options for the Port Control Protocol (PCP) + * RFC 7618: Dynamic Allocation of Shared IPv4 Addresses + * RFC 7710: Captive-Portal Identification Using DHCP or Router Advertisements (RAs) * draft-ietf-dhc-fqdn-option-07.txt * TFTP Server Address Option for DHCPv4 [draft-raj-dhc-tftp-addr-option-06.txt: http://tools.ietf.org/html/draft-raj-dhc-tftp-addr-option-06] * BOOTP and DHCP Parameters @@ -74,24 +81,14 @@ * http://www.cablelabs.com/projects/cablehome/downloads/specs/CH-SP-CH1.1-I11-060407.pdf * Broadband Forum TR-111 * http://www.broadband-forum.org/technical/download/TR-111.pdf + * Boot Server Discovery Protocol (BSDP) + * http://opensource.apple.com/source/bootp/bootp-198.1/Documentation/BSDP.doc * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * SPDX-License-Identifier: GPL-2.0-or-later */ /* @@ -108,10 +105,6 @@ #include "config.h" #include -#include -#include - -#include #include #include @@ -120,12 +113,14 @@ #include #include #include +#include #include -#include +#include #include #include -#include - +#include +#include +#include void proto_register_bootp(void); void proto_reg_handoff_bootp(void); @@ -150,7 +145,9 @@ static int hf_bootp_hw_ether_addr = -1; static int hf_bootp_server = -1; static int hf_bootp_file = -1; static int hf_bootp_cookie = -1; +static int hf_bootp_vendor_specific_options = -1; static int hf_bootp_dhcp = -1; +static int hf_bootp_fqdn_flags = -1; static int hf_bootp_fqdn_s = -1; static int hf_bootp_fqdn_o = -1; static int hf_bootp_fqdn_e = -1; @@ -161,11 +158,21 @@ static int hf_bootp_fqdn_rcode2 = -1; static int hf_bootp_fqdn_name = -1; static int hf_bootp_fqdn_asciiname = -1; static int hf_bootp_pkt_mta_cap_len = -1; +static int hf_bootp_pkt_mta_cap_type = -1; static int hf_bootp_docsis_cm_cap_type = -1; static int hf_bootp_docsis_cm_cap_len = -1; static int hf_bootp_client_identifier_uuid = -1; +static int hf_bootp_client_id_iaid = -1; +static int hf_bootp_client_id_duid_type = -1; +static int hf_bootp_client_hardware_address = -1; static int hf_bootp_client_identifier_duid_llt_hw_type = -1; static int hf_bootp_client_identifier_duid_ll_hw_type = -1; +static int hf_bootp_client_identifier_time = -1; +static int hf_bootp_client_identifier_link_layer_address = -1; +static int hf_bootp_client_identifier_enterprise_num = -1; +static int hf_bootp_client_identifier = -1; +static int hf_bootp_client_identifier_type = -1; +static int hf_bootp_client_identifier_undef = -1; static int hf_bootp_option_type = -1; static int hf_bootp_option_length = -1; static int hf_bootp_option_value = -1; @@ -274,6 +281,28 @@ static int hf_bootp_option43_cl_device_id_ca = -1; /* 43:53 CL */ static int hf_bootp_option43_cl_device_id_x509 = -1; /* 43:54 CL */ static int hf_bootp_option43_cl_end = -1; /* 43:255 CL */ +static int hf_bootp_option43_bsdp_suboption = -1; /* 43 suboption */ +static int hf_bootp_option43_bsdp_message_type = -1; /* 43:1 BSDP */ +static int hf_bootp_option43_bsdp_version = -1; /* 43:2 BSDP */ +static int hf_bootp_option43_bsdp_server_identifier = -1; /* 43:3 BSDP */ +static int hf_bootp_option43_bsdp_server_priority = -1; /* 43:4 BSDP */ +static int hf_bootp_option43_bsdp_reply_port = -1; /* 43:5 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_list_path = -1; /* 43:6 BSDP */ +static int hf_bootp_option43_bsdp_default_boot_image_id = -1; /* 43:7 BSDP */ +static int hf_bootp_option43_bsdp_selected_boot_image_id = -1; /* 43:8 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_list = -1; /* 43:9 BSDP */ +static int hf_bootp_option43_bsdp_netboot_firmware = -1; /* 43:10 BSDP */ +static int hf_bootp_option43_bsdp_attributes_filter_list = -1; /* 43:11 BSDP */ +static int hf_bootp_option43_bsdp_message_size = -1; /* 43:12 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_index = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_attribute = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_attribute_install = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_attribute_kind = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_attribute_reserved = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_image_desc = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_name = -1; /* 43 BSDP */ +static int hf_bootp_option43_bsdp_boot_image_name_len = -1; /* 43 BSDP */ + static int hf_bootp_option43_alcatel_suboption = -1; /* 43 suboption */ static int hf_bootp_option43_alcatel_padding = -1; /* 43:0 Alcatel */ static int hf_bootp_option43_alcatel_vlan_id = -1; /* 43:58 Alcatel */ @@ -283,6 +312,11 @@ static int hf_bootp_option43_alcatel_app_type = -1; /* 43:66 Alcatel */ static int hf_bootp_option43_alcatel_sip_url = -1; /* 43:67 Alcatel */ static int hf_bootp_option43_alcatel_end = -1; /* 43:255 Alcatel */ +static int hf_bootp_option43_arubaap_controllerip = -1; /* 43: ArubaAP*/ +static int hf_bootp_option43_arubaiap = -1; /* 43: ArubaIAP*/ +static int hf_bootp_option43_arubaiap_nameorg = -1; /* 43: ArubaIAP: Name Organisation*/ +static int hf_bootp_option43_arubaiap_ampip = -1; /* 43: ArubaIAP: AMP IP Address*/ +static int hf_bootp_option43_arubaiap_password = -1; /* 43 :ArubaIAP: Password*/ static int hf_bootp_option_netbios_over_tcpip_name_server = -1; /* 44 */ static int hf_bootp_option_netbios_over_tcpip_dd_name_server = -1; /* 45 */ @@ -301,6 +335,7 @@ static int hf_bootp_option_dhcp_max_message_size = -1; /* 57 */ static int hf_bootp_option_renewal_time_value = -1; /* 58 */ static int hf_bootp_option_rebinding_time_value = -1; /* 59 */ static int hf_bootp_option_vendor_class_id = -1; /* 60 */ +static int hf_bootp_option_vendor_class_data = -1; /* 60 */ static int hf_bootp_option_novell_netware_ip_domain = -1; /* 62 */ @@ -365,13 +400,52 @@ static int hf_bootp_option82_vi_cl_docsis_version = -1; /* 82:9 suboptions end */ static int hf_bootp_option82_flags = -1; /* 82:10 */ static int hf_bootp_option82_server_id_override = -1; /* 82:11 */ -static int hf_bootp_option82_link_selection_cisco = -1; /* 82:150 */ -static int hf_bootp_option82_vrf_name_vpn_id = -1; /* 82:151 */ - /* 82:151 suboptions */ +static int hf_bootp_option82_relay_agent_id = -1; /* 82:12 */ +static int hf_bootp_option82_link_selection_cisco = -1; /* 82:150 */ +static int hf_bootp_option82_vrf_name_vpn_id = -1; /* 82:151 */ + /* 82:151 suboptions */ +static int hf_bootp_option82_vrf_name_global = -1; +static int hf_bootp_option82_vrf_name = -1; static int hf_bootp_option82_vrf_name_vpn_id_oui = -1; static int hf_bootp_option82_vrf_name_vpn_id_index = -1; - /* 82:151 suboptions end */ -static int hf_bootp_option82_server_id_override_cisco = -1; /* 82:152 */ + /* 82:151 suboptions end */ +static int hf_bootp_option82_server_id_override_cisco = -1; /* 82:152 */ + +static int hf_bootp_option_isns_functions = -1; +static int hf_bootp_option_isns_functions_enabled = -1; +static int hf_bootp_option_isns_functions_dd_authorization = -1; +static int hf_bootp_option_isns_functions_sec_policy_distibution = -1; +static int hf_bootp_option_isns_functions_reserved = -1; + +static int hf_bootp_option_isns_discovery_domain_access = -1; +static int hf_bootp_option_isns_discovery_domain_access_enabled = -1; +static int hf_bootp_option_isns_discovery_domain_access_control_node = -1; +static int hf_bootp_option_isns_discovery_domain_access_iscsi_target = -1; +static int hf_bootp_option_isns_discovery_domain_access_iscsi_inititator = -1; +static int hf_bootp_option_isns_discovery_domain_access_ifcp_target_port = -1; +static int hf_bootp_option_isns_discovery_domain_access_ifcp_initiator_port = -1; +static int hf_bootp_option_isns_discovery_domain_access_reserved = -1; + +static int hf_bootp_option_isns_administrative_flags = -1; +static int hf_bootp_option_isns_administrative_flags_enabled = -1; +static int hf_bootp_option_isns_administrative_flags_heartbeat = -1; +static int hf_bootp_option_isns_administrative_flags_management_scns = -1; +static int hf_bootp_option_isns_administrative_flags_default_dd = -1; +static int hf_bootp_option_isns_administrative_flags_reserved = -1; + +static int hf_bootp_option_isns_server_security_bitmap = -1; +static int hf_bootp_option_isns_server_security_bitmap_enabled = -1; +static int hf_bootp_option_isns_server_security_bitmap_ike_ipsec_enabled = -1; +static int hf_bootp_option_isns_server_security_bitmap_main_mode = -1; +static int hf_bootp_option_isns_server_security_bitmap_aggressive_mode = -1; +static int hf_bootp_option_isns_server_security_bitmap_pfs = -1; +static int hf_bootp_option_isns_server_security_bitmap_transport_mode = -1; +static int hf_bootp_option_isns_server_security_bitmap_tunnel_mode = -1; +static int hf_bootp_option_isns_server_security_bitmap_reserved = -1; + +static int hf_bootp_option_isns_heartbeat_originator_addr = -1; +static int hf_bootp_option_isns_primary_server_addr = -1; +static int hf_bootp_option_isns_secondary_server_addr_list = -1; static int hf_bootp_option_novell_dss_string = -1; /* 85 */ static int hf_bootp_option_novell_dss_ip = -1; /* 85 */ @@ -396,6 +470,8 @@ static int hf_bootp_option_civic_location_country = -1; /* 99 */ static int hf_bootp_option_civic_location_ca_type = -1; /* 99 */ static int hf_bootp_option_civic_location_ca_length = -1; /* 99 */ static int hf_bootp_option_civic_location_ca_value = -1; /* 99 */ +static int hf_bootp_option_tz_pcode = -1; /* 100 */ +static int hf_bootp_option_tz_tcode = -1; /* 101 */ static int hf_bootp_option_netinfo_parent_server_address = -1; /* 112 */ static int hf_bootp_option_netinfo_parent_server_tag = -1; /* 113 */ static int hf_bootp_option_dhcp_auto_configuration = -1; /* 116 */ @@ -408,7 +484,16 @@ static int hf_bootp_option_sip_server_refer_last_option = -1; /* 120 */ static int hf_bootp_option_sip_server_enc = -1; /* 120 */ static int hf_bootp_option_sip_server_name = -1; /* 120 */ static int hf_bootp_option_sip_server_address = -1; /* 120 */ -static int hf_bootp_option_sip_server_address_stringz = -1; /* 120 */ +static int hf_bootp_option_classless_static_route = -1; /* 120 */ +static int hf_bootp_option_rfc3825_error = -1; /* 123 */ +static int hf_bootp_option_rfc3825_latitude = -1; /* 123 */ +static int hf_bootp_option_rfc3825_longitude = -1; /* 123 */ +static int hf_bootp_option_rfc3825_latitude_res = -1; /* 123 */ +static int hf_bootp_option_rfc3825_longitude_res = -1; /* 123 */ +static int hf_bootp_option_rfc3825_altitude = -1; /* 123 */ +static int hf_bootp_option_rfc3825_altitide_res = -1; /* 123 */ +static int hf_bootp_option_rfc3825_altitude_type = -1; /* 123 */ +static int hf_bootp_option_rfc3825_map_datum = -1; /* 123 */ static int hf_bootp_option_cl_dss_id_option = -1; /* 123 CL */ static int hf_bootp_option_cl_dss_id_len = -1; /* 123 CL */ static int hf_bootp_option_cl_dss_id = -1; /* 123 CL */ @@ -418,6 +503,7 @@ static int hf_bootp_option_vi_class_data_length = -1; /* 124 */ static int hf_bootp_option_vi_class_data = -1; /* 124 */ static int hf_bootp_option125_enterprise = -1; +static int hf_bootp_option125_length = -1; static int hf_bootp_option125_value = -1; /* 125 suboption value */ static int hf_bootp_option125_value_8 = -1; /* 125 suboption value */ static int hf_bootp_option125_value_16 = -1; /* 125 suboption value */ @@ -440,17 +526,68 @@ static int hf_bootp_option125_cl_modem_capabilities = -1; /* 125:CL 5 */ static int hf_bootp_option_subnet_selection_option = -1; /* 118 */ static int hf_bootp_option_lost_server_domain_name = -1; /* 137 */ static int hf_bootp_option_capwap_access_controller = -1; /* 138 */ +static int hf_bootp_option_andsf_server = -1; /* 142 */ +static int hf_bootp_option_forcerenew_nonce_algo = -1; /* 145 */ +static int hf_bootp_option_rdnss_reserved = -1; /* 146 */ +static int hf_bootp_option_rdnss_pref = -1; /* 146 */ +static int hf_bootp_option_rdnss_prim_dns_server = -1; /* 146 */ +static int hf_bootp_option_rdnss_sec_dns_server = -1; /* 146 */ +static int hf_bootp_option_rdnss_domain = -1; /* 146 */ static int hf_bootp_option_tftp_server_address = -1; /* 150 */ +static int hf_bootp_option_bulk_lease_status_code = -1; /* 151 */ +static int hf_bootp_option_bulk_lease_status_message = -1; /* 151 */ +static int hf_bootp_option_bulk_lease_base_time = -1; /* 152 */ +static int hf_bootp_option_bulk_lease_start_time_of_state = -1; /* 153 */ +static int hf_bootp_option_bulk_lease_query_start = -1; /* 154 */ +static int hf_bootp_option_bulk_lease_query_end = -1; /* 155 */ +static int hf_bootp_option_bulk_lease_dhcp_state = -1; /* 156 */ +static int hf_bootp_option_bulk_lease_data_source = -1; /* 157 */ +static int hf_bootp_option_pcp_list_length = -1; /* 158 */ +static int hf_bootp_option_pcp_server = -1; /* 158 */ +static int hf_bootp_option_portparams_offset = -1; /* 159 */ +static int hf_bootp_option_portparams_psid_length = -1; /* 159 */ +static int hf_bootp_option_portparams_psid = -1; /* 159 */ +static int hf_bootp_option_captive_portal = -1; /* 160 */ +static int hf_bootp_option_mudurl = -1; /* 161 */ +static int hf_bootp_option_pxe_config_file = -1; /* 209 */ +static int hf_bootp_option_pxe_path_prefix = -1; /* 210 */ static int hf_bootp_option_6RD_ipv4_mask_len = -1; /* 212 */ static int hf_bootp_option_6RD_prefix_len = -1; /* 212 */ static int hf_bootp_option_6RD_prefix = -1; /* 212 */ static int hf_bootp_option_6RD_border_relay_ip = -1; /* 212 */ +static int hf_bootp_option242_avaya = -1; /* 242 */ +static int hf_bootp_option242_avaya_tlssrvr = -1; /* 242 */ +static int hf_bootp_option242_avaya_httpsrvr = -1; /* 242 */ +static int hf_bootp_option242_avaya_httpdir = -1; /* 242 */ +static int hf_bootp_option242_avaya_static = -1; /* 242 */ +static int hf_bootp_option242_avaya_mcipadd = -1; /* 242 */ +static int hf_bootp_option242_avaya_dot1x = -1; /* 242 */ +static int hf_bootp_option242_avaya_icmpdu = -1; /* 242 */ +static int hf_bootp_option242_avaya_icmpred = -1; /* 242 */ +static int hf_bootp_option242_avaya_l2q = -1; /* 242 */ +static int hf_bootp_option242_avaya_l2qvlan = -1; /* 242 */ +static int hf_bootp_option242_avaya_loglocal = -1; /* 242 */ +static int hf_bootp_option242_avaya_phy1stat = -1; /* 242 */ +static int hf_bootp_option242_avaya_phy2stat = -1; /* 242 */ +static int hf_bootp_option242_avaya_procpswd = -1; /* 242 */ +static int hf_bootp_option242_avaya_procstat = -1; /* 242 */ +static int hf_bootp_option242_avaya_snmpadd = -1; /* 242 */ +static int hf_bootp_option242_avaya_snmpstring = -1; /* 242 */ +static int hf_bootp_option242_avaya_vlantest = -1; /* 242 */ static int hf_bootp_option_private_proxy_autodiscovery = -1; /* 252 */ static int hf_bootp_option_end = -1; /* 255 */ static int hf_bootp_option_end_overload = -1; /* 255 (with overload)*/ - - - +static int hf_bootp_vendor_unknown_suboption = -1; +static int hf_bootp_suboption_data = -1; +static int hf_bootp_pc_ietf_ccc_suboption = -1; +static int hf_bootp_pc_i05_ccc_suboption = -1; + +static int hf_bootp_cl_ietf_ccc_dev_realm_unc_key_nom_timeout = -1; +static int hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_timeout = -1; +static int hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_retries = -1; +static int hf_bootp_cl_ietf_ccc_dev_prov_unc_key_nom_timeout = -1; +static int hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_timeout = -1; +static int hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_retries = -1; static gint ett_bootp = -1; static gint ett_bootp_flags = -1; @@ -461,16 +598,33 @@ static gint ett_bootp_option77_instance = -1; static gint ett_bootp_option82_suboption = -1; static gint ett_bootp_option82_suboption9 = -1; static gint ett_bootp_option125_suboption = -1; +static gint ett_bootp_option125_tr111_suboption = -1; +static gint ett_bootp_option125_cl_suboption = -1; +static gint ett_bootp_option242_suboption = -1; static gint ett_bootp_fqdn = -1; +static gint ett_bootp_fqdn_flags = -1; +static gint ett_bootp_filename_option = -1; +static gint ett_bootp_server_hostname = -1; +static gint ett_bootp_isns_functions = -1; +static gint ett_bootp_isns_discovery_domain_access = -1; +static gint ett_bootp_isns_administrative_flags = -1; +static gint ett_bootp_isns_server_security_bitmap = -1; +static gint ett_bootp_isns_secondary_server_addr = -1; +static gint ett_bootp_o43_bsdp_boot_image = -1; +static gint ett_bootp_o43_bsdp_attributes = -1; +static gint ett_bootp_o43_bsdp_image_desc_list = -1; +static gint ett_bootp_o43_bsdp_image_desc = -1; +static gint ett_bootp_o43_bsdp_attributes_flags = -1; +static gint ett_bootp_option158_pcp_list = -1; static expert_field ei_bootp_bad_length = EI_INIT; +static expert_field ei_bootp_bad_bitfield = EI_INIT; static expert_field ei_bootp_missing_subopt_length = EI_INIT; static expert_field ei_bootp_missing_subopt_value = EI_INIT; static expert_field ei_bootp_mal_duid = EI_INIT; static expert_field hf_bootp_opt_overload_file_end_missing = EI_INIT; static expert_field hf_bootp_opt_overload_sname_end_missing = EI_INIT; static expert_field hf_bootp_subopt_unknown_type = EI_INIT; -static expert_field ei_bootp_option77_user_class_malformed = EI_INIT; static expert_field ei_bootp_option_civic_location_bad_cattype = EI_INIT; static expert_field ei_bootp_option_dhcp_name_service_invalid = EI_INIT; static expert_field ei_bootp_option_sip_server_address_encoding = EI_INIT; @@ -478,18 +632,40 @@ static expert_field ei_bootp_option_classless_static_route = EI_INIT; static expert_field ei_bootp_option125_enterprise_malformed = EI_INIT; static expert_field ei_bootp_option_6RD_malformed = EI_INIT; static expert_field ei_bootp_option82_vi_cl_tag_unknown = EI_INIT; +static expert_field ei_bootp_option_parse_err = EI_INIT; +static expert_field ei_bootp_nonstd_option_data = EI_INIT; static expert_field ei_bootp_suboption_invalid = EI_INIT; static expert_field ei_bootp_secs_le = EI_INIT; static expert_field ei_bootp_end_option_missing = EI_INIT; - +static expert_field ei_bootp_client_address_not_given = EI_INIT; +static expert_field ei_bootp_server_name_overloaded_by_dhcp = EI_INIT; +static expert_field ei_bootp_boot_filename_overloaded_by_dhcp = EI_INIT; +static expert_field ei_bootp_option_isns_ignored_bitfield = EI_INIT; +static expert_field ei_bootp_option242_avaya_l2qvlan_invalid = EI_INIT; +static expert_field ei_bootp_option242_avaya_vlantest_invalid = EI_INIT; + +static dissector_table_t bootp_option_table; +static dissector_table_t bootp_enterprise_table; +static heur_dissector_list_t bootp_vendor_id_subdissector; +static heur_dissector_list_t bootp_vendor_info_subdissector; static dissector_handle_t bootp_handle; +static dissector_handle_t bootpopt_basic_handle; + +typedef struct bootp_option_data +{ + guchar option; + guint8 *overload; + tvbuff_t *orig_tvb; + const char *dhcp_type; + const guint8 *vendor_class_id; +} bootp_option_data_t; /* RFC2937 The Name Service Search Option for DHCP */ -#define RFC2937_LOCAL_NAMING_INFORMATION 0 -#define RFC2937_DOMAIN_NAME_SERVER_OPTION 6 -#define RFC2937_NETWORK_INFORMATION_SERVERS_OPTION 41 -#define RFC2937_NETBIOS_OVER_TCP_IP_NAME_SERVER_OPTION 44 -#define RFC2937_NETWORK_INFORMATION_SERVICE_PLUS_SERVERS_OPTION 65 +#define RFC2937_LOCAL_NAMING_INFORMATION 0 +#define RFC2937_DOMAIN_NAME_SERVER_OPTION 6 +#define RFC2937_NETWORK_INFORMATION_SERVERS_OPTION 41 +#define RFC2937_NETBIOS_OVER_TCP_IP_NAME_SERVER_OPTION 44 +#define RFC2937_NETWORK_INFORMATION_SERVICE_PLUS_SERVERS_OPTION 65 /* RFC3825decoder error codes of the conversion function */ #define RFC3825_NOERROR 0 @@ -583,6 +759,9 @@ enum { RFC_3361_ENC_IPADDR }; +static void dissect_vendor_avaya_param(proto_tree *tree, packet_info *pinfo, proto_item *vti, + tvbuff_t *tvb, int optoff, wmem_strbuf_t *avaya_param_buf); + /* converts fixpoint presentation into decimal presentation also converts values which are out of range to allow decoding of received data */ static int rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct rfc3825_location_decimal_t *decimal); @@ -688,10 +867,51 @@ static const value_string duidtype_vals[] = { 0, NULL } }; +static const value_string forcerenew_nonce_algo_vals[] = { + { 1, "HMAC-MD5" }, + { 0, NULL }, +}; + +static const value_string rdnss_pref_vals[] = { + { 0, "Medium" }, + { 1, "High" }, + { 2, "Reserved" }, + { 3, "Low" }, + { 0, NULL }, +}; + +static const value_string bulk_lease_dhcp_status_code_vals[] = { + { 0, "Success" }, + { 1, "UpsecFail" }, + { 2, "QueryTerminated" }, + { 3, "MalformedQuery" }, + { 4, "NotAllowed" }, + { 0, NULL }, +}; + +static const value_string bulk_lease_dhcp_state_vals[] = { + { 1, "Available" }, + { 2, "Active" }, + { 3, "Expired" }, + { 4, "Released" }, + { 5, "Abandoned" }, + { 6, "Reset" }, + { 7, "Remote" }, + { 8, "Transitioning" }, + { 0, NULL }, +}; + static gboolean novell_string = FALSE; -#define UDP_PORT_BOOTPS 67 -#define UDP_PORT_BOOTPC 68 +static guint bootp_uuid_endian = ENC_LITTLE_ENDIAN; + +static const enum_val_t bootp_uuid_endian_vals[] = { + { "Little Endian", "Little Endian", ENC_LITTLE_ENDIAN}, + { "Big Endian", "Big Endian", ENC_BIG_ENDIAN }, + { NULL, NULL, 0 } +}; + +#define BOOTP_UDP_PORT_RANGE "67-68" #define BOOTP_BC 0x8000 #define BOOTP_MBZ 0x7FFF @@ -703,6 +923,38 @@ static gboolean novell_string = FALSE; #define F_FQDN_N 0x08 #define F_FQDN_MBZ 0xf0 +#define ISNS_BITFIELD_NZ_MUST_BE_IGNORED(mask, ena_flag) \ + ((mask) && !((mask) & (ena_flag))) + +/* iSNS bit fields */ +#define F_ISNS_FUNCTIONS_ENABLED 0x0001 +#define F_ISNS_FUNCTIONS_DD_AUTH 0x0002 +#define F_ISNS_FUNCTIONS_SEC_POLICY 0x0004 +#define F_ISNS_FUNCTIONS_RESERVED 0xFFF8 + +#define F_ISNS_DD_ACCESS_ENABLED 0x0001 +#define F_ISNS_DD_ACCESS_CTRL_NODE 0x0002 +#define F_ISNS_DD_ACCESS_ISCSI_TARGET 0x0004 +#define F_ISNS_DD_ACCESS_ISCSI_INITIATOR 0x0008 +#define F_ISNS_DD_ACCESS_IFCP_TARGET_PORT 0x0010 +#define F_ISNS_DD_ACCESS_IFCP_INITIATOR_PORT 0x0020 +#define F_ISNS_DD_ACCESS_RESERVED 0xFFC0 + +#define F_ISNS_ADMIN_FLAGS_ENABLED 0x0001 +#define F_ISNS_ADMIN_FLAGS_HEARTBEAT 0x0002 +#define F_ISNS_ADMIN_FLAGS_MANAGEMENT_SCNS 0x0004 +#define F_ISNS_ADMIN_FLAGS_DEFAULT_DD 0x0008 +#define F_ISNS_ADMIN_FLAGS_RESERVED 0xFFF0 + +#define F_ISNS_SRV_SEC_BITMAP_ENABLED 0x0001 +#define F_ISNS_SRV_SEC_BITMAP_IKE_IPSEC 0x0002 +#define F_ISNS_SRV_SEC_BITMAP_MAIN_MODE 0x0004 +#define F_ISNS_SRV_SEC_BITMAP_AGGRESSIVE 0x0008 +#define F_ISNS_SRV_SEC_BITMAP_PFS 0x0010 +#define F_ISNS_SRV_SEC_BITMAP_TRASPORT_MODE 0x0020 +#define F_ISNS_SRV_SEC_BITMAP_TUNNEL_MODE 0x0040 +#define F_ISNS_SRV_SEC_BITMAP_RESERVED 0xFF80 + static const true_false_string tfs_fqdn_s = { "Server", "Client" @@ -723,6 +975,21 @@ static const true_false_string tfs_fqdn_n = { "Some server updates" }; +static const true_false_string tfs_isns_function_dd_based_auth = { + "Automatically allowed access", + "Explicitly performed", +}; + +static const true_false_string tfs_isns_functions_sec_distrib = { + "Download from iSNS server", + "By other means", +}; + +static const true_false_string tfs_bulk_lease_data_source = { + "Remote", + "Local" +}; + enum field_type { special, none, @@ -741,7 +1008,8 @@ enum field_type { time_in_s_secs, /* Signed */ time_in_u_secs, /* Unsigned (not micro) */ fqdn, - ipv4_or_fqdn + ipv4_or_fqdn, + oui }; struct opt_info { @@ -776,32 +1044,17 @@ static const enum_val_t pkt_ccc_protocol_versions[] = { { NULL, NULL, 0 } }; +#define PACKETCABLE_BSDP "AAPLBSDPC" +#define PACKETCABLE_BSDPD "AAPLBSDPC/" + static gint pkt_ccc_protocol_version = PACKETCABLE_CCC_RFC_3495; static guint pkt_ccc_option = 122; - -static int dissect_vendor_pxeclient_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static int dissect_vendor_cablelabs_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static int dissect_vendor_alcatel_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static int dissect_netware_ip_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static int dissect_vendor_tr111_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static int bootp_dhcp_decode_agent_info(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static void dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, - int voff, int len); static void dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len, gboolean opt125); -static int dissect_packetcable_i05_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); -static int dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend, int revision); -static int dissect_vendor_cl_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend); + +#define ARUBA_INSTANT_AP "ArubaInstantAP" +#define ARUBA_AP "ArubaAP" #define OPT53_DISCOVER "Discover" /* http://www.iana.org/assignments/bootp-dhcp-parameters */ @@ -819,13 +1072,11 @@ static const value_string opt53_text[] = { { 11, "Lease Unassigned" }, /* RFC4388 */ { 12, "Lease Unknown" }, /* RFC4388 */ { 13, "Lease Active" }, /* RFC4388 */ - /* draft-ietf-dhc-leasequery-09.txt - { 13, "Lease query" }, */ - { 14, "Lease known" }, - { 15, "Lease unknown" }, - { 16, "Lease active" }, - { 17, "Unimplemented" }, - + { 14, "Bulk Lease Query" }, /* RFC6926 */ + { 15, "Lease Query Done" }, /* RFC6926 */ + { 16, "Active LeaseQuery" }, /* RFC7724 */ + { 17, "Lease Query Status" }, /* RFC7724 */ + { 18, "TLS" }, /* RFC7724 */ { 0, NULL } }; @@ -914,9 +1165,99 @@ static const value_string sip_server_enc_vals[] = { {1, "IPv4 Address" }, {0, NULL } }; + +static const value_string o43_bsdp_boot_image_install_vals[] = { + { 0, "non-install" }, + { 1, "install" }, + { 0, NULL } +}; + +static const value_string o43_bsdp_boot_image_kind_vals[] = { + { 0, "Mac OS 9" }, + { 1, "Mac OS X" }, + { 2, "Mac OS X Server" }, + { 3, "Hardware Diagnostics" }, + { 0, NULL } +}; + +static const value_string o43_bsdp_message_type_vals[] = { + { 1, "LIST" }, + { 2, "SELECT" }, + { 3, "FAILED" }, + { 0, NULL } +}; + +static const string_string option242_avaya_phystat_vals[] = { + { "0", "Disabled" }, + { "1", "Auto" }, + { "2", "10Mbps half" }, + { "3", "10Mbps full" }, + { "4", "100Mbps half" }, + { "5", "100Mbps full" }, + { "6", "1000Mbps full" }, + { 0, NULL } +}; + +static const string_string option242_avaya_l2q_vals[] = { + { "0", "Auto" }, + { "1", "Enabled" }, + { "2", "Disabled" }, + { 0, NULL } +}; + +static const string_string option242_avaya_dot1x_vals[] = { + { "0", "With PAE pass-through" }, + { "1", "With PAE pass-through and proxy Logoff" }, + { "2", "Without PAE pass-through or proxy Logoff" }, + { 0, NULL } +}; + +static const string_string option242_avaya_icmpdu_vals[] = { + { "0", "No ICMP Destination Unreachable messages" }, + { "1", "Send limited Port Unreachable messages" }, + { "2", "Send Protocol and Port Unreachable messages" }, + { 0, NULL } +}; + +static const string_string option242_avaya_icmpred_vals[] = { + { "0", "Ignore ICMP Redirect messages" }, + { "1", "Process ICMP Redirect messages" }, + { 0, NULL } +}; + +static const string_string option242_avaya_loglocal_vals[] = { + { "0", "Disabled" }, + { "1", "Emergencie" }, + { "2", "Alerts" }, + { "3", "Critical" }, + { "4", "Errors" }, + { "5", "Warnings" }, + { "6", "Notices" }, + { "7", "Information" }, + { "8", "Debug" }, + { 0, NULL } +}; + +static const string_string option242_avaya_procstat_vals[] = { + { "0", "All administrative options" }, + { "1", "Only view administrative options" }, + { 0, NULL } +}; + +static const string_string option242_avaya_static_vals[] = { + { "0", "Static programming never overrides call server (DHCP) or call server administered data" }, + { "1", "Static programming overrides only file server administered data" }, + { "2", "Static programming overrides only call server administered data" }, + { "3", "Static programming overrides both file server- and call server-administered data" }, + { 0, NULL } +}; + /* bootp options administration */ #define BOOTP_OPT_NUM 256 +/* All of the options that have a "basic" type that can be handled by dissect_bootpopt_basic_type() */ +#define BOOTP_OPTION_BASICTYPE_RANGE "1-20,22-32,34-42,44-51,53-54,56-59,64-76,86-87,91-93,100-101,112-113,116,118,137-138,142,150,153,156-157,161,209-210,252" + /* Re-define structure. Values to be updated by bootp_init_protocol */ static struct opt_info bootp_opt[BOOTP_OPT_NUM]; @@ -1004,7 +1345,7 @@ static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = { /* 80 */ { "Rapid commit", opaque, NULL }, /* 81 */ { "Client Fully Qualified Domain Name", special, NULL}, /* 82 */ { "Agent Information Option", special, NULL}, -/* 83 */ { "iSNS [TODO:RFC4174]", opaque, NULL }, +/* 83 */ { "iSNS", opaque, NULL }, /* 84 */ { "Removed/Unassigned", opaque, NULL }, /* 85 */ { "Novell Directory Services Servers", special, NULL}, /* 86 */ { "Novell Directory Services Tree Name", string, &hf_bootp_option_novell_ds_tree_name }, @@ -1021,8 +1362,8 @@ static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = { /* 97 */ { "UUID/GUID-based Client Identifier", special, NULL}, /* 98 */ { "Open Group's User Authentication [TODO:RFC2485]", opaque, NULL }, /* 99 */ { "Civic Addresses Configuration", special, NULL}, -/* 100 */ { "PCode [TODO:RFC4833]", opaque, NULL }, -/* 101 */ { "TCode [TODO:RFC4833]", opaque, NULL }, +/* 100 */ { "PCode", string, &hf_bootp_option_tz_pcode }, +/* 101 */ { "TCode", string, &hf_bootp_option_tz_tcode }, /* 102 */ { "Removed/unassigned", opaque, NULL }, /* 103 */ { "Removed/unassigned", opaque, NULL }, /* 104 */ { "Removed/unassigned", opaque, NULL }, @@ -1063,26 +1404,26 @@ static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = { /* 139 */ { "IPv4 Address-MoS", opaque, NULL }, /* 140 */ { "IPv4 FQDN-MoS", opaque, NULL }, /* 141 */ { "SIP UA Configuration Domains", opaque, NULL }, -/* 142 */ { "Unassigned", opaque, NULL }, -/* 143 */ { "Unassigned", opaque, NULL }, -/* 144 */ { "Unassigned", opaque, NULL }, -/* 145 */ { "Unassigned", opaque, NULL }, -/* 146 */ { "Unassigned", opaque, NULL }, +/* 142 */ { "IPv4 Address ANDSF", ipv4_list, &hf_bootp_option_andsf_server }, +/* 143 */ { "Zerotouch Redirect [TODO: draft-ietf-netconf-zerotouch]", opaque, NULL }, +/* 144 */ { "Geospatial Location [TODO:RFC6225]", opaque, NULL }, +/* 145 */ { "Forcerenew Nonce Capable", special, NULL }, +/* 146 */ { "RDNSS Selection", special, NULL }, /* 147 */ { "Unassigned", opaque, NULL }, /* 148 */ { "Unassigned", opaque, NULL }, /* 149 */ { "Unassigned", opaque, NULL }, /* 150 */ { "TFTP Server Address", ipv4_list, &hf_bootp_option_tftp_server_address }, -/* 151 */ { "Unassigned", opaque, NULL }, -/* 152 */ { "Unassigned", opaque, NULL }, -/* 153 */ { "Unassigned", opaque, NULL }, -/* 154 */ { "Unassigned", opaque, NULL }, -/* 155 */ { "Unassigned", opaque, NULL }, -/* 156 */ { "Unassigned", opaque, NULL }, -/* 157 */ { "Unassigned", opaque, NULL }, -/* 158 */ { "Unassigned", opaque, NULL }, -/* 159 */ { "Unassigned", opaque, NULL }, -/* 160 */ { "Unassigned", opaque, NULL }, -/* 161 */ { "Unassigned", opaque, NULL }, +/* 151 */ { "Leasequery Status code", special, NULL }, +/* 152 */ { "Leasequery Base Time", special, NULL }, +/* 153 */ { "Leasequery Start Time of State", time_in_u_secs, &hf_bootp_option_bulk_lease_start_time_of_state }, +/* 154 */ { "Leasequery Query Start Time", special, NULL }, +/* 155 */ { "Leasequery Query End Time", special, NULL }, +/* 156 */ { "Leasequery Dhcp State", val_u_byte, &hf_bootp_option_bulk_lease_dhcp_state }, +/* 157 */ { "Leasequery Data Source", val_boolean, &hf_bootp_option_bulk_lease_data_source }, +/* 158 */ { "PCP Server", special, NULL }, +/* 159 */ { "Portparams", special, NULL }, +/* 160 */ { "DHCP Captive-Portal", special, NULL }, +/* 161 */ { "Manufacturer Usage Description", string, &hf_bootp_option_mudurl}, /* 162 */ { "Unassigned", opaque, NULL }, /* 163 */ { "Unassigned", opaque, NULL }, /* 164 */ { "Unassigned", opaque, NULL }, @@ -1130,8 +1471,8 @@ static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = { /* 206 */ { "Unassigned", opaque, NULL }, /* 207 */ { "Unassigned", opaque, NULL }, /* 208 */ { "PXELINUX Magic", opaque, NULL }, -/* 209 */ { "Configuration file", opaque, NULL }, -/* 210 */ { "Authentication", special, NULL}, /* Path Prefix rfc5071 */ +/* 209 */ { "PXE Configuration file", string, &hf_bootp_option_pxe_config_file }, +/* 210 */ { "PXE Path Prefix", string, &hf_bootp_option_pxe_path_prefix }, /* 211 */ { "Reboot Time", opaque, NULL }, /* 212 */ { "6RD", opaque, NULL }, /* 213 */ { "V4 Access Domain", opaque, NULL }, @@ -1163,7 +1504,7 @@ static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = { /* 239 */ { "Private", opaque, NULL }, /* 240 */ { "Private", opaque, NULL }, /* 241 */ { "Private", opaque, NULL }, -/* 242 */ { "Private", opaque, NULL }, +/* 242 */ { "Private/Avaya IP Telephone", special, NULL }, /* 243 */ { "Private", opaque, NULL }, /* 244 */ { "Private", opaque, NULL }, /* 245 */ { "Private", opaque, NULL }, @@ -1194,31 +1535,31 @@ typedef struct { static uat_bootp_record_t *uat_bootp_records = NULL; static uat_t *bootp_uat = NULL; static guint num_bootp_records_uat = 0; +static wmem_list_t *saved_uat_opts = NULL; /* List of previous options from UAT to "free" from dissection */ static void* uat_bootp_record_copy_cb(void* n, const void* o, size_t siz _U_) { uat_bootp_record_t* new_record = (uat_bootp_record_t *)n; const uat_bootp_record_t* old_record = (const uat_bootp_record_t *)o; - if (old_record->text) { - new_record->text = g_strdup(old_record->text); - } else { - new_record->text = NULL; - } + new_record->text = g_strdup(old_record->text); return new_record; } -static void uat_bootp_record_update_cb(void* r, const char** err) { +static gboolean uat_bootp_record_update_cb(void* r, char** err) { uat_bootp_record_t* rec = (uat_bootp_record_t *)r; - if ((rec->opt == 0) || (rec->opt >=BOOTP_OPT_NUM-1)) + if ((rec->opt == 0) || (rec->opt >=BOOTP_OPT_NUM-1)) { *err = g_strdup_printf("Option must be between 1 and %d", BOOTP_OPT_NUM-2); + return FALSE; + } + return TRUE; } static void uat_bootp_record_free_cb(void*r) { uat_bootp_record_t* rec = (uat_bootp_record_t *)r; - if (rec->text) g_free(rec->text); + g_free(rec->text); } UAT_DEC_CB_DEF(uat_bootp_records, opt, uat_bootp_record_t) @@ -1262,10 +1603,10 @@ bootp_handle_basic_types(packet_info *pinfo, proto_tree *tree, proto_item *item, enum field_type ftype, int offset, int total_len, gint *hf, struct basic_types_hfs* hf_default) { - int i, left; - gint32 time_s_secs; + int i, left; + gint32 time_s_secs; guint32 time_u_secs; - int consumed = 0; + int consumed = 0; switch (ftype) { case bytes: @@ -1402,7 +1743,7 @@ bootp_handle_basic_types(packet_info *pinfo, proto_tree *tree, proto_item *item, if (hf != NULL) { time_s_secs = (gint32) tvb_get_ntohl(tvb, offset); proto_tree_add_int_format_value(tree, *hf, - tvb, offset, 4, time_s_secs, "(%ds) %s", time_s_secs, time_secs_to_str(time_s_secs)); + tvb, offset, 4, time_s_secs, "(%ds) %s", time_s_secs, signed_time_secs_to_str(wmem_packet_scope(), time_s_secs)); } else if (hf_default->time_in_s_secs != NULL) proto_tree_add_item(tree, *hf_default->time_in_s_secs, tvb, offset, 4, ENC_BIG_ENDIAN); @@ -1420,7 +1761,7 @@ bootp_handle_basic_types(packet_info *pinfo, proto_tree *tree, proto_item *item, time_u_secs = tvb_get_ntohl(tvb, offset); proto_tree_add_uint_format_value(tree, *hf, tvb, offset, 4, time_u_secs, "(%us) %s", time_u_secs, - ((time_u_secs == 0xffffffff) ? "infinity" : time_secs_to_str_unsigned(time_u_secs))); + ((time_u_secs == 0xffffffff) ? "infinity" : unsigned_time_secs_to_str(wmem_packet_scope(), time_u_secs))); } else if (hf_default->time_in_u_secs != NULL) proto_tree_add_item(tree, *hf_default->time_in_u_secs, tvb, offset, 4, ENC_BIG_ENDIAN); @@ -1429,37 +1770,16 @@ bootp_handle_basic_types(packet_info *pinfo, proto_tree *tree, proto_item *item, default: /* Ignore other field_types */ break; - } + } - return consumed; + return consumed; } -/* Returns the number of bytes consumed by this option. */ static int -bootp_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, int voff, - int eoff, gboolean first_pass, gboolean *at_end, const char **dhcp_type_p, - const guint8 **vendor_class_id_p, guint8 *overload_p) +dissect_bootpopt_basic_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { struct opt_info *opt; - enum field_type ftype; - guchar code = tvb_get_guint8(tvb, voff); - int optlen; - guchar byte; - int i, consumed, basictype_consumed; - int optoff, optleft, optend; - proto_tree *v_tree; - proto_item *vti, *ti; - guint8 protocol; - guint8 algorithm; - guint8 rdm; - guint8 fqdn_flags; - int o52voff, o52eoff; - gboolean o52at_end; - guint8 s_option; - guint8 s_len; - const guchar *dns_name; - gboolean option_handled = TRUE; - + bootp_option_data_t *option_data = (bootp_option_data_t*)data; struct basic_types_hfs default_hfs = { &hf_bootp_option_value, &hf_bootp_option_value_ip_address, @@ -1474,6 +1794,29 @@ bootp_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, int voff, &hf_bootp_option_value_u32 }; + opt = bootp_get_opt(option_data->option); + if (opt == NULL) + return 0; + + return bootp_handle_basic_types(pinfo, tree, tree, tvb, opt->ftype, + 0, tvb_reported_length(tvb), opt->phf, &default_hfs); +} + +/* Returns the number of bytes consumed by this option. */ +static int +bootp_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, int voff, + int eoff, gboolean first_pass, gboolean *at_end, const char **dhcp_type_p, + const guint8 **vendor_class_id_p, guint8 *overload_p) +{ + struct opt_info *opt; + guchar code = tvb_get_guint8(tvb, voff); + int optlen; + int i, consumed; + proto_tree *v_tree; + proto_item *vti, *ti_value; + tvbuff_t *option_tvb; + bootp_option_data_t option_data; + /* Options whose length isn't "optlen + 2". */ switch (code) { @@ -1572,7 +1915,8 @@ bootp_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, int voff, case 60: *vendor_class_id_p = - tvb_get_ptr(tvb, voff+2, consumed-2); + tvb_get_string_enc(wmem_packet_scope(), + tvb, voff+2, consumed-2, ENC_ASCII); break; case 119: rfc3396_dns_domain_search_list.total_number_of_block++; @@ -1597,1049 +1941,1193 @@ bootp_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, int voff, return consumed; } - /* function type may be overridden and that shouldn't be a 'saved' change */ - ftype = opt->ftype; - - optoff = voff+2; - vti = proto_tree_add_uint_format_value(bp_tree, hf_bootp_option_type, tvb, voff, consumed, code, "(%d) %s", code, opt->text); v_tree = proto_item_add_subtree(vti, ett_bootp_option); proto_tree_add_item(v_tree, hf_bootp_option_length, tvb, voff+1, 1, ENC_BIG_ENDIAN); - ti = proto_tree_add_item(v_tree, hf_bootp_option_value, tvb, voff+2, optlen, ENC_NA); - PROTO_ITEM_SET_HIDDEN(ti); + ti_value = proto_tree_add_item(v_tree, hf_bootp_option_value, tvb, voff+2, optlen, ENC_NA); + PROTO_ITEM_SET_HIDDEN(ti_value); - /* Special cases */ - switch (code) { + /* prepate data for dissector table */ + option_tvb = tvb_new_subset_length(tvb, voff+2, optlen); + option_data.option = code; + option_data.overload = overload_p; + option_data.dhcp_type = *dhcp_type_p; + option_data.vendor_class_id = *vendor_class_id_p; + option_data.orig_tvb = tvb; - case 21: /* Policy Filter */ - for (i = optoff, optleft = optlen; - optleft > 0; i += 8, optleft -= 8) { - if (optleft < 8) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Option length isn't a multiple of 8"); - break; - } + if (!dissector_try_uint_new(bootp_option_table, code, option_tvb, pinfo, v_tree, FALSE, &option_data)) { + /* hf_bootp_option_value is already in tree, just make it visible */ + PROTO_ITEM_SET_VISIBLE(ti_value); + } - proto_tree_add_item(v_tree, hf_bootp_option_policy_filter_ip, tvb, i, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_policy_filter_subnet_mask, tvb, i+4, 4, ENC_BIG_ENDIAN); - } - break; + return consumed; +} - case 33: /* Static Route */ - for (i = optoff, optleft = optlen; - optleft > 0; i += 8, optleft -= 8) { - if (optleft < 8) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Option length isn't a multiple of 8"); - break; - } +static int +dissect_bootpopt_policy_filter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; - proto_tree_add_item(v_tree, hf_bootp_option_static_route_ip, tvb, i, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_static_route_router, tvb, i+4, 4, ENC_BIG_ENDIAN); - } - break; + while (tvb_reported_length_remaining(tvb, offset) >= 8) { + proto_tree_add_item(tree, hf_bootp_option_policy_filter_ip, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_bootp_option_policy_filter_subnet_mask, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } - case 43: /* Vendor-Specific Info */ - s_option = tvb_get_guint8(tvb, optoff); + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Option length isn't a multiple of 8"); + } - /* PXE protocol 2.1 as described in the Intel specs */ - if (*vendor_class_id_p != NULL && - strncmp((const gchar*)*vendor_class_id_p, "PXEClient", strlen("PXEClient")) == 0) { - proto_item_append_text(vti, " (PXEClient)"); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); + return tvb_captured_length(tvb); +} - optend = optoff + optlen; - while (optoff < optend) { - optoff = dissect_vendor_pxeclient_suboption(pinfo, vti, v_tree, - tvb, optoff, optend); - } - } else if (*vendor_class_id_p != NULL && - ((strncmp((const gchar*)*vendor_class_id_p, "pktc", strlen("pktc")) == 0) || - (strncmp((const gchar*)*vendor_class_id_p, "docsis", strlen("docsis")) == 0) || - (strncmp((const gchar*)*vendor_class_id_p, "OpenCable2.0", strlen("OpenCable2.0")) == 0) || - (strncmp((const gchar*)*vendor_class_id_p, "CableHome", strlen("CableHome")) == 0))) { - /* CableLabs standard - see www.cablelabs.com/projects */ - proto_item_append_text(vti, " (CableLabs)"); - - optend = optoff + optlen; - while (optoff < optend) { - optoff = dissect_vendor_cablelabs_suboption(pinfo, vti, v_tree, - tvb, optoff, optend); +static int +dissect_bootpopt_static_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + + while (tvb_reported_length_remaining(tvb, offset) >= 8) { + proto_tree_add_item(tree, hf_bootp_option_static_route_ip, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_bootp_option_static_route_router, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Option length isn't a multiple of 8"); + } + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_vendor_specific_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + heur_dtbl_entry_t *hdtbl_entry; + proto_tree *vendor_tree; + + if (!dissector_try_heuristic(bootp_vendor_info_subdissector, tvb, pinfo, tree, &hdtbl_entry, data)) { + /* Default Vendor-Specific Info.. display in bytes */ + vendor_tree = proto_item_add_subtree(tree, ett_bootp_option); + proto_tree_add_item(vendor_tree, hf_bootp_option43_value, tvb, 0, tvb_reported_length(tvb), ENC_NA); + } + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_option_overload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + int offset = 0; + int suboffset, suboffset_end; + gboolean at_end; + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + guint32 byte; + + if (tvb_reported_length(tvb) < 1) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 1"); + return 1; + } + + proto_tree_add_item_ret_uint(tree, hf_bootp_option_option_overload, tvb, offset, 1, ENC_BIG_ENDIAN, &byte); + + /* Just in case we find an option 52 in sname or file */ + if ((*option_data->overload >= 1) && (*option_data->overload <= 3)) { + if (byte & OPT_OVERLOAD_SNAME) { + proto_item *oti; + proto_tree *overload_tree = proto_tree_add_subtree(tree, option_data->orig_tvb, + SERVER_NAME_OFFSET, SERVER_NAME_LEN, ett_bootp_server_hostname, &oti, + "Server host name option overload"); + guint8 ignore_overload = 0; + suboffset = SERVER_NAME_OFFSET; + suboffset_end = SERVER_NAME_OFFSET + SERVER_NAME_LEN; + at_end = FALSE; + rfc3396_dns_domain_search_list.index_current_block = 0; + rfc3396_sip_server.index_current_block = 0; + while (suboffset < suboffset_end && !at_end) { + suboffset += bootp_option(option_data->orig_tvb, pinfo, overload_tree, suboffset, + suboffset_end, FALSE, &at_end, + &option_data->dhcp_type, &option_data->vendor_class_id, + &ignore_overload); } - } else if (s_option==58 || s_option==64 || s_option==65 - || s_option==66 || s_option==67) { - /* Note that this is a rather weak (permissive) heuristic, */ - /* but since it comes last, I guess this is OK. */ - /* Add any stronger (less permissive) heuristics before this! */ - /* Alcatel-Lucent DHCP Extensions */ - proto_item_append_text(vti, " (Alcatel-Lucent)"); - optend = optoff + optlen; - while (optoff < optend) { - optoff = dissect_vendor_alcatel_suboption(pinfo, vti, v_tree, - tvb, optoff, optend); + if (!at_end) + { + expert_add_info(pinfo, oti, &hf_bootp_opt_overload_sname_end_missing); } } - break; - - case 52: /* Option Overload */ - if (optlen < 1) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 1"); - break; - } - - byte = tvb_get_guint8(tvb, optoff); - proto_tree_add_item(v_tree, *opt->phf, tvb, optoff, 1, ENC_BIG_ENDIAN); - - /* Just in case we find an option 52 in sname or file */ - if (voff > VENDOR_INFO_OFFSET && byte >= 1 && byte <= 3) { - if (byte & OPT_OVERLOAD_FILE) { - proto_item *oti; - oti = proto_tree_add_text (bp_tree, tvb, - FILE_NAME_OFFSET, FILE_NAME_LEN, - "Boot file name option overload"); - o52voff = FILE_NAME_OFFSET; - o52eoff = FILE_NAME_OFFSET + FILE_NAME_LEN; - o52at_end = FALSE; - rfc3396_dns_domain_search_list.index_current_block = 0; - rfc3396_sip_server.index_current_block = 0; - while (o52voff < o52eoff && !o52at_end) { - o52voff += bootp_option(tvb, pinfo, bp_tree, o52voff, - o52eoff, FALSE, &o52at_end, - dhcp_type_p, vendor_class_id_p, - overload_p); - } - if (!o52at_end) - { - expert_add_info(pinfo, oti, &hf_bootp_opt_overload_file_end_missing); - } + if (byte & OPT_OVERLOAD_FILE) { + proto_item *oti; + proto_tree *overload_tree = proto_tree_add_subtree(tree, option_data->orig_tvb, + FILE_NAME_OFFSET, FILE_NAME_LEN, ett_bootp_filename_option, &oti, + "Boot file name option overload"); + guint8 ignore_overload = 0; + suboffset = FILE_NAME_OFFSET; + suboffset_end = FILE_NAME_OFFSET + FILE_NAME_LEN; + at_end = FALSE; + rfc3396_dns_domain_search_list.index_current_block = 0; + rfc3396_sip_server.index_current_block = 0; + while (suboffset < suboffset_end && !at_end) { + suboffset += bootp_option(option_data->orig_tvb, pinfo, overload_tree, suboffset, + suboffset_end, FALSE, &at_end, + &option_data->dhcp_type, &option_data->vendor_class_id, + &ignore_overload); } - if (byte & OPT_OVERLOAD_SNAME) { - proto_item *oti; - oti = proto_tree_add_text (bp_tree, tvb, - SERVER_NAME_OFFSET, SERVER_NAME_LEN, - "Server host name option overload"); - o52voff = SERVER_NAME_OFFSET; - o52eoff = SERVER_NAME_OFFSET + SERVER_NAME_LEN; - o52at_end = FALSE; - rfc3396_dns_domain_search_list.index_current_block = 0; - rfc3396_sip_server.index_current_block = 0; - while (o52voff < o52eoff && !o52at_end) { - o52voff += bootp_option(tvb, pinfo, bp_tree, o52voff, - o52eoff, FALSE, &o52at_end, - dhcp_type_p, vendor_class_id_p, - overload_p); - } - if (!o52at_end) - { - expert_add_info(pinfo, oti, &hf_bootp_opt_overload_sname_end_missing); - } + if (!at_end) + { + expert_add_info(pinfo, oti, &hf_bootp_opt_overload_file_end_missing); } - /* The final end option is not in overload */ - *overload_p = 0; } - break; + /* The final end option is not in overload */ + *option_data->overload = 0; + } - case 55: /* Parameter Request List */ - for (i = 0; i < optlen; i++) { - byte = tvb_get_guint8(tvb, optoff+i); - proto_tree_add_uint_format_value(v_tree, hf_bootp_option_parameter_request_list_item, - tvb, optoff+i, 1, byte, "(%d) %s", byte, bootp_get_opt_text(byte)); - } - break; + return tvb_captured_length(tvb); +} - case 60: /* Vendor class identifier */ - /* - * XXX - RFC 2132 says this is a string of octets; - * should we check for non-printables? - */ +static int +dissect_bootpopt_dhcp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint32 type; - proto_tree_add_item(v_tree, hf_bootp_option_vendor_class_id, tvb, optoff, consumed-2, ENC_ASCII|ENC_NA); - if ((tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP10, - (int)strlen(PACKETCABLE_MTA_CAP10)) == 0) - || - (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP15, - (int)strlen(PACKETCABLE_MTA_CAP15)) == 0) - || - (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP20, - (int)strlen(PACKETCABLE_MTA_CAP20)) == 0)) - { - dissect_packetcable_mta_cap(v_tree, tvb, optoff, optlen); - } else - if ((tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP11, - (int)strlen(PACKETCABLE_CM_CAP11)) == 0) - || - (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP20, - (int)strlen(PACKETCABLE_CM_CAP20)) == 0 )) - { - dissect_docsis_cm_cap(v_tree, tvb, optoff, optlen, FALSE); - } else - if (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP30, - (int)strlen(PACKETCABLE_CM_CAP30)) == 0 ) - { - proto_tree_add_text(v_tree, tvb, optoff, optlen, - "vendor-class-data: \"%s\"", tvb_format_stringzpad(tvb, optoff, optlen)); - } - break; + proto_tree_add_item_ret_uint(tree, hf_bootp_option_dhcp, tvb, 0, 1, ENC_NA, &type); + /* Show the message type name on the Message Type option, and in the protocol root */ + proto_item_append_text(tree, " (%s)", val_to_str(type, opt53_text, "Unknown Message Type (0x%02x)")); + proto_item_append_text(proto_item_get_parent(tree), " (%s)", val_to_str(type, opt53_text, "Unknown Message Type (0x%02x)")); + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_param_request_list(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int offset = 0; + guint8 byte; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + byte = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tree, hf_bootp_option_parameter_request_list_item, + tvb, offset, 1, byte, "(%d) %s", byte, bootp_get_opt_text(byte)); + offset++; + } + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_vendor_class_identifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + heur_dtbl_entry_t *hdtbl_entry; + + /* + * XXX - RFC 2132 says this is a string of octets; + * should we check for non-printables? + */ + proto_tree_add_item(tree, hf_bootp_option_vendor_class_id, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA); + dissector_try_heuristic(bootp_vendor_id_subdissector, tvb, pinfo, tree, &hdtbl_entry, data); + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_client_identifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + int length = tvb_reported_length(tvb); + guchar byte; - case 61: /* Client Identifier */ - if (optlen > 0) - byte = tvb_get_guint8(tvb, optoff); + if (length > 0) + byte = tvb_get_guint8(tvb, offset); + else + byte = 0; + + /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll + guess that the first is the hwtype, and the last 6 + are the hw addr */ + /* See http://www.iana.org/assignments/arp-parameters */ + /* RFC2132 9.14 Client-identifier has the following to say: + A hardware type of 0 (zero) should be used when the value + field contains an identifier other than a hardware address + (e.g. a fully qualified domain name). */ + + if (length == 7 && byte > 0 && byte < 48) { + proto_tree_add_item(tree, hf_bootp_hw_type, tvb, offset, 1, ENC_NA); + + if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802) + proto_tree_add_item(tree, hf_bootp_hw_ether_addr, tvb, offset+1, 6, ENC_NA); else - byte = 0; - - /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll - guess that the first is the hwtype, and the last 6 - are the hw addr */ - /* See http://www.iana.org/assignments/arp-parameters */ - /* RFC2132 9.14 Client-identifier has the following to say: - A hardware type of 0 (zero) should be used when the value - field contains an identifier other than a hardware address - (e.g. a fully qualified domain name). */ - - if (optlen == 7 && byte > 0 && byte < 48) { - proto_tree_add_item(v_tree, - hf_bootp_hw_type, tvb, optoff, 1, - ENC_NA); - - if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802) - proto_tree_add_item(v_tree, - hf_bootp_hw_ether_addr, tvb, optoff+1, 6, - ENC_NA); - else - proto_tree_add_text(v_tree, tvb, optoff+1, 6, - "Client hardware address: %s", - tvb_arphrdaddr_to_str(tvb, optoff+1, 6, byte)); - } else if (optlen == 17 && byte == 0) { - /* Identifier is a UUID */ - proto_tree_add_item(v_tree, hf_bootp_client_identifier_uuid, - tvb, optoff + 1, 16, ENC_LITTLE_ENDIAN); - /* From RFC 4631 paragraph 6.1 DHCPv4 Client Behavior: - To send an RFC 3315-style binding identifier in a DHCPv4 'client - identifier' option, the type of the 'client identifier' option is set - to 255. */ - } else if (byte == 255) { - guint16 duidtype; - guint16 hwtype; - guint8 *buf; - int enterprise; - - /* The type field is immediately followed by the IAID, which is - an opaque 32-bit quantity */ - proto_tree_add_text(v_tree, tvb, optoff+1, 4, - "IAID: %s", - tvb_arphrdaddr_to_str(tvb, optoff+1, 4, byte)); - optoff = optoff + 5; - duidtype = tvb_get_ntohs(tvb, optoff); - proto_tree_add_text(v_tree, tvb, optoff, 2, - "DUID type: %s (%u)", - val_to_str_const(duidtype, duidtype_vals, "Unknown"), - duidtype); - switch (duidtype) { - case DUID_LLT: - if (optlen < 8) { - expert_add_info(pinfo, vti, &ei_bootp_mal_duid); - break; - } - hwtype=tvb_get_ntohs(tvb, optoff + 2); - proto_tree_add_item(v_tree, hf_bootp_client_identifier_duid_llt_hw_type, - tvb, optoff + 2, 2, ENC_BIG_ENDIAN); - - /* XXX seconds since Jan 1 2000 */ - proto_tree_add_text(v_tree, tvb, optoff + 4, 4, - "Time: %u", tvb_get_ntohl(tvb, optoff + 4)); - if (optlen > 8) { - proto_tree_add_text(v_tree, tvb, optoff + 8, - optlen - 13, "Link-layer address: %s", - tvb_arphrdaddr_to_str(tvb, optoff+8, optlen-13, hwtype)); - } - break; - case DUID_EN: - if (optlen < 6) { - expert_add_info(pinfo, vti, &ei_bootp_mal_duid); - break; - } - enterprise = tvb_get_ntohl(tvb, optoff+2); - proto_tree_add_text(v_tree, tvb, optoff + 2, 4, - "Enterprise-number: %s (%u)", - val_to_str_ext_const( enterprise, &sminmpec_values_ext, "Unknown"), - enterprise); - if (optlen > 6) { - buf = tvb_bytes_to_str(tvb, optoff + 6, optlen - 11); - proto_tree_add_text(v_tree, tvb, optoff + 6, - optlen - 11, "identifier: %s", buf); - } - break; - case DUID_LL: - if (optlen < 4) { - expert_add_info(pinfo, vti, &ei_bootp_mal_duid); - break; - } - hwtype=tvb_get_ntohs(tvb, optoff + 2); - proto_tree_add_item(v_tree, hf_bootp_client_identifier_duid_ll_hw_type, - tvb, optoff + 2, 2, ENC_BIG_ENDIAN); - - if (optlen > 4) { - proto_tree_add_text(v_tree, tvb, optoff + 4, - optlen - 9, "Link-layer address: %s", - tvb_arphrdaddr_to_str(tvb, optoff+4, optlen-9, hwtype)); - } + proto_tree_add_string(tree, hf_bootp_client_hardware_address, tvb, offset+1, 6, + tvb_arphrdaddr_to_str(tvb, offset+1, 6, byte)); + } else if (length == 17 && byte == 0) { + /* Identifier is a UUID */ + proto_tree_add_item(tree, hf_bootp_client_identifier_uuid, tvb, offset + 1, 16, bootp_uuid_endian); + + /* From RFC 4361 paragraph 6.1 DHCPv4 Client Behavior: + To send an RFC 3315-style binding identifier in a DHCPv4 'client + identifier' option, the type of the 'client identifier' option is set + to 255. */ + } else if (byte == 255) { + guint16 duidtype; + guint16 hwtype; + + /* The type field is immediately followed by the IAID, which is + an opaque 32-bit quantity */ + proto_tree_add_string(tree, hf_bootp_client_id_iaid, tvb, offset+1, 4, + tvb_arphrdaddr_to_str(tvb, offset+1, 4, byte)); + offset += 5; + duidtype = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_bootp_client_id_duid_type, tvb, offset, 2, ENC_BIG_ENDIAN); + switch (duidtype) { + case DUID_LLT: + if (length < 8) { + expert_add_info(pinfo, tree, &ei_bootp_mal_duid); break; } - } else { - /* otherwise, it's opaque data */ - } - break; - case 77: { /* User Class Information RFC 3004 */ - guchar user_class_instance_index; - proto_item *vtix; - proto_tree *o77_v_tree; - if (optlen < 2) { - expert_add_info_format(pinfo, v_tree, &ei_bootp_bad_length, "length isn't >= 2"); + hwtype=tvb_get_ntohs(tvb, offset + 2); + proto_tree_add_item(tree, hf_bootp_client_identifier_duid_llt_hw_type, + tvb, offset + 2, 2, ENC_BIG_ENDIAN); + + /* XXX seconds since Jan 1 2000 */ + proto_tree_add_item(tree, hf_bootp_client_identifier_time, tvb, offset + 4, 4, ENC_BIG_ENDIAN); + if (length > 8) { + proto_tree_add_string(tree, hf_bootp_client_identifier_link_layer_address, tvb, offset + 8, + length - 13, tvb_arphrdaddr_to_str(tvb, offset+8, length-13, hwtype)); + } break; - } - optleft = optlen; - for (user_class_instance_index = 0, i = 0, byte = tvb_get_guint8(tvb, optoff); i < optlen; byte = tvb_get_guint8(tvb, optoff + i), user_class_instance_index++) { - /* Create subtree for instance of User Class. */ - vtix = proto_tree_add_uint_format_value(v_tree, hf_bootp_option77_user_class, - tvb, optoff + i, byte + 1, user_class_instance_index, "[%d]", user_class_instance_index); - o77_v_tree = proto_item_add_subtree(vtix, ett_bootp_option77_instance); - - /* Add length for instance of User Class. */ - proto_tree_add_item(o77_v_tree, hf_bootp_option77_user_class_length, - tvb, optoff + i, 1, ENC_BIG_ENDIAN); - - if (byte == 0) { - expert_add_info_format(pinfo, vtix, &ei_bootp_bad_length, "UC_Len_%u isn't >= 1 (UC_Len_%u = 0)", user_class_instance_index, user_class_instance_index); + case DUID_EN: + if (length < 6) { + expert_add_info(pinfo, tree, &ei_bootp_mal_duid); break; } - optleft -= byte + 1; - if (optleft < 0) { - expert_add_info(pinfo, vtix, &ei_bootp_option77_user_class_malformed); + proto_tree_add_item(tree, hf_bootp_client_identifier_enterprise_num, tvb, offset + 2, 4, ENC_BIG_ENDIAN); + if (length > 6) { + proto_tree_add_item(tree, hf_bootp_client_identifier, tvb, offset + 6, length - 11, ENC_NA); + } + break; + case DUID_LL: + if (length < 4) { + expert_add_info(pinfo, tree, &ei_bootp_mal_duid); break; } + hwtype=tvb_get_ntohs(tvb, offset + 2); + proto_tree_add_item(tree, hf_bootp_client_identifier_duid_ll_hw_type, + tvb, offset + 2, 2, ENC_BIG_ENDIAN); - /* Add data for instance of User Class. */ - proto_tree_add_item(o77_v_tree, hf_bootp_option77_user_class_data, - tvb, optoff + i + 1, byte, ENC_BIG_ENDIAN); - - /* Slide to next instance of User Class if any. */ - i += byte + 1; + if (length > 4) { + proto_tree_add_string(tree, hf_bootp_client_identifier_link_layer_address, tvb, offset + 4, + length - 9, tvb_arphrdaddr_to_str(tvb, offset+4, length-9, hwtype)); + } + break; } - break; + } else if (byte == 0 && length > 1) { + /* identifier other than a hardware address (e.g. a fully qualified domain name) */ + proto_tree_add_item(tree, hf_bootp_client_identifier_type, tvb, offset, 1, ENC_NA); + proto_tree_add_item(tree, hf_bootp_client_identifier_undef, tvb, offset+1, length-1, ENC_ASCII|ENC_NA); + } else { + /* otherwise, it's opaque data */ } - case 97: /* Client Identifier (UUID) */ - if (optlen > 0) - byte = tvb_get_guint8(tvb, optoff); - else - byte = 0; - - /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll - guess that the first is the hwtype, and the last 6 - are the hw addr */ - /* See http://www.iana.org/assignments/arp-parameters */ - /* RFC2132 9.14 Client-identifier has the following to say: - A hardware type of 0 (zero) should be used when the value - field contains an identifier other than a hardware address - (e.g. a fully qualified domain name). */ - - if (optlen == 7 && byte > 0 && byte < 48) { - proto_tree_add_item(v_tree, - hf_bootp_hw_type, tvb, optoff, 1, - ENC_NA); - if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802) - proto_tree_add_item(v_tree, - hf_bootp_hw_ether_addr, tvb, optoff+1, 6, - ENC_NA); - else - proto_tree_add_text(v_tree, tvb, optoff+1, 6, - "Client hardware address: %s", - tvb_arphrdaddr_to_str(tvb, optoff+1, 6, byte)); - } else if (optlen == 17 && byte == 0) { - /* Identifier is a UUID */ - proto_tree_add_item(v_tree, hf_bootp_client_identifier_uuid, - tvb, optoff + 1, 16, ENC_LITTLE_ENDIAN); - } else { - /* otherwise, it's opaque data */ - } - break; - case 63: /* NetWare/IP options (RFC 2242) */ - - optend = optoff + optlen; - while (optoff < optend) - optoff = dissect_netware_ip_suboption(pinfo, vti, v_tree, tvb, optoff, optend); - break; - - case 78: /* SLP Directory Agent Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/ - if (optlen < 1) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 1"); - break; - } - optleft = optlen; - byte = tvb_get_guint8(tvb, optoff); - proto_tree_add_item(v_tree, hf_bootp_option_slp_directory_agent_value, tvb, optoff, 1, ENC_BIG_ENDIAN); + return tvb_captured_length(tvb); +} - optoff++; - optleft--; - if (byte == 0x80) { - if (optleft == 0) - break; - optoff++; - optleft--; - } - for (i = optoff; optleft > 0; i += 4, optleft -= 4) { - if (optleft < 4) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Option length isn't a multiple of 4"); - break; - } +static int +dissect_bootpopt_user_class_information(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guchar user_class_instance_index = 0; + int offset = 0; + guint32 class_length; + proto_item *vtix, *len_item; + proto_tree *o77_v_tree; + if (tvb_reported_length(tvb) < 2) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 2"); + return 1; + } - proto_tree_add_item(v_tree, hf_bootp_option_slp_directory_agent_slpda_address, tvb, i, 4, ENC_BIG_ENDIAN); - } - break; + if (!tvb_strneql(tvb, offset, "iPXE", 4)) { + /* The iPXE is known to violate RFC 3004, http://forum.ipxe.org/showthread.php?tid=7530 */ + proto_item *expert_ti = proto_tree_add_item(tree, hf_bootp_option77_user_class_data, tvb, offset, -1, ENC_NA); + expert_add_info(pinfo, expert_ti, &ei_bootp_nonstd_option_data); + return tvb_captured_length(tvb); + } - case 79: /* SLP Service Scope Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/ - proto_tree_add_item(v_tree, hf_bootp_option_slp_service_scope_value, tvb, optoff, 1, ENC_BIG_ENDIAN); + while (tvb_reported_length_remaining(tvb, offset) > 0) { + /* Create subtree for instance of User Class. */ + vtix = proto_tree_add_uint_format_value(tree, hf_bootp_option77_user_class, + tvb, offset, 1, user_class_instance_index, "[%d]", user_class_instance_index); + o77_v_tree = proto_item_add_subtree(vtix, ett_bootp_option77_instance); - optoff++; - optleft = optlen - 1; - proto_tree_add_item(v_tree, hf_bootp_option_slp_service_scope_string, tvb, optoff, optleft, ENC_ASCII|ENC_NA); - break; + /* Add length for instance of User Class. */ + len_item = proto_tree_add_item_ret_uint(o77_v_tree, hf_bootp_option77_user_class_length, + tvb, offset, 1, ENC_BIG_ENDIAN, &class_length); + proto_item_set_len(vtix, class_length+1); + offset += 1; - case 81: /* Client Fully Qualified Domain Name */ - if (optlen < 3) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 3"); + if (class_length == 0) { + expert_add_info_format(pinfo, len_item, &ei_bootp_bad_length, "UC_Len_%u isn't >= 1 (UC_Len_%u = 0)", user_class_instance_index, user_class_instance_index); break; } - fqdn_flags = tvb_get_guint8(tvb, optoff); - proto_tree_add_text(v_tree, tvb, optoff, 1, "Flags: 0x%02x", fqdn_flags); - proto_tree_add_item(v_tree, hf_bootp_fqdn_mbz, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_fqdn_n, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_fqdn_e, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_fqdn_o, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_fqdn_s, tvb, optoff, 1, ENC_BIG_ENDIAN); - /* XXX: use code from packet-dns for return code decoding */ - proto_tree_add_item(v_tree, hf_bootp_fqdn_rcode1, tvb, optoff+1, 1, ENC_BIG_ENDIAN); - /* XXX: use code from packet-dns for return code decoding */ - proto_tree_add_item(v_tree, hf_bootp_fqdn_rcode2, tvb, optoff+2, 1, ENC_BIG_ENDIAN); - if (optlen > 3) { - if (fqdn_flags & F_FQDN_E) { - get_dns_name(tvb, optoff+3, optlen-3, optoff+3, &dns_name); - proto_tree_add_string(v_tree, hf_bootp_fqdn_name, - tvb, optoff+3, optlen-3, dns_name); - } else { - proto_tree_add_item(v_tree, hf_bootp_fqdn_asciiname, - tvb, optoff+3, optlen-3, ENC_ASCII|ENC_NA); - } - } - break; - case 82: /* Relay Agent Information Option */ - optend = optoff + optlen; - while (optoff < optend) - optoff = bootp_dhcp_decode_agent_info(pinfo, vti, v_tree, tvb, optoff, optend); - break; + /* Add data for instance of User Class. */ + proto_tree_add_item(o77_v_tree, hf_bootp_option77_user_class_data, tvb, offset, class_length, ENC_NA); + offset += class_length; + user_class_instance_index++; + } - case 85: /* Novell Servers (RFC 2241) */ - /* Option 85 can be sent as a string */ - /* Added by Greg Morris (gmorris[AT]novell.com) */ - if (novell_string) { - proto_tree_add_item(v_tree, hf_bootp_option_novell_dss_string, tvb, optoff, optlen, ENC_ASCII|ENC_NA); - } else{ - /* IP addresses */ - for (i = optoff, optleft = optlen; optleft > 0; - i += 4, optleft -= 4) { - if (optleft < 4) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Option length isn't a multiple of 4"); - break; - } + return tvb_captured_length(tvb); +} - proto_tree_add_item(v_tree, hf_bootp_option_novell_dss_ip, tvb, i, 4, ENC_BIG_ENDIAN); - } - } - break; +static int +dissect_bootpopt_slp_directory_agent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + guint32 byte; - case 94: { /* Client network interface identifier */ - guint8 id_type; + if (tvb_reported_length(tvb) < 1) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 1"); + return 1; + } - id_type = tvb_get_guint8(tvb, optoff); + proto_tree_add_item_ret_uint(tree, hf_bootp_option_slp_directory_agent_value, tvb, offset, 1, ENC_BIG_ENDIAN, &byte); + offset++; - if (id_type == 0x01) { - proto_tree_add_item(v_tree, hf_bootp_option_client_network_id_major_ver, - tvb, optoff + 1, 1, ENC_LITTLE_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_client_network_id_minor_ver, - tvb, optoff + 2, 1, ENC_LITTLE_ENDIAN); - } + if (byte == 0x80) { + if (tvb_reported_length_remaining(tvb, offset) == 0) + return offset; - break; + offset++; } - case 90: /* DHCP Authentication */ - case 210: /* Was this used for authentication at one time? */ - if (optlen < 11) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 11"); - break; - } - optleft = optlen; - protocol = tvb_get_guint8(tvb, optoff); + while (tvb_reported_length_remaining(tvb, offset) >= 4) { + proto_tree_add_item(tree, hf_bootp_option_slp_directory_agent_slpda_address, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_protocol, tvb, optoff, 1, ENC_BIG_ENDIAN); - optoff++; - optleft--; + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Option length isn't a multiple of 4"); + } - algorithm = tvb_get_guint8(tvb, optoff); - switch (protocol) { + return tvb_captured_length(tvb); +} - case AUTHEN_PROTO_DELAYED_AUTHEN: - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_alg_delay, tvb, optoff, 1, ENC_BIG_ENDIAN); - break; +static int +dissect_bootpopt_slp_service_scope(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int offset = 0; - default: - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_algorithm, tvb, optoff, 1, ENC_BIG_ENDIAN); - break; + proto_tree_add_item(tree, hf_bootp_option_slp_service_scope_value, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset++; + proto_tree_add_item(tree, hf_bootp_option_slp_service_scope_string, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA); + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_client_full_domain_name(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + static const int * fqdn_hf_flags[] = { + &hf_bootp_fqdn_mbz, + &hf_bootp_fqdn_n, + &hf_bootp_fqdn_e, + &hf_bootp_fqdn_o, + &hf_bootp_fqdn_s, + NULL + }; + guint8 fqdn_flags; + int offset = 0, length = tvb_reported_length(tvb); + const guchar *dns_name; + guint dns_name_len; + + if (length < 3) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 3"); + return 1; + } + + fqdn_flags = tvb_get_guint8(tvb, offset); + proto_tree_add_bitmask(tree, tvb, offset, hf_bootp_fqdn_flags, + ett_bootp_fqdn_flags, fqdn_hf_flags, ENC_BIG_ENDIAN); + + /* XXX: use code from packet-dns for return code decoding */ + proto_tree_add_item(tree, hf_bootp_fqdn_rcode1, tvb, offset+1, 1, ENC_BIG_ENDIAN); + /* XXX: use code from packet-dns for return code decoding */ + proto_tree_add_item(tree, hf_bootp_fqdn_rcode2, tvb, offset+2, 1, ENC_BIG_ENDIAN); + + if (length > 3) { + if (fqdn_flags & F_FQDN_E) { + get_dns_name(tvb, offset+3, length-3, offset+3, &dns_name, &dns_name_len); + proto_tree_add_string(tree, hf_bootp_fqdn_name, + tvb, offset+3, length-3, format_text(wmem_packet_scope(), dns_name, dns_name_len)); + } else { + proto_tree_add_item(tree, hf_bootp_fqdn_asciiname, tvb, offset+3, length-3, ENC_ASCII|ENC_NA); } - optoff++; - optleft--; + } - rdm = tvb_get_guint8(tvb, optoff); - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_rdm, tvb, optoff, 1, ENC_BIG_ENDIAN); - optoff++; - optleft--; + return tvb_captured_length(tvb); +} - switch (rdm) { +static int +dissect_bootpopt_novell_servers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; - case AUTHEN_RDM_MONOTONIC_COUNTER: - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_rdm_replay_detection, tvb, optoff, 8, ENC_BIG_ENDIAN); - break; + /* Option 85 can be sent as a string */ + /* Added by Greg Morris (gmorris[AT]novell.com) */ + if (novell_string) { + proto_tree_add_item(tree, hf_bootp_option_novell_dss_string, tvb, offset, tvb_reported_length(tvb), ENC_ASCII|ENC_NA); + } else { + /* IP addresses */ + while (tvb_reported_length_remaining(tvb, offset) >= 4) { - default: - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_rdm_rdv, tvb, optoff, 8, ENC_ASCII|ENC_NA); - break; + proto_tree_add_item(tree, hf_bootp_option_novell_dss_ip, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; } - optoff += 8; - optleft -= 8; - switch (protocol) { + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Option length isn't a multiple of 4"); + } + } - case AUTHEN_PROTO_DELAYED_AUTHEN: - switch (algorithm) { + return tvb_captured_length(tvb); +} - case AUTHEN_DELAYED_ALGO_HMAC_MD5: - if (*dhcp_type_p && !strcmp(*dhcp_type_p, OPT53_DISCOVER)) { - /* Discover has no Secret ID nor HMAC MD5 Hash */ - break; - } else { - if (optlen < 31) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 31"); - break; - } +static int +dissect_bootpopt_dhcp_authentication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + int offset = 0; + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + guint32 protocol, rdm; + guint8 algorithm; + + if (tvb_reported_length(tvb) < 11) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 11"); + return 1; + } - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_secret_id, tvb, optoff, 4, ENC_BIG_ENDIAN); - optoff += 4; - /*optleft -= 4;*/ - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_hmac_md5_hash, tvb, optoff, 16, ENC_ASCII|ENC_NA); - break; - } + proto_tree_add_item_ret_uint(tree, hf_bootp_option_dhcp_authentication_protocol, tvb, offset, 1, ENC_BIG_ENDIAN, &protocol); + offset++; - default: - if (optleft == 0) + algorithm = tvb_get_guint8(tvb, offset); + switch (protocol) { + + case AUTHEN_PROTO_DELAYED_AUTHEN: + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_alg_delay, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + + default: + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_algorithm, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + } + offset++; + + proto_tree_add_item_ret_uint(tree, hf_bootp_option_dhcp_authentication_rdm, tvb, offset, 1, ENC_BIG_ENDIAN, &rdm); + offset++; + + switch (rdm) { + + case AUTHEN_RDM_MONOTONIC_COUNTER: + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_rdm_replay_detection, tvb, offset, 8, ENC_BIG_ENDIAN); + break; + + default: + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_rdm_rdv, tvb, offset, 8, ENC_ASCII|ENC_NA); + break; + } + offset += 8; + + switch (protocol) { + + case AUTHEN_PROTO_DELAYED_AUTHEN: + switch (algorithm) { + + case AUTHEN_DELAYED_ALGO_HMAC_MD5: + if (option_data->dhcp_type && !strcmp(option_data->dhcp_type, OPT53_DISCOVER)) { + /* Discover has no Secret ID nor HMAC MD5 Hash */ + break; + } else { + if (tvb_reported_length_remaining(tvb, offset) < 31) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 31"); break; + } - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_information, tvb, optoff, optleft, ENC_ASCII|ENC_NA); + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_secret_id, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_hmac_md5_hash, tvb, offset, 16, ENC_ASCII|ENC_NA); break; } - break; default: - if (optleft == 0) + if (tvb_reported_length_remaining(tvb, offset) == 0) break; - proto_tree_add_item(v_tree, hf_bootp_option_dhcp_authentication_information, tvb, optoff, optleft, ENC_ASCII|ENC_NA); + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_information, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA); break; } break; - case 99: /* civic location (RFC 4776) */ + default: + if (tvb_reported_length_remaining(tvb, offset) == 0) + break; - optleft = optlen; - if (optleft >= 3) - { - proto_tree_add_item(v_tree, hf_bootp_option_civic_location_what, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_civic_location_country, tvb, optoff+1, 2, ENC_ASCII|ENC_NA); - optleft = optleft - 3; - optoff = optoff + 3; + proto_tree_add_item(tree, hf_bootp_option_dhcp_authentication_information, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA); + break; + } - while (optleft >= 2) - { - int calength = tvb_get_guint8(tvb, optoff+1); - proto_tree_add_item(v_tree, hf_bootp_option_civic_location_ca_type, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_civic_location_ca_length, tvb, optoff+1, 1, ENC_BIG_ENDIAN); + return tvb_captured_length(tvb); +} - optoff += 2; - optleft -= 2; +static int +dissect_bootpopt_client_network_interface_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int offset = 0; + guint8 id_type; + + id_type = tvb_get_guint8(tvb, offset); + offset++; + + if (id_type == 0x01) { + proto_tree_add_item(tree, hf_bootp_option_client_network_id_major_ver, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + proto_tree_add_item(tree, hf_bootp_option_client_network_id_minor_ver, + tvb, offset, 1, ENC_LITTLE_ENDIAN); + } - if (calength == 0) - continue; + return tvb_captured_length(tvb); +} - if (optleft >= calength) - { - proto_tree_add_item(v_tree, hf_bootp_option_civic_location_ca_value, tvb, optoff, calength, ENC_ASCII|ENC_NA); +static int +dissect_bootpopt_client_identifier_uuid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int offset = 0, length = tvb_reported_length(tvb); + guint8 byte; - optoff = optoff + calength; - optleft = optleft - calength; - } - else - { - optleft = 0; - expert_add_info(pinfo, vti, &ei_bootp_option_civic_location_bad_cattype); - } - } - } - break; + if (length > 0) + byte = tvb_get_guint8(tvb, offset); + else + byte = 0; + + /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll + guess that the first is the hwtype, and the last 6 + are the hw addr */ + /* See http://www.iana.org/assignments/arp-parameters */ + /* RFC2132 9.14 Client-identifier has the following to say: + A hardware type of 0 (zero) should be used when the value + field contains an identifier other than a hardware address + (e.g. a fully qualified domain name). */ + + if (length == 7 && byte > 0 && byte < 48) { + proto_tree_add_item(tree, hf_bootp_hw_type, tvb, offset, 1, ENC_NA); + if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802) + proto_tree_add_item(tree, hf_bootp_hw_ether_addr, tvb, offset+1, 6, ENC_NA); + else + proto_tree_add_string(tree, hf_bootp_client_hardware_address, tvb, offset+1, 6, + tvb_arphrdaddr_to_str(tvb, offset+1, 6, byte)); + } else if (length == 17 && byte == 0) { + /* Identifier is a UUID */ + proto_tree_add_item(tree, hf_bootp_client_identifier_uuid, tvb, offset + 1, 16, bootp_uuid_endian); + } else { + /* otherwise, it's opaque data */ + } - case 117: /* The Name Service Search Option for DHCP (RFC 2937) */ - if (optlen < 2) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 2"); - } else if (optlen & 1) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length (%u) isn't even number", optlen); - } else { - guint16 ns; - for (i = 0, ns = tvb_get_ntohs(tvb, optoff); i < optlen; i += 2, ns = tvb_get_ntohs(tvb, optoff + i)) { - switch (ns) { - case RFC2937_LOCAL_NAMING_INFORMATION: - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_name_service_search_option, tvb, optoff + i, 2, "Local naming information (e.g., an /etc/hosts file on a UNIX machine) (0)"); - break; - case RFC2937_DOMAIN_NAME_SERVER_OPTION: - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_name_service_search_option, tvb, optoff + i, 2, "Domain Name Server Option (6)"); - break; - case RFC2937_NETWORK_INFORMATION_SERVERS_OPTION: - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_name_service_search_option, tvb, optoff + i, 2, "Network Information Servers Option (41)"); - break; - case RFC2937_NETBIOS_OVER_TCP_IP_NAME_SERVER_OPTION: - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_name_service_search_option, tvb, optoff + i, 2, "NetBIOS over TCP/IP Name Server Option (44)"); - break; - case RFC2937_NETWORK_INFORMATION_SERVICE_PLUS_SERVERS_OPTION: - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_name_service_search_option, tvb, optoff + i, 2, "Network Information Service+ Servers Option (65)"); - break; - default: - expert_add_info_format(pinfo, vti, &ei_bootp_option_dhcp_name_service_invalid, - "Invalid Name Service (%u). RFC 2937 defines only 0, 6, 41, 44, and 65 as possible values.", ns); - break; - } - } - } - break; + return tvb_captured_length(tvb); +} - case 119: { /* Dynamic Host Configuration Protocol (DHCP) Domain Search Option (RFC 3397) */ - /* Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) (RFC 3396) */ - /* Domain Names - Implementation And Specification (RFC 1035) */ - char tmpChar[BOOTP_MAX_NO_CHAR]; - rfc3396_dns_domain_search_list.index_current_block++; - if (rfc3396_dns_domain_search_list.total_number_of_block > 1) { - g_snprintf(tmpChar, BOOTP_MAX_NO_CHAR, "%u/%u", rfc3396_dns_domain_search_list.index_current_block, rfc3396_dns_domain_search_list.total_number_of_block); - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_dns_domain_search_list_rfc_3396_detected, tvb, optoff, optlen, tmpChar); - if (rfc3396_dns_domain_search_list.index_current_block != rfc3396_dns_domain_search_list.total_number_of_block) { - g_snprintf(tmpChar, BOOTP_MAX_NO_CHAR, "%u/%u", rfc3396_dns_domain_search_list.total_number_of_block, rfc3396_dns_domain_search_list.total_number_of_block); - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_dns_domain_search_list_refer_last_option, tvb, optoff, optlen, tmpChar); - } - } +static int +dissect_bootpopt_civic_location(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; - if (rfc3396_dns_domain_search_list.tvb_composite == NULL && optlen) { - /* We use composite tvb for managing RFC 3396 */ - rfc3396_dns_domain_search_list.tvb_composite = tvb_new_composite(); - } + if (tvb_reported_length(tvb) >= 3) + { + proto_tree_add_item(tree, hf_bootp_option_civic_location_what, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item(tree, hf_bootp_option_civic_location_country, tvb, offset, 2, ENC_ASCII|ENC_NA); + offset += 2; - /* Concatenate the block before being interpreted for managing RFC 3396 */ - if (optlen) - tvb_composite_append(rfc3396_dns_domain_search_list.tvb_composite, tvb_new_subset(tvb, optoff, optlen, optlen)); + while (tvb_reported_length_remaining(tvb, offset) >= 2) + { + guint32 calength; + proto_tree_add_item(tree, hf_bootp_option_civic_location_ca_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item_ret_uint(tree, hf_bootp_option_civic_location_ca_length, tvb, offset, 1, ENC_BIG_ENDIAN, &calength); + offset++; - if (rfc3396_dns_domain_search_list.index_current_block == rfc3396_dns_domain_search_list.total_number_of_block - && rfc3396_dns_domain_search_list.tvb_composite) { - /* Here, we are into the last (or unique) option 119. */ - /* We will display the information about fqdn */ - unsigned int consumedx = 0; - unsigned int offset = 0; - tvb_composite_finalize(rfc3396_dns_domain_search_list.tvb_composite); + if (calength == 0) + continue; - while (offset < tvb_length(rfc3396_dns_domain_search_list.tvb_composite)) { - /* use the get_dns_name method that manages all techniques of RFC 1035 (compression pointer and so on) */ - consumedx = get_dns_name(rfc3396_dns_domain_search_list.tvb_composite, offset, tvb_length(rfc3396_dns_domain_search_list.tvb_composite), 0, &dns_name); - if (rfc3396_dns_domain_search_list.total_number_of_block == 1) { - /* RFC 3396 is not used, so we can easily link the fqdn with v_tree. */ - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_dns_domain_search_list_fqdn, tvb, optoff + offset, consumedx, dns_name); - } else { - /* RFC 3396 is used, so the option is split into several option 119. We don't link fqdn with v_tree. */ - proto_tree_add_string(v_tree, hf_bootp_option_dhcp_dns_domain_search_list_fqdn, tvb, 0, 0, dns_name); - } - offset += consumedx; + if (tvb_reported_length_remaining(tvb, offset) >= (int)calength) + { + proto_tree_add_item(tree, hf_bootp_option_civic_location_ca_value, tvb, offset, calength, ENC_ASCII|ENC_NA); + offset += calength; } - rfc3396_dns_domain_search_list.tvb_composite = NULL; - } - break; - } - case 120: { /* SIP Servers (RFC 3361) */ - /* Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) (RFC 3396) */ - /* Domain Names - Implementation And Specification (RFC 1035) */ - char tmpChar[BOOTP_MAX_NO_CHAR]; - rfc3396_sip_server.index_current_block++; - if (rfc3396_sip_server.total_number_of_block > 1) { - g_snprintf(tmpChar, BOOTP_MAX_NO_CHAR, "%u/%u", rfc3396_sip_server.index_current_block, rfc3396_sip_server.total_number_of_block); - proto_tree_add_string(v_tree, hf_bootp_option_sip_server_rfc_3396_detected, tvb, optoff, optlen, tmpChar); - if (rfc3396_sip_server.index_current_block != rfc3396_sip_server.total_number_of_block) { - g_snprintf(tmpChar, BOOTP_MAX_NO_CHAR, "%u/%u", rfc3396_sip_server.total_number_of_block, rfc3396_sip_server.total_number_of_block); - proto_tree_add_string(v_tree, hf_bootp_option_sip_server_refer_last_option, tvb, optoff, optlen, tmpChar); + else + { + expert_add_info(pinfo, tree, &ei_bootp_option_civic_location_bad_cattype); + break; } } + } + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_name_server_search(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0, length = tvb_reported_length(tvb); + guint16 ns; + + if (length < 2) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 2"); + return 1; + } else if (length & 1) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length (%u) isn't even number", length); + return 1; + } - if (rfc3396_sip_server.tvb_composite == NULL && optlen) { - /* We use composite tvb for managing RFC 3396 */ - rfc3396_sip_server.tvb_composite = tvb_new_composite(); + while (tvb_reported_length_remaining(tvb, offset) > 0) { + ns = tvb_get_ntohs(tvb, offset); + /* XXX - Make this a value_string */ + switch (ns) { + case RFC2937_LOCAL_NAMING_INFORMATION: + proto_tree_add_string(tree, hf_bootp_option_dhcp_name_service_search_option, tvb, offset, 2, "Local naming information (e.g., an /etc/hosts file on a UNIX machine) (0)"); + break; + case RFC2937_DOMAIN_NAME_SERVER_OPTION: + proto_tree_add_string(tree, hf_bootp_option_dhcp_name_service_search_option, tvb, offset, 2, "Domain Name Server Option (6)"); + break; + case RFC2937_NETWORK_INFORMATION_SERVERS_OPTION: + proto_tree_add_string(tree, hf_bootp_option_dhcp_name_service_search_option, tvb, offset, 2, "Network Information Servers Option (41)"); + break; + case RFC2937_NETBIOS_OVER_TCP_IP_NAME_SERVER_OPTION: + proto_tree_add_string(tree, hf_bootp_option_dhcp_name_service_search_option, tvb, offset, 2, "NetBIOS over TCP/IP Name Server Option (44)"); + break; + case RFC2937_NETWORK_INFORMATION_SERVICE_PLUS_SERVERS_OPTION: + proto_tree_add_string(tree, hf_bootp_option_dhcp_name_service_search_option, tvb, offset, 2, "Network Information Service+ Servers Option (65)"); + break; + default: + expert_add_info_format(pinfo, tree, &ei_bootp_option_dhcp_name_service_invalid, + "Invalid Name Service (%u). RFC 2937 defines only 0, 6, 41, 44, and 65 as possible values.", ns); + break; } + offset += 2; + } - /* Concatenate the block before being interpreted for managing RFC 3396 */ - if (optlen) - tvb_composite_append(rfc3396_sip_server.tvb_composite, tvb_new_subset(tvb, optoff, optlen, optlen)); + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_dhcp_domain_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int length = tvb_reported_length(tvb); + const guchar *dns_name; + guint dns_name_len; + + /* Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) (RFC 3396) */ + /* Domain Names - Implementation And Specification (RFC 1035) */ + rfc3396_dns_domain_search_list.index_current_block++; + if (rfc3396_dns_domain_search_list.total_number_of_block > 1) { + proto_tree_add_string(tree, hf_bootp_option_dhcp_dns_domain_search_list_rfc_3396_detected, tvb, 0, length, + wmem_strdup_printf(wmem_packet_scope(), "%u/%u", rfc3396_dns_domain_search_list.index_current_block, rfc3396_dns_domain_search_list.total_number_of_block)); + if (rfc3396_dns_domain_search_list.index_current_block != rfc3396_dns_domain_search_list.total_number_of_block) { + proto_tree_add_string(tree, hf_bootp_option_dhcp_dns_domain_search_list_refer_last_option, tvb, 0, length, + wmem_strdup_printf(wmem_packet_scope(), "%u/%u", rfc3396_dns_domain_search_list.total_number_of_block, rfc3396_dns_domain_search_list.total_number_of_block)); + } + } - if (rfc3396_sip_server.index_current_block == rfc3396_sip_server.total_number_of_block - && rfc3396_sip_server.tvb_composite) { - /* Here, we are into the last (or unique) option 120. */ - /* We will display the information about SIP server */ - guint8 enc; - unsigned int offset = 1; /* ignore enc */ - tvb_composite_finalize(rfc3396_sip_server.tvb_composite); + if (rfc3396_dns_domain_search_list.tvb_composite == NULL && length) { + /* We use composite tvb for managing RFC 3396 */ + rfc3396_dns_domain_search_list.tvb_composite = tvb_new_composite(); + } - enc = tvb_get_guint8(rfc3396_sip_server.tvb_composite, 0); - if (rfc3396_sip_server.total_number_of_block == 1) { + /* Concatenate the block before being interpreted for managing RFC 3396 */ + if (length) + tvb_composite_append(rfc3396_dns_domain_search_list.tvb_composite, tvb_new_subset_length(tvb, 0, length)); + + if (rfc3396_dns_domain_search_list.index_current_block == rfc3396_dns_domain_search_list.total_number_of_block + && rfc3396_dns_domain_search_list.tvb_composite) { + /* Here, we are into the last (or unique) option 119. */ + /* We will display the information about fqdn */ + unsigned int consumedx = 0; + unsigned int composite_offset = 0; + tvb_composite_finalize(rfc3396_dns_domain_search_list.tvb_composite); + + while (composite_offset < tvb_reported_length(rfc3396_dns_domain_search_list.tvb_composite)) { + /* use the get_dns_name method that manages all techniques of RFC 1035 (compression pointer and so on) */ + consumedx = get_dns_name(rfc3396_dns_domain_search_list.tvb_composite, composite_offset, + tvb_reported_length(rfc3396_dns_domain_search_list.tvb_composite), 0, &dns_name, &dns_name_len); + if (rfc3396_dns_domain_search_list.total_number_of_block == 1) { /* RFC 3396 is not used, so we can easily link the fqdn with v_tree. */ - proto_tree_add_uint(v_tree, hf_bootp_option_sip_server_enc, tvb, optoff, 1, enc); + proto_tree_add_string(tree, hf_bootp_option_dhcp_dns_domain_search_list_fqdn, tvb, composite_offset, consumedx, dns_name); } else { - /* RFC 3396 is used, so the option is split into several option 120. We don't link fqdn with v_tree. */ - proto_tree_add_uint(v_tree, hf_bootp_option_sip_server_enc, tvb, 0, 0, enc); + /* RFC 3396 is used, so the option is split into several option 119. We don't link fqdn with v_tree. */ + proto_tree_add_string(tree, hf_bootp_option_dhcp_dns_domain_search_list_fqdn, tvb, 0, 0, dns_name); } + composite_offset += consumedx; + } + rfc3396_dns_domain_search_list.tvb_composite = NULL; + } - switch (enc) { - case RFC_3361_ENC_FQDN: { - unsigned int consumedx = 0; - if (tvb_length(rfc3396_sip_server.tvb_composite) < 3) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 3 (len = %u)", tvb_length(rfc3396_sip_server.tvb_composite)); - break; - } + return tvb_captured_length(tvb); +} - while (offset < tvb_length(rfc3396_sip_server.tvb_composite)) { - /* use the get_dns_name method that manages all techniques of RFC 1035 (compression pointer and so on) */ - consumedx = get_dns_name(rfc3396_sip_server.tvb_composite, offset, tvb_length(rfc3396_sip_server.tvb_composite), 1 /* ignore enc */, &dns_name); +static int +dissect_bootpopt_sip_servers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int length = tvb_reported_length(tvb); + const guchar *dns_name; + guint dns_name_len; + + /* Encoding Long Options in the Dynamic Host Configuration Protocol (DHCPv4) (RFC 3396) */ + /* Domain Names - Implementation And Specification (RFC 1035) */ + rfc3396_sip_server.index_current_block++; + if (rfc3396_sip_server.total_number_of_block > 1) { + proto_tree_add_string(tree, hf_bootp_option_sip_server_rfc_3396_detected, tvb, 0, length, + wmem_strdup_printf(wmem_packet_scope(), "%u/%u", rfc3396_sip_server.index_current_block, rfc3396_sip_server.total_number_of_block)); + if (rfc3396_sip_server.index_current_block != rfc3396_sip_server.total_number_of_block) { + proto_tree_add_string(tree, hf_bootp_option_sip_server_refer_last_option, tvb, 0, length, + wmem_strdup_printf(wmem_packet_scope(), "%u/%u", rfc3396_sip_server.total_number_of_block, rfc3396_sip_server.total_number_of_block)); + } + } - if (rfc3396_sip_server.total_number_of_block == 1) { - /* RFC 3396 is not used, so we can easily link the fqdn with v_tree. */ - proto_tree_add_string(v_tree, hf_bootp_option_sip_server_name, tvb, optoff + offset, consumedx, dns_name); - } else { - /* RFC 3396 is used, so the option is split into several option 120. We don't link fqdn with v_tree. */ - proto_tree_add_string(v_tree, hf_bootp_option_sip_server_name, tvb, 0, 0, dns_name); - } - offset += consumedx; - } - rfc3396_sip_server.tvb_composite = NULL; + if (rfc3396_sip_server.tvb_composite == NULL && length) { + /* We use composite tvb for managing RFC 3396 */ + rfc3396_sip_server.tvb_composite = tvb_new_composite(); + } + + /* Concatenate the block before being interpreted for managing RFC 3396 */ + if (length) + tvb_composite_append(rfc3396_sip_server.tvb_composite, tvb_new_subset_length(tvb, 0, length)); + + if (rfc3396_sip_server.index_current_block == rfc3396_sip_server.total_number_of_block + && rfc3396_sip_server.tvb_composite) { + /* Here, we are into the last (or unique) option 120. */ + /* We will display the information about SIP server */ + guint8 enc; + unsigned int composite_offset = 1; /* ignore enc */ + tvb_composite_finalize(rfc3396_sip_server.tvb_composite); + + enc = tvb_get_guint8(rfc3396_sip_server.tvb_composite, 0); + if (rfc3396_sip_server.total_number_of_block == 1) { + /* RFC 3396 is not used, so we can easily link the fqdn with tree. */ + proto_tree_add_uint(tree, hf_bootp_option_sip_server_enc, tvb, 0, 1, enc); + } else { + /* RFC 3396 is used, so the option is split into several option 120. We don't link fqdn with tree. */ + proto_tree_add_uint(tree, hf_bootp_option_sip_server_enc, tvb, 0, 0, enc); + } + + switch (enc) { + case RFC_3361_ENC_FQDN: { + unsigned int consumedx = 0; + if (tvb_reported_length(rfc3396_sip_server.tvb_composite) < 3) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 3 (len = %u)", tvb_reported_length(rfc3396_sip_server.tvb_composite)); break; } - case RFC_3361_ENC_IPADDR: - if (tvb_length(rfc3396_sip_server.tvb_composite) < 5) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 5 (len = %u)", tvb_length(rfc3396_sip_server.tvb_composite)); - break; - } - /* x % 2^n == x & (2^n - 1) note : (assuming x is a positive integer) */ - if ((tvb_length(rfc3396_sip_server.tvb_composite) - 1) & 3) { - if (rfc3396_sip_server.total_number_of_block == 1) - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't a multiple of 4 plus 1 (len = %u).", tvb_length(rfc3396_sip_server.tvb_composite)); - else - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, - "length isn't a multiple of 4 plus 1 (len = %u). For your information with RFC 3396, the length is the length sum of all options 120 into this BOOTP packet.", - tvb_length(rfc3396_sip_server.tvb_composite)); - break; - } - while (offset < tvb_length(rfc3396_sip_server.tvb_composite)) { - if (rfc3396_sip_server.total_number_of_block == 1) { - /* RFC 3396 is not used, so we can easily link the fqdn with v_tree. */ - proto_tree_add_item(v_tree, hf_bootp_option_sip_server_address, rfc3396_sip_server.tvb_composite, offset, 4, ENC_BIG_ENDIAN); - } else { - /* RFC 3396 is used, so the option is split into several option 120. We don't link fqdn with v_tree. */ - /* Since we don't use the "numbered argument" as described by README.developer, we have to repeat the arguments :( */ - g_snprintf(tmpChar, BOOTP_MAX_NO_CHAR, "%u.%u.%u.%u (%u.%u.%u.%u)", - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset + 1), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset + 2), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset + 3), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset + 1), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset + 2), - tvb_get_guint8(rfc3396_sip_server.tvb_composite, offset + 3) - ); - proto_tree_add_string(v_tree, hf_bootp_option_sip_server_address_stringz, tvb, 0, 0, tmpChar); - } - offset += 4; + + while (composite_offset < tvb_reported_length(rfc3396_sip_server.tvb_composite)) { + /* use the get_dns_name method that manages all techniques of RFC 1035 (compression pointer and so on) */ + consumedx = get_dns_name(rfc3396_sip_server.tvb_composite, composite_offset, tvb_reported_length(rfc3396_sip_server.tvb_composite), + 1 /* ignore enc */, &dns_name, &dns_name_len); + + if (rfc3396_sip_server.total_number_of_block == 1) { + /* RFC 3396 is not used, so we can easily link the fqdn with v_tree. */ + proto_tree_add_string(tree, hf_bootp_option_sip_server_name, tvb, composite_offset, consumedx, dns_name); + } else { + /* RFC 3396 is used, so the option is split into several option 120. We don't link fqdn with v_tree. */ + proto_tree_add_string(tree, hf_bootp_option_sip_server_name, tvb, 0, 0, format_text(wmem_packet_scope(), dns_name, dns_name_len)); } - break; - default: - expert_add_info_format(pinfo, vti, &ei_bootp_option_sip_server_address_encoding, "RFC 3361 defines only 0 and 1 for Encoding byte (Encoding = %u).", enc); - break; + composite_offset += consumedx; } - } - break; - } - case 121: /* Classless Static Route */ - case 249: { /* Classless Static Route (Microsoft) */ - int mask_width, significant_octets; - optend = optoff + optlen; - /* minimum length is 5 bytes */ - if (optlen < 5) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't >= 5"); + rfc3396_sip_server.tvb_composite = NULL; break; } - while (optoff < optend) { - mask_width = tvb_get_guint8(tvb, optoff); - /* mask_width <= 32 */ - if (mask_width > 32) { - expert_add_info_format(pinfo, vti, &ei_bootp_option_classless_static_route, "Mask width (%d) > 32", mask_width); + case RFC_3361_ENC_IPADDR: + if (tvb_reported_length(rfc3396_sip_server.tvb_composite) < 5) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 5 (len = %u)", tvb_reported_length(rfc3396_sip_server.tvb_composite)); break; } - significant_octets = (mask_width + 7) / 8; - vti = proto_tree_add_text(v_tree, tvb, optoff, - 1 + significant_octets + 4, - "Subnet/MaskWidth-Router: "); - optoff++; - /* significant octets + router(4) */ - if (optend < optoff + significant_octets + 4) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Remaining length (%d) < %d bytes", optend - optoff, significant_octets + 4); + /* x % 2^n == x & (2^n - 1) note : (assuming x is a positive integer) */ + if ((tvb_reported_length(rfc3396_sip_server.tvb_composite) - 1) & 3) { + if (rfc3396_sip_server.total_number_of_block == 1) + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't a multiple of 4 plus 1 (len = %u).", tvb_reported_length(rfc3396_sip_server.tvb_composite)); + else + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, + "length isn't a multiple of 4 plus 1 (len = %u). For your information with RFC 3396, the length is the length sum of all options 120 into this BOOTP packet.", + tvb_reported_length(rfc3396_sip_server.tvb_composite)); break; } - if(mask_width == 0) - proto_item_append_text(vti, "default"); - else { - for(i = 0 ; i < significant_octets ; i++) { - if (i > 0) - proto_item_append_text(vti, "."); - byte = tvb_get_guint8(tvb, optoff++); - proto_item_append_text(vti, "%d", byte); + while (composite_offset < tvb_reported_length(rfc3396_sip_server.tvb_composite)) { + if (rfc3396_sip_server.total_number_of_block == 1) { + /* RFC 3396 is not used, so we can easily link the fqdn with v_tree. */ + proto_tree_add_item(tree, hf_bootp_option_sip_server_address, rfc3396_sip_server.tvb_composite, composite_offset, 4, ENC_BIG_ENDIAN); + } else { + guint32 sip_server = tvb_get_ipv4(rfc3396_sip_server.tvb_composite, composite_offset); + /* RFC 3396 is used, so the option is split into several option 120. We don't link fqdn with v_tree. */ + proto_tree_add_ipv4(tree, hf_bootp_option_sip_server_address, tvb, 0, 0, sip_server); } - for(i = significant_octets ; i < 4 ; i++) - proto_item_append_text(vti, ".0"); - proto_item_append_text(vti, "/%d", mask_width); + composite_offset += 4; } - proto_item_append_text(vti, "-%s", tvb_ip_to_str(tvb, optoff)); - optoff += 4; + break; + default: + expert_add_info_format(pinfo, tree, &ei_bootp_option_sip_server_address_encoding, "RFC 3361 defines only 0 and 1 for Encoding byte (Encoding = %u).", enc); + break; } - break; } - case 123: /* coordinate based location RFC 3825 or CableLabs DSS_ID */ - if (optlen == 16) { - int c; - unsigned char lci[16]; - struct rfc3825_location_fixpoint_t location_fp; - struct rfc3825_location_decimal_t location; + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_classless_static_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + int i, mask_width, significant_octets; + proto_item* route_item; + + /* minimum length is 5 bytes */ + if (tvb_reported_length(tvb) < 5) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length isn't >= 5"); + return 1; + } + while (tvb_reported_length_remaining(tvb, offset) > 0) { + mask_width = tvb_get_guint8(tvb, offset); + /* mask_width <= 32 */ + if (mask_width > 32) { + expert_add_info_format(pinfo, tree, &ei_bootp_option_classless_static_route, "Mask width (%d) > 32", mask_width); + break; + } + significant_octets = (mask_width + 7) / 8; + route_item = proto_tree_add_bytes_format(tree, hf_bootp_option_classless_static_route, tvb, offset, + 1 + significant_octets + 4, NULL, " "); + offset++; + /* significant octets + router(4) */ + if (tvb_reported_length_remaining(tvb, offset + significant_octets + 4) < 0) { + expert_add_info_format(pinfo, route_item, &ei_bootp_bad_length, "Remaining length (%d) < %d bytes", tvb_reported_length_remaining(tvb, offset), significant_octets + 4); + break; + } + if(mask_width == 0) + proto_item_append_text(route_item, "default"); + else { + for(i = 0 ; i < significant_octets ; i++) { + if (i > 0) + proto_item_append_text(route_item, "."); + proto_item_append_text(route_item, "%d", tvb_get_guint8(tvb, offset++)); + } + for(i = significant_octets ; i < 4 ; i++) + proto_item_append_text(route_item, ".0"); + proto_item_append_text(route_item, "/%d", mask_width); + } + proto_item_append_text(route_item, "-%s", tvb_ip_to_str(tvb, offset)); + offset += 4; + } - for (c=0; c < 16;c++) - lci[c] = (unsigned char) tvb_get_guint8(tvb, optoff + c); + return tvb_captured_length(tvb); +} - /* convert lci encoding into fixpoint location */ - rfc3825_lci_to_fixpoint(lci, &location_fp); +static int +dissect_bootpopt_coordinate_based_location(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0, length = tvb_reported_length(tvb); + proto_item* ti; - /* convert location from decimal to fixpoint */ - i = rfc3825_fixpoint_to_decimal(&location_fp, &location); + if (length == 16) { + int ret; + unsigned char lci[16]; + struct rfc3825_location_fixpoint_t location_fp; + struct rfc3825_location_decimal_t location; - if (i != RFC3825_NOERROR) { - proto_tree_add_text(v_tree, tvb, optoff, optlen, "Error: %s", val_to_str_const(i, rfc3825_error_types, "Unknown")); - } else { - proto_tree_add_text(v_tree, tvb, optoff, 5, "Latitude: %15.10f", location.latitude); - proto_tree_add_text(v_tree, tvb, optoff+5, 5, "Longitude: %15.10f", location.longitude); - proto_tree_add_text(v_tree, tvb, optoff, 1, "Latitude resolution: %15.10f", location.latitude_res); - proto_tree_add_text(v_tree, tvb, optoff+5, 1, "Longitude resolution: %15.10f", location.longitude_res); - proto_tree_add_text(v_tree, tvb, optoff+12, 4, "Altitude: %15.10f", location.altitude); - proto_tree_add_text(v_tree, tvb, optoff+10, 2, "Altitude resolution: %15.10f", location.altitude_res); - proto_tree_add_text(v_tree, tvb, optoff+10, 1, "Altitude type: %s (%d)", val_to_str_const(location.altitude_type, altitude_type_values, "Unknown"), location.altitude_type); - proto_tree_add_text(v_tree, tvb, optoff+15, 1, "Map Datum: %s (%d)", val_to_str_const(location.datum_type, map_datum_type_values, "Unknown"), location.datum_type); - } - } else if (optlen < 69) { /* CableLabs DSS_ID */ + tvb_memcpy(tvb, lci, offset, 16); - proto_tree_add_item(v_tree, hf_bootp_option_cl_dss_id_option, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_cl_dss_id_len, tvb, optoff+1, 1, ENC_BIG_ENDIAN); - s_len = tvb_get_guint8(tvb, optoff+1); - proto_tree_add_item(v_tree, hf_bootp_option_cl_dss_id, tvb, optoff+2, s_len, ENC_ASCII|ENC_NA); + /* convert lci encoding into fixpoint location */ + rfc3825_lci_to_fixpoint(lci, &location_fp); - if (optlen > s_len+2) { /* Second DSS_ID*/ + /* convert location from decimal to fixpoint */ + ret = rfc3825_fixpoint_to_decimal(&location_fp, &location); - proto_tree_add_item(v_tree, hf_bootp_option_cl_dss_id_option, tvb, optoff+2+s_len, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_cl_dss_id_len, tvb, optoff+1+2+s_len, 1, ENC_BIG_ENDIAN); - s_len = tvb_get_guint8(tvb, optoff+1+2+s_len); - proto_tree_add_item(v_tree, hf_bootp_option_cl_dss_id, tvb, optoff+2+2+s_len, s_len, ENC_ASCII|ENC_NA); - } + if (ret != RFC3825_NOERROR) { + ti = proto_tree_add_uint(tree, hf_bootp_option_rfc3825_error, tvb, offset, 1, ret); + proto_item_set_len(ti, length); } else { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Invalid length of DHCP option!"); + proto_tree_add_double_format_value(tree, hf_bootp_option_rfc3825_latitude, tvb, offset, 5, location.latitude, "%15.10f", location.latitude); + proto_tree_add_double_format_value(tree, hf_bootp_option_rfc3825_longitude, tvb, offset+5, 5, location.longitude, "%15.10f", location.longitude); + proto_tree_add_double_format_value(tree, hf_bootp_option_rfc3825_latitude_res, tvb, offset, 1, location.latitude_res, "%15.10f", location.latitude_res); + proto_tree_add_double_format_value(tree, hf_bootp_option_rfc3825_longitude_res, tvb, offset+5, 1, location.longitude_res, "%15.10f", location.longitude_res); + proto_tree_add_double_format_value(tree, hf_bootp_option_rfc3825_altitude, tvb, offset+12, 4, location.altitude, "%15.10f", location.altitude); + proto_tree_add_double_format_value(tree, hf_bootp_option_rfc3825_altitide_res, tvb, offset+10, 2, location.altitude_res, "%15.10f", location.altitude_res); + proto_tree_add_uint(tree, hf_bootp_option_rfc3825_altitude_type, tvb, offset+10, 1, location.altitude_type); + proto_tree_add_uint(tree, hf_bootp_option_rfc3825_map_datum, tvb, offset+15, 1, location.datum_type); } - break; + } else if (length < 69) { /* CableLabs DSS_ID */ + int s_len; - case 124: { /* V-I Vendor Class */ - int data_len; + proto_tree_add_item(tree, hf_bootp_option_cl_dss_id_option, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_bootp_option_cl_dss_id_len, tvb, offset+1, 1, ENC_BIG_ENDIAN); + s_len = tvb_get_guint8(tvb, offset+1); + proto_tree_add_item(tree, hf_bootp_option_cl_dss_id, tvb, offset+2, s_len, ENC_ASCII|ENC_NA); - if (optlen == 1) { - /* CableLab specific */ - proto_tree_add_item(v_tree, hf_bootp_option_vi_class_cl_address_mode, tvb, optoff, optlen, ENC_BIG_ENDIAN); - break; + if (length > s_len+2) { /* Second DSS_ID*/ + + proto_tree_add_item(tree, hf_bootp_option_cl_dss_id_option, tvb, offset+2+s_len, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_bootp_option_cl_dss_id_len, tvb, offset+1+2+s_len, 1, ENC_BIG_ENDIAN); + s_len = tvb_get_guint8(tvb, offset+1+2+s_len); + proto_tree_add_item(tree, hf_bootp_option_cl_dss_id, tvb, offset+2+2+s_len, s_len, ENC_ASCII|ENC_NA); } + } else { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Invalid length of DHCP option!"); + } - optleft = optlen; + return tvb_captured_length(tvb); +} - while (optleft > 0) { +static int +dissect_bootpopt_vi_vendor_class(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + int data_len; - if (optleft < 5) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length < 5"); - break; - } + if (tvb_reported_length(tvb) == 1) { + /* CableLab specific */ + proto_tree_add_item(tree, hf_bootp_option_vi_class_cl_address_mode, tvb, 0, 1, ENC_BIG_ENDIAN); + return 1; + } - proto_tree_add_item(v_tree, hf_bootp_option_vi_class_enterprise, tvb, optoff, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_vi_class_data_length, tvb, optoff, 1, ENC_BIG_ENDIAN); - data_len = tvb_get_guint8(tvb, optoff + 4); + while (tvb_reported_length_remaining(tvb, offset) >= 5) { - optoff += 5; - optleft -= 5; + proto_tree_add_item(tree, hf_bootp_option_vi_class_enterprise, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_bootp_option_vi_class_data_length, tvb, offset, 1, ENC_BIG_ENDIAN); + data_len = tvb_get_guint8(tvb, offset); + offset += 1; - proto_tree_add_item(v_tree, hf_bootp_option_vi_class_data, tvb, optoff, data_len, ENC_ASCII|ENC_NA); + proto_tree_add_item(tree, hf_bootp_option_vi_class_data, tvb, offset, data_len, ENC_ASCII|ENC_NA); - /* look for next enterprise number */ - optoff += data_len; - optleft -= data_len; - } - break; + /* look for next enterprise number */ + offset += data_len; } - case 125: { /* V-I Vendor-specific Information */ - int enterprise = 0; - int s_end = 0; - int s_option_len = 0; - proto_tree *e_tree = 0; + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length < 5"); + } - optend = optoff + optlen; - optleft = optlen; + return tvb_captured_length(tvb); +} - while (optleft > 0) { +static int +dissect_bootpopt_forcerenew_nonce(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int offset = 0; + while ( tvb_reported_length_remaining(tvb, offset) > 0) { + proto_tree_add_item(tree, hf_bootp_option_forcerenew_nonce_algo, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + } - if (optleft < 5) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length < 5"); - break; - } + return tvb_captured_length(tvb); +} - enterprise = tvb_get_ntohl(tvb, optoff); - vti = proto_tree_add_item(v_tree, hf_bootp_option125_enterprise, tvb, optoff, 4, ENC_BIG_ENDIAN); +static int +dissect_bootpopt_rdnss(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + int offset = 0; + const guchar *dns_name; + guint dns_name_len; - s_option_len = tvb_get_guint8(tvb, optoff + 4); + if (tvb_reported_length(tvb) < 10) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be >= 10"); + return 1; + } + proto_tree_add_item(tree, hf_bootp_option_rdnss_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_bootp_option_rdnss_pref, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(tree, hf_bootp_option_rdnss_prim_dns_server, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_bootp_option_rdnss_sec_dns_server, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + get_dns_name(tvb, offset, tvb_reported_length_remaining(tvb,offset), offset, &dns_name, &dns_name_len); + proto_tree_add_string(tree, hf_bootp_option_rdnss_domain, tvb, offset, + tvb_reported_length_remaining(tvb,offset), format_text(wmem_packet_scope(), dns_name, dns_name_len)); + + return tvb_captured_length(tvb); +} - optoff += 5; - optleft -= 5; +static int +dissect_bootpopt_dhcp_captive_portal(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + proto_item *ti_cp; + ti_cp = proto_tree_add_item(tree, hf_bootp_option_captive_portal, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA); + PROTO_ITEM_SET_URL(ti_cp); - /* Handle DSL Forum TR-111 Option 125 */ - switch (enterprise) { + return tvb_captured_length(tvb); +} - case 3561: /* ADSL Forum */ - s_end = optoff + s_option_len; - if ( s_end > optend ) { - expert_add_info_format(pinfo, vti, &ei_bootp_option125_enterprise_malformed, "no room left in option for enterprise %u data", enterprise); - break; - } +static int +dissect_bootpopt_bulk_lease_query_start(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + if (tvb_reported_length(tvb) != 4) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be 4"); + return 1; + } + proto_tree_add_item(tree, hf_bootp_option_bulk_lease_query_start, tvb, 0, 4, ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN); - e_tree = proto_item_add_subtree(vti, ett_bootp_option); - while (optoff < s_end) { + return tvb_captured_length(tvb); +} - optoff = dissect_vendor_tr111_suboption(pinfo, vti, e_tree, tvb, optoff, s_end); - } - break; +static int +dissect_bootpopt_bulk_lease_query_end(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + if (tvb_reported_length(tvb) != 4) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be 4"); + return 1; + } + proto_tree_add_item(tree, hf_bootp_option_bulk_lease_query_end, tvb, 0, 4, ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN); - case 4491: /* CableLab */ - s_end = optoff + s_option_len; - if ( s_end > optend ) { - expert_add_info_format(pinfo, vti, &ei_bootp_option125_enterprise_malformed, "no room left in option for enterprise %u data", enterprise); - break; - } + return tvb_captured_length(tvb); +} - e_tree = proto_item_add_subtree(vti, ett_bootp_option); - while (optoff < s_end) { - optoff = dissect_vendor_cl_suboption(pinfo, vti, e_tree, tvb, optoff, s_end); - } - break; +static int +dissect_bootpopt_bulk_lease_base_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + if (tvb_reported_length(tvb) != 4) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be 4"); + return 1; + } + proto_tree_add_item(tree, hf_bootp_option_bulk_lease_base_time, tvb, 0, 4, ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN); - default: - /* skip over the data and look for next enterprise number */ - optoff += s_option_len; - } + return tvb_captured_length(tvb); +} - optleft -= s_option_len; - } - break; +static int +dissect_bootpopt_bulk_lease_status_code(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + if (tvb_reported_length(tvb) < 1) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must >= 1"); + return 1; } - - case 212: { /* 6RD option (RFC 5969) */ - if (optlen < 22) { - expert_add_info(pinfo, vti, &ei_bootp_option_6RD_malformed); - break; + proto_tree_add_item(tree, hf_bootp_option_bulk_lease_status_code, tvb, 0, 1, ENC_BIG_ENDIAN); + if ( tvb_reported_length_remaining(tvb, 1) > 0) { + proto_tree_add_item(tree, hf_bootp_option_bulk_lease_status_message, tvb, 1, tvb_reported_length_remaining(tvb, 1), ENC_UTF_8|ENC_NA); } - proto_tree_add_item(v_tree, hf_bootp_option_6RD_ipv4_mask_len, tvb, optoff, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_6RD_prefix_len, tvb, optoff+1, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(v_tree, hf_bootp_option_6RD_prefix, tvb, optoff+2, 16, ENC_NA); - proto_tree_add_item(v_tree, hf_bootp_option_6RD_border_relay_ip, tvb, optoff+18, 4, ENC_BIG_ENDIAN); - - /* More Border Relay IPv4 addresses included */ - if (optlen > 22) { - optoff += 22; - for (i = optoff, optleft = optlen - 22; optleft > 0; i += 4, optleft -= 4) { - if (optleft < 4) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "Option length isn't a multiple of 4"); - break; - } + return tvb_captured_length(tvb); +} - proto_tree_add_item(v_tree, hf_bootp_option_6RD_border_relay_ip, tvb, i, 4, ENC_BIG_ENDIAN); - } +static int +dissect_bootpopt_pcp_server(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + proto_tree *tree_pcp; + int offset = 0; + guint8 list_length; + guint8 ip_list_length; + proto_item *ti_pcp; + + if (tvb_reported_length(tvb) < 5) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must >= 5"); + return 1; + } + while (tvb_reported_length_remaining(tvb, offset) >= 5) { + ip_list_length = 0; + list_length = tvb_get_guint8(tvb, offset); + tree_pcp = proto_tree_add_subtree(tree, tvb, offset, list_length, ett_bootp_option158_pcp_list, + &ti_pcp, "PCP server list"); + proto_tree_add_item(tree_pcp, hf_bootp_option_pcp_list_length, tvb, offset, 1, ENC_NA); + offset += 1; + ip_list_length += 1; + while (((list_length - 1)%4 == 0) && (ip_list_length < list_length) && tvb_reported_length_remaining(tvb,offset) >= 4) { + proto_tree_add_item(tree_pcp, hf_bootp_option_pcp_server, tvb, offset, 4, ENC_NA); + offset += 4; + ip_list_length += 4; } - break; } - default: /* not special */ - /* The PacketCable CCC option number can vary. If this is a CCC option, - handle it as a special. - */ - if (code == pkt_ccc_option) { - ftype = special; - proto_item_append_text(vti, - "CableLabs Client Configuration (%d bytes)", - optlen); - optend = optoff + optlen; - while (optoff < optend) { - switch (pkt_ccc_protocol_version) { - - case PACKETCABLE_CCC_I05: - optoff = dissect_packetcable_i05_ccc(pinfo, vti, v_tree, tvb, optoff, optend); - break; - case PACKETCABLE_CCC_DRAFT5: - case PACKETCABLE_CCC_RFC_3495: - optoff = dissect_packetcable_ietf_ccc(pinfo, vti, v_tree, tvb, optoff, optend, pkt_ccc_protocol_version); - break; - default: /* XXX Should we do something here? */ - break; - } - } - } else { - option_handled = FALSE; - } + return tvb_captured_length(tvb); +} - break; +static int +dissect_bootpopt_portparams(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + if (tvb_reported_length(tvb) != 4) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be 4"); + return 1; } + proto_tree_add_item(tree, hf_bootp_option_portparams_offset, tvb, 0, 1, ENC_NA); + proto_tree_add_item(tree, hf_bootp_option_portparams_psid_length, tvb, 1, 1, ENC_NA); + proto_tree_add_item(tree, hf_bootp_option_portparams_psid, tvb, 2, 2, ENC_NA); - basictype_consumed = bootp_handle_basic_types(pinfo, v_tree, vti, tvb, ftype, - optoff, optlen, opt->phf, &default_hfs); + return tvb_captured_length(tvb); +} - if ((basictype_consumed == 0) && (option_handled == FALSE) && - (opt->phf == NULL) && (optlen > 0)) { - proto_tree_add_item(v_tree, hf_bootp_option_value, tvb, voff+2, optlen, ENC_NA); +static int +dissect_bootpopt_6RD_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + + if (tvb_reported_length(tvb) < 22) { + expert_add_info(pinfo, tree, &ei_bootp_option_6RD_malformed); + return 1; } - return consumed; + proto_tree_add_item(tree, hf_bootp_option_6RD_ipv4_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_bootp_option_6RD_prefix_len, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_bootp_option_6RD_prefix, tvb, offset+2, 16, ENC_NA); + proto_tree_add_item(tree, hf_bootp_option_6RD_border_relay_ip, tvb, offset+18, 4, ENC_BIG_ENDIAN); + + /* More Border Relay IPv4 addresses included */ + if (tvb_reported_length(tvb) > 22) { + offset += 22; + while (tvb_reported_length_remaining(tvb, offset) >= 4) { + proto_tree_add_item(tree, hf_bootp_option_6RD_border_relay_ip, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Option length isn't a multiple of 4"); + } + } + + return tvb_captured_length(tvb); +} + +static int +dissect_bootpopt_avaya_ip_telephone(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + proto_tree *o242avaya_v_tree; + proto_item *avaya_ti; + const guint8 *avaya_option = NULL; + gchar *field = NULL; + wmem_strbuf_t *avaya_param_buf = NULL; + + /* minimum length is 5 bytes */ + if (tvb_reported_length(tvb) < 5) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "Avaya IP Telephone option length isn't >= 5"); + return 1; + } + avaya_ti = proto_tree_add_item_ret_string(tree, hf_bootp_option242_avaya, tvb, offset, tvb_reported_length(tvb), ENC_ASCII|ENC_NA, wmem_packet_scope(), &avaya_option); + o242avaya_v_tree = proto_item_add_subtree(avaya_ti, ett_bootp_option242_suboption); + avaya_param_buf = wmem_strbuf_new(wmem_packet_scope(), ""); + for ( field = strtok((char*)avaya_option, ","); field; field = strtok(NULL, ",") ) { + if (!strchr(field, '=')) { + if (wmem_strbuf_get_len(avaya_param_buf) == 0) { + expert_add_info_format(pinfo, avaya_ti, &hf_bootp_subopt_unknown_type, "ERROR, Unknown parameter %s", field); + offset += (int)strlen(field); + break; + } + wmem_strbuf_append_printf(avaya_param_buf,",%s", field); + } + else { + if (wmem_strbuf_get_len(avaya_param_buf) > 0) { + dissect_vendor_avaya_param(o242avaya_v_tree, pinfo, avaya_ti, tvb, offset, avaya_param_buf); + offset += (int)wmem_strbuf_get_len(avaya_param_buf) + 1; + wmem_strbuf_truncate(avaya_param_buf, 0); + } + wmem_strbuf_append(avaya_param_buf, field); + } + } + if (wmem_strbuf_get_len(avaya_param_buf) > 0) { + dissect_vendor_avaya_param(o242avaya_v_tree, pinfo, avaya_ti, tvb, offset, avaya_param_buf); + } + + return tvb_captured_length(tvb); } static const value_string option82_suboption_vals[] = { @@ -2655,6 +3143,7 @@ static const value_string option82_suboption_vals[] = { { 9, "Vendor-Specific Information" }, { 10, "Flags" }, { 11, "Server ID Override" }, + { 12, "Relay Agent Identifier" }, { 150, "Link selection (Cisco proprietary)" }, { 151, "VRF name/VPN ID" }, { 152, "Server ID Override (Cisco proprietary)" }, @@ -2665,13 +3154,13 @@ static int bootp_dhcp_decode_agent_info(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend) { - int suboptoff = optoff; - guint8 subopt, idx, vs_opt, vs_len; - int subopt_len, subopt_end, datalen; - guint32 enterprise; + int suboptoff = optoff; + guint8 subopt, idx, vs_opt, vs_len; + int subopt_len, subopt_end, datalen; + guint32 enterprise; proto_item *vti, *ti; proto_tree *o82_v_tree, *o82_sub_tree; - guint8 tag, tag_len; + guint8 tag, tag_len; struct basic_types_hfs default_hfs = { &hf_bootp_option82_value, @@ -2704,6 +3193,7 @@ bootp_dhcp_decode_agent_info(packet_info *pinfo, proto_item *v_ti, proto_tree *v {9, {"Vendor-Specific Information", special, &hf_bootp_option82_vi}}, /* [RFC 4243] */ {10, {"Flags", val_u_byte, &hf_bootp_option82_flags}}, /* [RFC5010] */ {11, {"Server ID Override", ipv4, &hf_bootp_option82_server_id_override}}, /* [RFC 5107] */ + {12, {"Relay Agent Identifier", bytes, &hf_bootp_option82_relay_agent_id}}, /* [RFC 6925] */ {150, {"Link selection (Cisco proprietary)", ipv4, &hf_bootp_option82_link_selection_cisco}}, /* [RFC3527] */ {151, {"VRF name/VPN ID", special, &hf_bootp_option82_vrf_name_vpn_id}}, /* [RFC2685] */ {152, {"Server ID Override (Cisco proprietary)", ipv4, &hf_bootp_option82_server_id_override_cisco}} /* [RFC 5107] */ @@ -2803,12 +3293,15 @@ bootp_dhcp_decode_agent_info(packet_info *pinfo, proto_item *v_ti, proto_tree *v } break; case 151: - if (subopt_len != 7) { - expert_add_info_format(pinfo, vti, &ei_bootp_bad_length, "length isn't 7"); - break; + if (subopt_len == 1) { + proto_tree_add_item(o82_v_tree, hf_bootp_option82_vrf_name_global, tvb, suboptoff, 1, ENC_NA); + } + else if (subopt_len != 7) { + proto_tree_add_item(o82_v_tree, hf_bootp_option82_vrf_name, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA); + } else { + proto_tree_add_item(o82_v_tree, hf_bootp_option82_vrf_name_vpn_id_oui, tvb, suboptoff, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(o82_v_tree, hf_bootp_option82_vrf_name_vpn_id_index, tvb, suboptoff+3, 4, ENC_BIG_ENDIAN); } - proto_tree_add_item(o82_v_tree, hf_bootp_option82_vrf_name_vpn_id_oui, tvb, suboptoff, 3, ENC_BIG_ENDIAN); - proto_tree_add_item(o82_v_tree, hf_bootp_option82_vrf_name_vpn_id_index, tvb, suboptoff+3, 4, ENC_BIG_ENDIAN); break; default: if (o82_opt[idx].info.phf != NULL) @@ -2830,6 +3323,18 @@ bootp_dhcp_decode_agent_info(packet_info *pinfo, proto_item *v_ti, proto_tree *v return optoff; } +static int +dissect_bootpopt_relay_agent_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + offset = bootp_dhcp_decode_agent_info(pinfo, tree, tree, tvb, offset, tvb_reported_length(tvb)); + } + + return tvb_captured_length(tvb); +} + static const value_string option43_pxeclient_suboption_vals[] = { { 0, "Padding" }, { 1, "PXE mtftp IP" }, @@ -2853,9 +3358,9 @@ static int dissect_vendor_pxeclient_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend) { - int suboptoff = optoff; - guint8 subopt; - guint8 subopt_len; + int suboptoff = optoff; + guint8 subopt; + guint8 subopt_len; proto_tree *o43pxeclient_v_tree; proto_item *vti, *ti; @@ -2951,6 +3456,112 @@ dissect_vendor_pxeclient_suboption(packet_info *pinfo, proto_item *v_ti, proto_t return optoff; } +static gboolean +dissect_pxeclient_vendor_info_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + int offset = 0; + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + proto_tree* vendor_tree; + + /* PXE protocol 2.1 as described in the Intel specs */ + if ((option_data->vendor_class_id == NULL) || + (strncmp((const gchar*)option_data->vendor_class_id, "PXEClient", strlen("PXEClient")) != 0)) + return FALSE; + + proto_item_append_text(tree, " (PXEClient)"); + vendor_tree = proto_item_add_subtree(tree, ett_bootp_option); + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + offset = dissect_vendor_pxeclient_suboption(pinfo, tree, vendor_tree, + tvb, offset, tvb_reported_length(tvb)); + } + + return TRUE; +} + +static void +dissect_vendor_avaya_param(proto_tree *tree, packet_info *pinfo, proto_item *vti, + tvbuff_t *tvb, int optoff, wmem_strbuf_t *avaya_param_buf) +{ + const gchar *field; + int len; + + field = wmem_strbuf_get_str(avaya_param_buf); + len = (int)wmem_strbuf_get_len(avaya_param_buf); + + if((strncmp(field, "TLSSRVR=", 8) == 0) && ( len > 8 )) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_tlssrvr, tvb, optoff, len, field + 8); + } + else if((strncmp(field, "HTTPSRVR=", 9) == 0) && ( len > 9)) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_httpsrvr, tvb, optoff, len, field + 9); + } + else if((strncmp(field, "HTTPDIR=", 8) == 0) && ( len > 8)) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_httpdir, tvb, optoff, len, field + 8); + } + else if((strncmp(field, "STATIC=", 7) == 0) && ( len > 7)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_static, tvb, optoff, len, field + 7, "%s (%s)", field + 7, str_to_str(field + 7, option242_avaya_static_vals, "Unknown (%s)")); + } + else if((strncmp(field, "MCIPADD=", 8) == 0) && ( len > 8)) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_mcipadd, tvb, optoff, len, field + 8); + } + else if((strncmp(field, "DOT1X=", 6) == 0) && ( len > 6)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_dot1x, tvb, optoff, len, field + 6, "%s (%s)", field + 6, str_to_str(field + 6, option242_avaya_dot1x_vals, "Unknown (%s)")); + } + else if((strncmp(field, "ICMPDU=", 7) == 0) && ( len > 7)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_icmpdu, tvb, optoff, len, field + 7, "%s (%s)", field + 7, str_to_str(field + 7, option242_avaya_icmpdu_vals, "Unknown (%s)")); + } + else if((strncmp(field, "ICMPRED=", 8) == 0) && ( len > 8)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_icmpred, tvb, optoff, len, field + 8, "%s (%s)", field + 8, str_to_str(field + 8, option242_avaya_icmpred_vals, "Unknown (%s)")); + } + else if((strncmp(field, "L2Q=", 4) == 0) && ( len > 4)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_l2q, tvb, optoff, len, field + 4, "%s (%s)", field + 4, str_to_str(field + 4, option242_avaya_l2q_vals, "Unknown (%s)")); + } + else if((strncmp(field, "L2QVLAN=", 8) == 0) && ( len > 8)) { + gint32 val = -1; + gboolean val_valid; + proto_item* pi; + + val_valid = ws_strtoi32(field + 8, NULL, &val); + pi = proto_tree_add_int(tree, hf_bootp_option242_avaya_l2qvlan, tvb, optoff, len, val); + if (val_valid) + expert_add_info(pinfo, pi, &ei_bootp_option242_avaya_l2qvlan_invalid); + } + else if((strncmp(field, "LOGLOCAL=", 9) == 0) && ( len > 9)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_loglocal, tvb, optoff, len, field + 9, "%s (%s)", field + 9, str_to_str(field + 9, option242_avaya_loglocal_vals, "Unknown (%s)")); + } + else if((strncmp(field, "PHY1STAT=", 9) == 0) && ( len > 9)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_phy1stat, tvb, optoff, len, field + 9, "%s (%s)", field + 9, str_to_str(field + 9, option242_avaya_phystat_vals, "Unknown (%s)")); + } + else if((strncmp(field, "PHY2STAT=", 9) == 0) && ( len > 9)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_phy2stat, tvb, optoff, len, field + 9, "%s (%s)", field + 9, str_to_str(field + 9, option242_avaya_phystat_vals, "Unknown (%s)")); + } + else if((strncmp(field, "PROCPSWD=", 9) == 0) && ( len > 9)) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_procpswd, tvb, optoff, len, field + 9); + } + else if((strncmp(field, "PROCSTAT=", 9) == 0) && ( len > 9)) { + proto_tree_add_string_format_value(tree, hf_bootp_option242_avaya_procstat, tvb, optoff, len, field + 9, "%s (%s)", field + 9, str_to_str(field + 9, option242_avaya_procstat_vals, "Unknown (%s)")); + } + else if((strncmp(field, "SNMPADD=", 8) == 0) && ( len > 8)) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_snmpadd, tvb, optoff, len, field + 8); + } + else if((strncmp(field, "SNMPSTRING=", 11) == 0) && ( len > 11)) { + proto_tree_add_string(tree, hf_bootp_option242_avaya_snmpstring, tvb, optoff, len, field + 11); + } + else if((strncmp(field, "VLANTEST=", 9) == 0) && ( len > 9)) { + gint32 val = -1; + gboolean val_valid; + proto_item* pi; + + val_valid = ws_strtoi32(field + 9, NULL, &val); + pi = proto_tree_add_int(tree, hf_bootp_option242_avaya_vlantest, tvb, optoff, len, val); + if (!val_valid) + expert_add_info(pinfo, pi, &ei_bootp_option242_avaya_vlantest_invalid); + } + else { + expert_add_info_format(pinfo, vti, &hf_bootp_subopt_unknown_type, "ERROR, Unknown Avaya IP Telephone parameter %s", field); + } +} + /* RFC3825Decoder: http://www.enum.at/rfc3825encoder.529.0.html */ static void rfc3825_lci_to_fixpoint(const unsigned char lci[16], struct rfc3825_location_fixpoint_t *fixpoint) @@ -3014,9 +3625,9 @@ rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct return RFC3825_LATITUDE_UNCERTAINTY_OUTOFRANGE; } if (fixpoint->latitude_res > 8 ) { - decimal->latitude_res = (double) 1 / (1 << (fixpoint->latitude_res - 8)); + decimal->latitude_res = (double) 1 / (G_GUINT64_CONSTANT(1) << (fixpoint->latitude_res - 8)); } else { - decimal->latitude_res = 1 << (8 - fixpoint->latitude_res); + decimal->latitude_res = (double) (G_GUINT64_CONSTANT(1) << (8 - fixpoint->latitude_res)); } /* Longitude */ @@ -3030,9 +3641,9 @@ rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct return RFC3825_LONGITUDE_UNCERTAINTY_OUTOFRANGE; } if (fixpoint->longitude_res > 8 ) { - decimal->longitude_res = (double) 1 / (1 << (fixpoint->longitude_res - 8)); + decimal->longitude_res = (double) 1 / (G_GUINT64_CONSTANT(1) << (fixpoint->longitude_res - 8)); } else { - decimal->longitude_res = 1 << (8 - fixpoint->longitude_res); + decimal->longitude_res = (double) (G_GUINT64_CONSTANT(1) << (8 - fixpoint->longitude_res)); } /* Altitude Type */ @@ -3052,9 +3663,9 @@ rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct return RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE; } if (fixpoint->altitude_res > 21 ) { - decimal->altitude_res = (double) 1 / (1 << (fixpoint->altitude_res - 21)); + decimal->altitude_res = (double) 1 / (G_GUINT64_CONSTANT(1) << (fixpoint->altitude_res - 21)); } else { - decimal->altitude_res = 1 << (21 - fixpoint->altitude_res); + decimal->altitude_res = (double) (G_GUINT64_CONSTANT(1) << (21 - fixpoint->altitude_res)); } } else if (decimal->altitude_type == 2) { /* Floors */ /* Altitude */ @@ -3076,6 +3687,122 @@ rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct return RFC3825_NOERROR; } +static int +dissect_bootpopt_isns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + static const int *isns_functions_hf_flags[] = { + &hf_bootp_option_isns_functions_enabled, + &hf_bootp_option_isns_functions_dd_authorization, + &hf_bootp_option_isns_functions_sec_policy_distibution, + &hf_bootp_option_isns_functions_reserved, + NULL + }; + + static const int *isns_dda_hf_flags[] = { + &hf_bootp_option_isns_discovery_domain_access_enabled, + &hf_bootp_option_isns_discovery_domain_access_control_node, + &hf_bootp_option_isns_discovery_domain_access_iscsi_target, + &hf_bootp_option_isns_discovery_domain_access_iscsi_inititator, + &hf_bootp_option_isns_discovery_domain_access_ifcp_target_port, + &hf_bootp_option_isns_discovery_domain_access_ifcp_initiator_port, + &hf_bootp_option_isns_discovery_domain_access_reserved, + NULL + }; + + static const int *isns_administrative_flags[] = { + &hf_bootp_option_isns_administrative_flags_enabled, + &hf_bootp_option_isns_administrative_flags_heartbeat, + &hf_bootp_option_isns_administrative_flags_management_scns, + &hf_bootp_option_isns_administrative_flags_default_dd, + &hf_bootp_option_isns_administrative_flags_reserved, + NULL + }; + + static const int *isns_server_security_flags[] = { + &hf_bootp_option_isns_server_security_bitmap_enabled, + &hf_bootp_option_isns_server_security_bitmap_ike_ipsec_enabled, + &hf_bootp_option_isns_server_security_bitmap_main_mode, + &hf_bootp_option_isns_server_security_bitmap_aggressive_mode, + &hf_bootp_option_isns_server_security_bitmap_pfs, + &hf_bootp_option_isns_server_security_bitmap_transport_mode, + &hf_bootp_option_isns_server_security_bitmap_tunnel_mode, + &hf_bootp_option_isns_server_security_bitmap_reserved, + NULL + }; + + guint16 function_flags, dd_access_flags, administrative_flags; + guint32 server_security_flags; + proto_tree *server_tree; + proto_item *item; + int length = tvb_reported_length(tvb); + int offset = 0, heartbeat_set = 0; + + if (length < 14) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be >= 14"); + return 1; + } + + item = proto_tree_add_bitmask(tree, tvb, offset, hf_bootp_option_isns_functions, + ett_bootp_isns_functions, isns_functions_hf_flags, ENC_BIG_ENDIAN); + function_flags = tvb_get_ntohs(tvb, offset); + /* RFC 4174, section "2.1. iSNS Functions Field" specifies that if + * the field "Function Fields Enabled" is set to 0, then "the contents + * of all other iSNS Function fields MUST be ignored. We will display + * the fields but add an informational expert info. This goes for all + * the bitmasks: iSNS Functions, DD Access, Administrative Flags, iSNS + * Server Security Bitmap */ + if (ISNS_BITFIELD_NZ_MUST_BE_IGNORED(function_flags, F_ISNS_FUNCTIONS_ENABLED)) + expert_add_info(pinfo, item, &ei_bootp_option_isns_ignored_bitfield); + + offset += 2; + item = proto_tree_add_bitmask(tree, tvb, offset, hf_bootp_option_isns_discovery_domain_access, + ett_bootp_isns_discovery_domain_access, isns_dda_hf_flags, ENC_BIG_ENDIAN); + dd_access_flags = tvb_get_ntohs(tvb, offset); + if (ISNS_BITFIELD_NZ_MUST_BE_IGNORED(dd_access_flags, F_ISNS_DD_ACCESS_ENABLED)) + expert_add_info(pinfo, item, &ei_bootp_option_isns_ignored_bitfield); + + offset += 2; + administrative_flags = tvb_get_ntohs(tvb, offset); + if (administrative_flags & F_ISNS_ADMIN_FLAGS_ENABLED) { + if ((administrative_flags & F_ISNS_ADMIN_FLAGS_HEARTBEAT)) { + if (length < 18) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length must be >= 18"); + return offset; + } + heartbeat_set = 1; + } + } + item = proto_tree_add_bitmask(tree, tvb, offset, hf_bootp_option_isns_administrative_flags, + ett_bootp_isns_administrative_flags, isns_administrative_flags, ENC_BIG_ENDIAN); + if (ISNS_BITFIELD_NZ_MUST_BE_IGNORED(administrative_flags, F_ISNS_ADMIN_FLAGS_ENABLED)) + expert_add_info(pinfo, item, &ei_bootp_option_isns_ignored_bitfield); + + offset += 2; + item = proto_tree_add_bitmask(tree, tvb, offset, hf_bootp_option_isns_server_security_bitmap, + ett_bootp_isns_server_security_bitmap, isns_server_security_flags, ENC_BIG_ENDIAN); + server_security_flags = tvb_get_ntohl(tvb, offset); + if (ISNS_BITFIELD_NZ_MUST_BE_IGNORED(server_security_flags, F_ISNS_SRV_SEC_BITMAP_ENABLED)) + expert_add_info(pinfo, item, &ei_bootp_option_isns_ignored_bitfield); + + offset += 4; + if (heartbeat_set) { + proto_tree_add_item(tree, hf_bootp_option_isns_heartbeat_originator_addr, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + } + + proto_tree_add_item(tree, hf_bootp_option_isns_primary_server_addr, tvb, offset, 4, ENC_BIG_ENDIAN); + + offset += 4; + if (tvb_reported_length_remaining(tvb, offset) > 0) { + server_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bootp_isns_secondary_server_addr, + &item, "Secondary iSNS Servers"); + bootp_handle_basic_types(pinfo, server_tree, item, tvb, ipv4_list, offset, tvb_reported_length_remaining(tvb, offset), + &hf_bootp_option_isns_secondary_server_addr_list, NULL); + } + + return tvb_captured_length(tvb); +} + static const value_string option43_cl_suboption_vals[] = { { 0, "Padding" }, { 1, "Suboption Request List" }, @@ -3114,9 +3841,9 @@ static int dissect_vendor_cablelabs_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend) { - int suboptoff = optoff; - guint8 subopt; - guint8 subopt_len; + int suboptoff = optoff; + guint8 subopt; + guint8 subopt_len; proto_tree *o43cl_v_tree; proto_item *vti; @@ -3275,6 +4002,323 @@ dissect_vendor_cablelabs_suboption(packet_info *pinfo, proto_item *v_ti, proto_t return optoff; } +static gboolean +dissect_cablelabs_vendor_info_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + int offset = 0; + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + proto_tree* vendor_tree; + + if ((option_data->vendor_class_id != NULL) && + ((strncmp((const gchar*)option_data->vendor_class_id, "pktc", strlen("pktc")) == 0) || + (strncmp((const gchar*)option_data->vendor_class_id, "docsis", strlen("docsis")) == 0) || + (strncmp((const gchar*)option_data->vendor_class_id, "OpenCable2.0", strlen("OpenCable2.0")) == 0) || + (strncmp((const gchar*)option_data->vendor_class_id, "CableHome", strlen("CableHome")) == 0))) { + /* CableLabs standard - see www.cablelabs.com/projects */ + proto_item_append_text(tree, " (CableLabs)"); + vendor_tree = proto_item_add_subtree(tree, ett_bootp_option); + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + offset = dissect_vendor_cablelabs_suboption(pinfo, tree, vendor_tree, + tvb, offset, tvb_reported_length(tvb)); + } + return TRUE; + } + + return FALSE; +} + +static gboolean +dissect_aruba_ap_vendor_info_heur( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data) +{ + int offset = 0; + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + proto_tree* vendor_tree; + + if ((option_data->vendor_class_id == NULL) || + (strncmp((const gchar*)option_data->vendor_class_id, ARUBA_AP, strlen(ARUBA_AP)) != 0)) + return FALSE; + + proto_item_append_text(tree, " (Aruba AP)"); + vendor_tree = proto_item_add_subtree(tree, ett_bootp_option); + + proto_tree_add_item(vendor_tree, hf_bootp_option43_arubaap_controllerip, tvb, offset, tvb_reported_length(tvb), ENC_ASCII|ENC_NA); + return TRUE; +} + +static gboolean +dissect_aruba_instant_ap_vendor_info_heur( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data) +{ + int offset = 0; + int reported_len = tvb_reported_length(tvb); + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + proto_tree* vendor_tree; + proto_item* vendor_item; + gint32 nameorglen, ampiplen; + + /* Aruba Instant AP */ + if ((option_data->vendor_class_id == NULL) || + (strncmp((const gchar*)option_data->vendor_class_id, ARUBA_INSTANT_AP, strlen(ARUBA_INSTANT_AP)) != 0)) + return FALSE; + + proto_item_append_text(tree, " (Aruba Instant AP)"); + + vendor_item = proto_tree_add_item(tree, hf_bootp_option43_arubaiap, tvb, offset, reported_len, ENC_ASCII|ENC_NA); + vendor_tree = proto_item_add_subtree(vendor_item, ett_bootp_option43_suboption); + nameorglen = tvb_find_guint8(tvb, offset, tvb_reported_length(tvb), ','); + proto_tree_add_item(vendor_tree, hf_bootp_option43_arubaiap_nameorg, tvb, offset, nameorglen, ENC_ASCII|ENC_NA); + offset += (nameorglen+1); + ampiplen = tvb_find_guint8(tvb, offset, reported_len-nameorglen-1, ',') - offset; + proto_tree_add_item(vendor_tree, hf_bootp_option43_arubaiap_ampip, tvb, offset, ampiplen, ENC_ASCII|ENC_NA); + offset += (ampiplen+1); + proto_tree_add_item(vendor_tree, hf_bootp_option43_arubaiap_password, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA); + + return TRUE; +} + +static const value_string option43_bsdp_suboption_vals[] = { + { 1, "Message Type" }, + { 2, "Version" }, + { 3, "Server Identifier" }, + { 4, "Server Priority" }, + { 5, "Reply Port" }, + { 6, "Boot Image List Path" }, + { 7, "Default Boot Image" }, + { 8, "Selected Boot Image" }, + { 9, "Boot Image List" }, + { 10, "NetBoot 1.0 Firmware" }, + { 11, "Boot Image Attributes Filter List" }, + { 12, "Maximum Message Size" }, + { 0, NULL} +}; + +static void +dissect_vendor_bsdp_boot_image(proto_tree *v_tree, tvbuff_t *tvb, int optoff) +{ + static const int * bootp_o43_bsdp_attributes_flags[] = { + &hf_bootp_option43_bsdp_boot_image_attribute_install, + &hf_bootp_option43_bsdp_boot_image_attribute_kind, + &hf_bootp_option43_bsdp_boot_image_attribute_reserved, + NULL + }; + + proto_tree_add_bitmask(v_tree, tvb, optoff, hf_bootp_option43_bsdp_boot_image_attribute, ett_bootp_o43_bsdp_attributes_flags, bootp_o43_bsdp_attributes_flags, ENC_NA); +} + +static int +dissect_vendor_bsdp_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, + tvbuff_t *tvb, int optoff, int optend) +{ + int suboptoff = optoff; + int attributes_off; + guint8 subopt, string_len; + guint8 subopt_len, attributes_len; + proto_tree *o43bsdp_v_tree, *o43bsdp_va_tree, *o43bsdp_vb_tree, *o43bsdp_vc_tree, *o43bsdp_vd_tree; + proto_item *vti, *ti, *tj; + + subopt = tvb_get_guint8(tvb, optoff); + suboptoff++; + + if (suboptoff >= optend) { + expert_add_info_format(pinfo, v_ti, &ei_bootp_missing_subopt_length, + "Suboption %d: no room left in option for suboption length", subopt); + return (optend); + } + + subopt_len = tvb_get_guint8(tvb, suboptoff); + vti = proto_tree_add_uint_format_value(v_tree, hf_bootp_option43_bsdp_suboption, + tvb, optoff, subopt_len+2, subopt, "(%d) %s", + subopt, val_to_str_const(subopt, option43_bsdp_suboption_vals, "Unknown")); + + o43bsdp_v_tree = proto_item_add_subtree(vti, ett_bootp_option43_suboption); + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_suboption_length, tvb, suboptoff, 1, ENC_BIG_ENDIAN); + suboptoff++; + + if (suboptoff+subopt_len > optend) { + expert_add_info_format(pinfo, vti, &ei_bootp_missing_subopt_value, + "Suboption %d: no room left in option for suboption value", subopt); + return (optend); + } + + switch(subopt) + { + case 1: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_message_type, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA); + break; + case 2: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_version, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN); + break; + case 3: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_server_identifier, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN); + break; + case 4: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_server_priority, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN); + break; + case 5: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_reply_port, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN); + break; + case 6: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_boot_image_list_path, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA); + break; + case 7: + ti = proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_default_boot_image_id, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN|ENC_NA); + o43bsdp_va_tree = proto_item_add_subtree(ti, ett_bootp_o43_bsdp_boot_image); + dissect_vendor_bsdp_boot_image(o43bsdp_va_tree, tvb, suboptoff); + proto_tree_add_item(o43bsdp_va_tree, hf_bootp_option43_bsdp_boot_image_index, tvb, suboptoff+2, subopt_len-2, ENC_BIG_ENDIAN|ENC_NA); + break; + case 8: + ti = proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_selected_boot_image_id, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN|ENC_NA); + o43bsdp_vc_tree = proto_item_add_subtree(ti, ett_bootp_o43_bsdp_boot_image); + dissect_vendor_bsdp_boot_image(o43bsdp_vc_tree, tvb, suboptoff); + proto_tree_add_item(o43bsdp_vc_tree, hf_bootp_option43_bsdp_boot_image_index, tvb, suboptoff+2, subopt_len-2, ENC_BIG_ENDIAN|ENC_NA); + break; + case 9: + ti = proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_boot_image_list, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN|ENC_NA); + attributes_len = subopt_len; + attributes_off = suboptoff; + o43bsdp_vd_tree = proto_item_add_subtree(ti, ett_bootp_o43_bsdp_image_desc_list); + while (attributes_len >= 5) { + string_len = tvb_get_guint8(tvb, attributes_off+4); + if (string_len > 0) { + tj = proto_tree_add_item(o43bsdp_vd_tree, hf_bootp_option43_bsdp_image_desc, tvb, attributes_off, string_len+5, ENC_BIG_ENDIAN|ENC_NA); + o43bsdp_vb_tree = proto_item_add_subtree(tj, ett_bootp_o43_bsdp_image_desc); + dissect_vendor_bsdp_boot_image(o43bsdp_vb_tree, tvb, attributes_off); + proto_tree_add_item(o43bsdp_vb_tree, hf_bootp_option43_bsdp_boot_image_index, tvb, attributes_off+2, 2, ENC_BIG_ENDIAN|ENC_NA); + proto_tree_add_item(o43bsdp_vb_tree, hf_bootp_option43_bsdp_boot_image_name_len, tvb, attributes_off+4, 1, ENC_BIG_ENDIAN|ENC_NA); + proto_tree_add_item(o43bsdp_vb_tree, hf_bootp_option43_bsdp_boot_image_name, tvb, attributes_off+5, string_len, ENC_UTF_8|ENC_NA); + } + attributes_off += 5 + string_len; + attributes_len -= 5 + string_len; + } + break; + case 10: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_netboot_firmware, tvb, suboptoff, subopt_len, ENC_NA); + break; + case 11: + ti = proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_attributes_filter_list, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN|ENC_NA); + attributes_len = subopt_len; + attributes_off = suboptoff; + o43bsdp_va_tree = proto_item_add_subtree(ti, ett_bootp_o43_bsdp_attributes); + while (attributes_len >= 2) { + dissect_vendor_bsdp_boot_image(o43bsdp_va_tree, tvb, attributes_off); + attributes_off+=2; + attributes_len-=2; + } + break; + case 12: + proto_tree_add_item(o43bsdp_v_tree, hf_bootp_option43_bsdp_message_size, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN|ENC_NA); + break; + } + + optoff += (subopt_len + 2); + return optoff; +} + +static gboolean +dissect_packetcable_bsdpd_vendor_info_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + int offset = 0; + bootp_option_data_t *option_data = (bootp_option_data_t*)data; + proto_tree* vendor_tree; + + if ((option_data->vendor_class_id == NULL) || + (strncmp((const gchar*)option_data->vendor_class_id, PACKETCABLE_BSDP, strlen(PACKETCABLE_BSDP)) != 0)) + return FALSE; + + /* Apple BSDP */ + proto_item_append_text(tree, " (Boot Server Discovery Protocol (BSDP))"); + vendor_tree = proto_item_add_subtree(tree, ett_bootp_option); + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + offset = dissect_vendor_bsdp_suboption(pinfo, tree, vendor_tree, + tvb, offset, tvb_reported_length(tvb)); + } + + return TRUE; +} + + +static int +dissect_vendor_generic_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, + tvbuff_t *tvb, int optoff, int optend) +{ + int suboptoff = optoff; + guint8 subopt; + int subopt_len; + proto_item *item; + proto_tree *sub_tree; + + item = proto_tree_add_item(v_tree, hf_bootp_vendor_unknown_suboption, tvb, optoff, 1, ENC_NA); + subopt = tvb_get_guint8(tvb, optoff); + + suboptoff+=1; + + if (suboptoff >= optend) { + expert_add_info_format(pinfo, v_ti, &ei_bootp_missing_subopt_length, + "Suboption %d: no room left in option for suboption length", subopt); + return (optend); + } + + sub_tree = proto_item_add_subtree(item, ett_bootp_option125_suboption); + proto_tree_add_item_ret_uint(sub_tree, hf_bootp_suboption_length, tvb, suboptoff, 1, ENC_NA, &subopt_len); + suboptoff++; + + if (suboptoff+subopt_len > optend) { + expert_add_info_format(pinfo, item, &ei_bootp_missing_subopt_value, + "Suboption %d: no room left in option for suboption value", subopt); + return (optend); + } + + proto_tree_add_item(sub_tree, hf_bootp_suboption_data, tvb, suboptoff, subopt_len, ENC_NA); + suboptoff+= subopt_len; + + return suboptoff; + +} + +static int +dissect_bootpopt_vi_vendor_specific_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + int enterprise = 0; + int s_end = 0; + int option_data_len = 0; + proto_item *vti; + proto_tree *e_tree; + + while (tvb_reported_length_remaining(tvb, offset) >= 5) { + + vti = proto_tree_add_item_ret_uint(tree, hf_bootp_option125_enterprise, tvb, offset, 4, ENC_BIG_ENDIAN, &enterprise); + e_tree = proto_item_add_subtree(vti, ett_bootp_option); + offset += 4; + + proto_tree_add_item_ret_uint(e_tree, hf_bootp_option125_length, tvb, offset, 1, ENC_NA, &option_data_len); + offset += 1; + + s_end = offset + option_data_len; + if ( tvb_reported_length_remaining(tvb, s_end) < 0 ) { + expert_add_info_format(pinfo, vti, &ei_bootp_option125_enterprise_malformed, "no room left in option for enterprise %u data", enterprise); + break; + } + + while (offset < s_end) { + tvbuff_t *enterprise_tvb = tvb_new_subset_length(tvb, offset, option_data_len); + int bytes_dissected = dissector_try_uint(bootp_enterprise_table, enterprise, enterprise_tvb, pinfo, e_tree); + if (bytes_dissected == 0) { + offset = dissect_vendor_generic_suboption(pinfo, vti, e_tree, tvb, offset, s_end); + } else{ + offset += bytes_dissected; + } + } + } + + if (tvb_reported_length_remaining(tvb, offset) > 0) { + expert_add_info_format(pinfo, tree, &ei_bootp_bad_length, "length < 5"); + } + + return tvb_captured_length(tvb); +} + static const value_string option43_alcatel_suboption_vals[] = { { 0, "Padding" }, { 58, "Voice VLAN ID" }, @@ -3292,13 +4336,45 @@ static const value_string option43_alcatel_app_type_vals[] = { { 0, NULL} }; +/* Look for 'encapsulated vendor-specific options' */ +static gboolean +test_encapsulated_vendor_options(tvbuff_t *tvb, int optoff, int optend) +{ + guint8 subopt; + guint8 subopt_len; + + while (optoff < optend) { + subopt = tvb_get_guint8(tvb, optoff); + optoff++; + + /* Skip padding */ + if (subopt == 0) + continue; + /* We are done, skip any remaining bytes */ + if (subopt == 255) + break; + + /* We expect a length byte next */ + if (optoff >= optend) + return FALSE; + subopt_len = tvb_get_guint8(tvb, optoff); + optoff++; + + /* Check remaining room for suboption in option */ + if (optoff + subopt_len > optend) + return FALSE; + optoff += subopt_len; + } + return TRUE; +} + static int dissect_vendor_alcatel_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend) { - int suboptoff = optoff; - guint8 subopt; - guint8 subopt_len; + int suboptoff = optoff; + guint8 subopt; + guint8 subopt_len; proto_item *vti; proto_tree *o43alcatel_v_tree; @@ -3380,6 +4456,35 @@ dissect_vendor_alcatel_suboption(packet_info *pinfo, proto_item *v_ti, proto_tre return optoff; } +static gboolean +dissect_alcatel_lucent_vendor_info_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + int offset = 0; + guint8 s_option; + proto_tree* vendor_tree; + + if (tvb_reported_length(tvb) < 1) + return FALSE; + + s_option = tvb_get_guint8(tvb, offset); + if ((s_option==58 || s_option==64 || s_option==65 + || s_option==66 || s_option==67) + && test_encapsulated_vendor_options(tvb, offset, tvb_reported_length(tvb))) { + + /* Alcatel-Lucent DHCP Extensions */ + proto_item_append_text(tree, " (Alcatel-Lucent)"); + vendor_tree = proto_item_add_subtree(tree, ett_bootp_option); + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + offset = dissect_vendor_alcatel_suboption(pinfo, tree, vendor_tree, + tvb, offset, tvb_reported_length(tvb)); + } + return TRUE; + } + + return FALSE; +} + static const value_string option63_suboption_vals[] = { { 1, "NWIP does not exist on subnet" }, { 2, "NWIP exists in options area" }, @@ -3399,8 +4504,8 @@ static int dissect_netware_ip_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend) { - int suboptoff = optoff; - guint8 subopt, subopt_len; + int suboptoff = optoff; + guint8 subopt, subopt_len; proto_tree *o63_v_tree; proto_item *vti, *ti; @@ -3475,6 +4580,18 @@ dissect_netware_ip_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v return optoff; } +static int +dissect_bootpopt_netware_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + offset = dissect_netware_ip_suboption(pinfo, tree, tree, tvb, offset, tvb_reported_length(tvb)); + } + + return tvb_captured_length(tvb); +} + static const value_string option125_tr111_suboption_vals[] = { { 1, "DeviceManufacturerOUI" }, { 2, "DeviceSerialNumber" }, @@ -3486,13 +4603,12 @@ static const value_string option125_tr111_suboption_vals[] = { }; static int -dissect_vendor_tr111_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend) +dissect_vendor_tr111_suboption(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - int suboptoff = optoff; + int offset = 0; proto_tree *o125_v_tree; proto_item *vti, *ti; - guint8 subopt, subopt_len; + guint8 subopt, subopt_len; struct basic_types_hfs default_hfs = { NULL, @@ -3514,56 +4630,62 @@ dissect_vendor_tr111_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree static struct opt_info o125_tr111_opt[]= { /* 0 */ {"nop", special, NULL}, /* dummy */ - /* 1 */ {"DeviceManufacturerOUI", string, &hf_bootp_option125_tr111_device_manufacturer_oui}, - /* 2 */ {"DeviceSerialNumber", string, &hf_bootp_option125_tr111_device_serial_number}, - /* 3 */ {"DeviceProductClass", string, &hf_bootp_option125_tr111_device_product_class}, + /* 1 */ {"DeviceManufacturerOUI", oui, &hf_bootp_option125_tr111_device_manufacturer_oui}, + /* 2 */ {"DeviceSerialNumber", string, &hf_bootp_option125_tr111_device_serial_number}, + /* 3 */ {"DeviceProductClass", string, &hf_bootp_option125_tr111_device_product_class}, /* 4 */ {"GatewayManufacturerOUI", string, &hf_bootp_option125_tr111_gateway_manufacturer_oui}, - /* 5 */ {"GatewaySerialNumber", string, &hf_bootp_option125_tr111_gateway_serial_number}, - /* 6 */ {"GatewayProductClass", string, &hf_bootp_option125_tr111_gateway_product_class}, + /* 5 */ {"GatewaySerialNumber", string, &hf_bootp_option125_tr111_gateway_serial_number}, + /* 6 */ {"GatewayProductClass", string, &hf_bootp_option125_tr111_gateway_product_class}, }; - subopt = tvb_get_guint8(tvb, optoff); - suboptoff++; + subopt = tvb_get_guint8(tvb, offset); + offset++; - if (suboptoff >= optend) { - expert_add_info_format(pinfo, v_ti, &ei_bootp_missing_subopt_length, - "Suboption %d: no room left in option for suboption length", subopt); - return (optend); + if (tvb_reported_length_remaining(tvb, offset) < 1) { + expert_add_info_format(pinfo, tree, &ei_bootp_missing_subopt_length, + "Suboption %d: no room left in option for suboption length", subopt); + return offset; } - subopt_len = tvb_get_guint8(tvb, suboptoff); - vti = proto_tree_add_uint_format_value(v_tree, hf_bootp_option125_tr111_suboption, - tvb, optoff, subopt_len+2, subopt, "(%d) %s", + subopt_len = tvb_get_guint8(tvb, offset); + vti = proto_tree_add_uint_format_value(tree, hf_bootp_option125_tr111_suboption, + tvb, offset, subopt_len+2, subopt, "(%d) %s", subopt, val_to_str_const(subopt, option125_tr111_suboption_vals, "Unknown")); - o125_v_tree = proto_item_add_subtree(vti, hf_bootp_option125_tr111_suboption); - proto_tree_add_item(o125_v_tree, hf_bootp_suboption_length, tvb, suboptoff, 1, ENC_BIG_ENDIAN); - suboptoff++; + o125_v_tree = proto_item_add_subtree(vti, ett_bootp_option125_tr111_suboption); + proto_tree_add_item(o125_v_tree, hf_bootp_suboption_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; - if (suboptoff+subopt_len > optend) { + if (tvb_reported_length_remaining(tvb, offset) < subopt_len) { expert_add_info_format(pinfo, vti, &ei_bootp_missing_subopt_value, "Suboption %d: no room left in option for suboption value", subopt); - return (optend); + return offset; } - ti = proto_tree_add_item(v_tree, hf_bootp_option125_value, tvb, suboptoff, subopt_len, ENC_NA); + ti = proto_tree_add_item(tree, hf_bootp_option125_value, tvb, offset, subopt_len, ENC_NA); PROTO_ITEM_SET_HIDDEN(ti); if (subopt < array_length(o125_tr111_opt)) { - if (bootp_handle_basic_types(pinfo, o125_v_tree, vti, tvb, o125_tr111_opt[subopt].ftype, - suboptoff, subopt_len, o125_tr111_opt[subopt].phf, &default_hfs) == 0) { + if (bootp_handle_basic_types(pinfo, o125_v_tree, vti, tvb, o125_tr111_opt[subopt].ftype, offset, subopt_len, o125_tr111_opt[subopt].phf, &default_hfs) == 0) { if (o125_tr111_opt[subopt].ftype == special) { if (o125_tr111_opt[subopt].phf != NULL) - proto_tree_add_item(v_tree, *o125_tr111_opt[subopt].phf, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN); + proto_tree_add_item(o125_v_tree, *o125_tr111_opt[subopt].phf, tvb, offset, subopt_len, ENC_BIG_ENDIAN); else - proto_tree_add_item(v_tree, hf_bootp_option125_value, tvb, suboptoff, subopt_len, ENC_NA); + proto_tree_add_item(o125_v_tree, hf_bootp_option125_value, tvb, offset, subopt_len, ENC_NA); + } + else if (o125_tr111_opt[subopt].ftype == oui) { + /* Get hex string. Expecting 6 characters. */ + gchar *oui_string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, subopt_len, ENC_ASCII); + /* Convert to OUI number. Only 3 bytes so no data lost in downcast. */ + guint32 oui_number = (guint32)strtol(oui_string, NULL, 16); + /* Add item using oui_vals */ + proto_tree_add_uint(o125_v_tree, *o125_tr111_opt[subopt].phf, tvb, offset, subopt_len, oui_number); } else if (o125_tr111_opt[subopt].phf == NULL) - proto_tree_add_item(v_tree, hf_bootp_option125_value, tvb, suboptoff, subopt_len, ENC_NA); + proto_tree_add_item(o125_v_tree, hf_bootp_option125_value, tvb, offset, subopt_len, ENC_NA); } } - optoff += (subopt_len + 2); - return optoff; + return subopt_len + 2; } static const value_string option125_cl_suboption_vals[] = { @@ -3584,11 +4706,10 @@ static const value_string pkt_mib_env_ind_opt_vals[] = { }; static int -dissect_vendor_cl_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, - tvbuff_t *tvb, int optoff, int optend) +dissect_vendor_cl_suboption(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - int suboptoff = optoff; - guint8 subopt, subopt_len; + int offset = 0; + guint8 subopt, subopt_len; proto_tree *o125_v_tree; proto_item *vti; @@ -3608,60 +4729,62 @@ dissect_vendor_cl_suboption(packet_info *pinfo, proto_item *v_ti, proto_tree *v_ static struct opt_info o125_cl_opt[]= { /* 0 */ {"nop", special, NULL}, /* dummy */ - /* 1 */ {"Option Request = ", val_u_byte, &hf_bootp_option125_cl_option_request}, + /* 1 */ {"Option Request = ", bytes, &hf_bootp_option125_cl_option_request}, /* 2 */ {"TFTP Server Addresses : ", ipv4_list, &hf_bootp_option125_cl_tftp_server_addresses}, /* 3 */ {"eRouter Container Option : ", bytes, &hf_bootp_option125_cl_erouter_container_option}, /* 4 */ {"MIB Environment Indicator Option = ", val_u_byte, &hf_bootp_option125_cl_mib_environment_indicator_option}, /* 5 */ {"Modem Capabilities : ", special, &hf_bootp_option125_cl_modem_capabilities}, }; - subopt = tvb_get_guint8(tvb, optoff); - suboptoff++; + subopt = tvb_get_guint8(tvb, offset); + offset++; - if (suboptoff >= optend) { - expert_add_info_format(pinfo, v_ti, &ei_bootp_missing_subopt_length, + if (tvb_reported_length_remaining(tvb, offset) < 1) { + expert_add_info_format(pinfo, tree, &ei_bootp_missing_subopt_length, "Suboption %d: no room left in option for suboption length", subopt); - return (optend); + return offset; } - subopt_len = tvb_get_guint8(tvb, suboptoff); - vti = proto_tree_add_uint_format_value(v_tree, hf_bootp_option125_cl_suboption, - tvb, optoff, subopt_len+2, subopt, "(%d) %s", + subopt_len = tvb_get_guint8(tvb, offset); + vti = proto_tree_add_uint_format_value(tree, hf_bootp_option125_cl_suboption, + tvb, offset, subopt_len+2, subopt, "(%d) %s", subopt, val_to_str_const(subopt, option125_cl_suboption_vals, "Unknown")); - o125_v_tree = proto_item_add_subtree(vti, hf_bootp_option125_cl_suboption); - proto_tree_add_item(o125_v_tree, hf_bootp_suboption_length, tvb, suboptoff, 1, ENC_BIG_ENDIAN); - suboptoff++; + o125_v_tree = proto_item_add_subtree(vti, ett_bootp_option125_cl_suboption); + proto_tree_add_item(o125_v_tree, hf_bootp_suboption_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; - if (suboptoff+subopt_len > optend) { + if (tvb_reported_length_remaining(tvb, offset) < subopt_len) { expert_add_info_format(pinfo, vti, &ei_bootp_missing_subopt_value, "Suboption %d: no room left in option for suboption value", subopt); - return (optend); + return offset; } if (subopt < array_length(o125_cl_opt)) { if (bootp_handle_basic_types(pinfo, o125_v_tree, vti, tvb, o125_cl_opt[subopt].ftype, - suboptoff, subopt_len, o125_cl_opt[subopt].phf, &default_hfs) == 0) { + offset, subopt_len, o125_cl_opt[subopt].phf, &default_hfs) == 0) { switch(o125_cl_opt[subopt].ftype) { case special: if (o125_cl_opt[subopt].phf != NULL) - proto_tree_add_item(o125_v_tree, *o125_cl_opt[subopt].phf, tvb, suboptoff, subopt_len, ENC_BIG_ENDIAN); + proto_tree_add_item(o125_v_tree, *o125_cl_opt[subopt].phf, tvb, offset, subopt_len, ENC_BIG_ENDIAN); else - proto_tree_add_item(o125_v_tree, hf_bootp_option125_value, tvb, suboptoff, subopt_len, ENC_NA); - - dissect_docsis_cm_cap(o125_v_tree, tvb, optoff, subopt_len+2, TRUE); + proto_tree_add_item(o125_v_tree, hf_bootp_option125_value, tvb, offset, subopt_len, ENC_NA); + switch(subopt){ + case 5: /* Modem Capabilities */ + dissect_docsis_cm_cap(o125_v_tree, tvb, offset-2, subopt_len+2, TRUE); + break; + } break; default: if (o125_cl_opt[subopt].phf == NULL) - proto_tree_add_item(o125_v_tree, hf_bootp_option125_value, tvb, suboptoff, subopt_len, ENC_NA); + proto_tree_add_item(o125_v_tree, hf_bootp_option125_value, tvb, offset, subopt_len, ENC_NA); break; } } } - optoff += (subopt_len + 2); - return optoff; + return subopt_len + 2; } /* PacketCable Multimedia Terminal Adapter device capabilities (option 60). @@ -3808,74 +4931,54 @@ static const value_string pkt_mdc_mib_orgs[] = { { 0, NULL } }; -static const value_string pkt_mdc_supp_flow_vals[] = { - { 1 << 0, "Secure Flow (Full Secure Provisioning Flow)" }, - { 1 << 1, "Hybrid Flow" }, - { 1 << 2, "Basic Flow" }, - { 0, NULL } -}; +static int hf_bootp_pkt_mdc_supp_flow_secure = -1; +static int hf_bootp_pkt_mdc_supp_flow_hybrid = -1; +static int hf_bootp_pkt_mdc_supp_flow_basic = -1; #define PKT_MDC_MIB_CL 0x3030 -static const value_string pkt_mdc_cl_mib_vals[] = { - { 1 << 0, "PacketCable 1.5 MTA MIB" }, - { 1 << 1, "PacketCable 1.5 Signaling MIB" }, - { 1 << 2, "PacketCable 1.5 Management Event MIB" }, - { 1 << 3, "PacketCable 1.5 MTA Extension MIB" }, - { 1 << 4, "PacketCable 1.5 Signaling Extension MIB" }, - { 1 << 5, "PacketCable 1.5 MEM Extension MIB" }, - { 1 << 6, "Reserved" }, - { 1 << 7, "Reserved" }, - { 0, NULL } -}; +static int hf_bootp_pkt_mdc_mib_cl_mta = -1; +static int hf_bootp_pkt_mdc_mib_cl_signaling = -1; +static int hf_bootp_pkt_mdc_mib_cl_management_event = -1; +static int hf_bootp_pkt_mdc_mib_cl_mta_extension = -1; +static int hf_bootp_pkt_mdc_mib_cl_mta_signaling_extension = -1; +static int hf_bootp_pkt_mdc_mib_cl_mta_mem_extention = -1; +static int hf_bootp_pkt_mdc_mib_cl_reserved = -1; #define PKT_MDC_MIB_IETF 0x3031 -static const value_string pkt_mdc_ietf_mib_vals[] = { - { 1 << 0, "IETF MTA MIB" }, - { 1 << 1, "IETF Signaling MIB" }, - { 1 << 2, "IETF Management Event MIB" }, - { 1 << 3, "Reserved" }, - { 1 << 4, "Reserved" }, - { 1 << 5, "Reserved" }, - { 1 << 6, "Reserved" }, - { 1 << 7, "Reserved" }, - { 0, NULL } -}; +static int hf_bootp_pkt_mdc_mib_ietf_mta = -1; +static int hf_bootp_pkt_mdc_mib_ietf_signaling = -1; +static int hf_bootp_pkt_mdc_mib_ietf_management_event = -1; +static int hf_bootp_pkt_mdc_mib_ietf_reserved = -1; #define PKT_MDC_MIB_EURO 0x3032 -static const value_string pkt_mdc_euro_mib_vals[] = { - { 1 << 0, "PacketCable 1.5 MTA MIB" }, - { 1 << 1, "PacketCable 1.5 Signaling MIB" }, - { 1 << 2, "PacketCable 1.5 Management Event MIB" }, - { 1 << 3, "PacketCable 1.5 MTA Extension MIB" }, - { 1 << 4, "PacketCable 1.5 Signaling Extension MIB" }, - { 1 << 5, "PacketCable 1.5 MEM Extension MIB" }, - { 1 << 6, "Reserved" }, - { 1 << 7, "Reserved" }, - { 0, NULL } -}; +static int hf_bootp_pkt_mdc_mib_euro_mta = -1; +static int hf_bootp_pkt_mdc_mib_euro_signaling = -1; +static int hf_bootp_pkt_mdc_mib_euro_management_event = -1; +static int hf_bootp_pkt_mdc_mib_euro_mta_extension = -1; +static int hf_bootp_pkt_mdc_mib_euro_mta_signaling_extension = -1; +static int hf_bootp_pkt_mdc_mib_euro_mta_mem_extention = -1; +static int hf_bootp_pkt_mdc_mib_euro_reserved = -1; static void -dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len) +dissect_packetcable_mta_cap(proto_tree *v_tree, packet_info *pinfo, tvbuff_t *tvb, int voff, int len) { - guint16 raw_val; - unsigned long flow_val = 0; - int off = PKT_MDC_TLV_OFF + voff; - int subopt_off, max_len; - guint tlv_len, i, mib_val; - guint8 asc_val[3] = " ", flow_val_str[5]; - char bit_fld[64]; + guint16 raw_val; + guint32 flow_val = 0; + int off = PKT_MDC_TLV_OFF + voff; + int subopt_off, max_len; + guint tlv_len, i, mib_val; + guint8 asc_val[3] = " ", flow_val_str[5]; proto_item *ti, *mib_ti; proto_tree *subtree, *subtree2; tvb_memcpy (tvb, asc_val, off, 2); if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len > 0xff) { - proto_tree_add_text(v_tree, tvb, off, len - off, + proto_tree_add_expert_format(v_tree, pinfo, &ei_bootp_bad_length, tvb, off, len - off, "Bogus length: %s", asc_val); return; } else { - proto_tree_add_uint_format_value(v_tree, hf_bootp_pkt_mta_cap_len, tvb, off, 2, - tlv_len, "%d", tlv_len); + proto_tree_add_uint(v_tree, hf_bootp_pkt_mta_cap_len, tvb, off, 2, tlv_len); off += 2; while (off - voff < len) { @@ -3886,17 +4989,17 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len tvb_memcpy(tvb, asc_val, off + 2, 2); if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len < 1 || tlv_len > G_MAXUINT16) { - proto_tree_add_text(v_tree, tvb, off, len - off, - "[Bogus length: %s]", asc_val); + proto_tree_add_expert_format(v_tree, pinfo, &ei_bootp_bad_length, tvb, off, len - off, + "Bogus length: %s", asc_val); return; } else { /* Value(s) */ - ti = proto_tree_add_text(v_tree, - tvb, off, (tlv_len * 2) + 4, - "0x%s: %s = ", + ti = proto_tree_add_uint_format(v_tree, hf_bootp_pkt_mta_cap_type, + tvb, off, 2, raw_val, "0x%s: %s = ", tvb_format_text(tvb, off, 2), val_to_str_const(raw_val, pkt_mdc_type_vals, "unknown")); + proto_item_set_len(ti, (tlv_len * 2) + 4); switch (raw_val) { case PKT_MDC_VERSION: @@ -3959,9 +5062,10 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len case PKT_MDC_PROV_FLOWS: tvb_memcpy(tvb, flow_val_str, off + 4, 4); flow_val_str[4] = '\0'; - flow_val = strtoul((gchar*)flow_val_str, NULL, 16); + /* We are only reading 4 digits which should fit in 32 bits */ + flow_val = (guint32)strtoul((gchar*)flow_val_str, NULL, 16); proto_item_append_text(ti, - "0x%04lx", flow_val); + "0x%04x", flow_val); break; case PKT_MDC_T38_VERSION: @@ -3993,13 +5097,14 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len } subtree = proto_item_add_subtree(ti, ett_bootp_option); if (raw_val == PKT_MDC_PROV_FLOWS) { - for (i = 0 ; i < 3; i++) { - if (flow_val & pkt_mdc_supp_flow_vals[i].value) { - decode_bitfield_value(bit_fld, (guint32)flow_val, pkt_mdc_supp_flow_vals[i].value, 16); - proto_tree_add_text(subtree, tvb, off + 4, 4, "%s%s", - bit_fld, pkt_mdc_supp_flow_vals[i].strptr); - } - } + static const int * flows[] = { + &hf_bootp_pkt_mdc_supp_flow_secure, + &hf_bootp_pkt_mdc_supp_flow_hybrid, + &hf_bootp_pkt_mdc_supp_flow_basic, + NULL + }; + + proto_tree_add_bitmask_list_value(subtree, tvb, off + 4, 4, flows, flow_val); } else if (raw_val == PKT_MDC_MIBS) { /* 17 06 02 00 38 02 01 07 */ subopt_off = off + 4; @@ -4008,8 +5113,8 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len raw_val = tvb_get_ntohs(tvb, subopt_off); if (raw_val != 0x3032) { /* We only know how to handle a length of 2 */ tvb_memcpy(tvb, asc_val, subopt_off, 2); - proto_tree_add_text(subtree, tvb, subopt_off, 2, - "[Bogus length: %s]", asc_val); + proto_tree_add_expert_format(subtree, pinfo, &ei_bootp_bad_length, tvb, subopt_off, 2, + "Bogus length: %s", asc_val); return; } @@ -4017,7 +5122,8 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len raw_val = tvb_get_ntohs(tvb, subopt_off); tvb_memcpy(tvb, asc_val, subopt_off, 2); - mib_ti = proto_tree_add_text(subtree, tvb, subopt_off, 2, "%s (%s)", + subtree2 = proto_tree_add_subtree_format(subtree, tvb, subopt_off, 2, + ett_bootp_option, &mib_ti, "%s (%s)", val_to_str_const(raw_val, pkt_mdc_mib_orgs, "Unknown"), asc_val); if (subopt_off > off + 4 + 2) { proto_item_append_text(ti, ", "); @@ -4027,46 +5133,55 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len subopt_off += 2; tvb_memcpy(tvb, asc_val, subopt_off, 2); if (sscanf((gchar*)asc_val, "%x", &mib_val) != 1) { - proto_tree_add_text(v_tree, tvb, subopt_off, 2, - "[Bogus bitfield: %s]", asc_val); + proto_tree_add_expert_format(v_tree, pinfo, &ei_bootp_bad_bitfield, tvb, subopt_off, 2, + "Bogus bitfield: %s", asc_val); return; } switch (raw_val) { - case PKT_MDC_MIB_CL: - subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option); - - for (i = 0; i < 8; i++) { - if (mib_val & pkt_mdc_cl_mib_vals[i].value) { - decode_bitfield_value(bit_fld, mib_val, pkt_mdc_cl_mib_vals[i].value, 8); - proto_tree_add_text(subtree2, tvb, subopt_off, 2, - "%s%s", bit_fld, pkt_mdc_cl_mib_vals[i].strptr); - } - } + case PKT_MDC_MIB_CL: { + static const int * cl_flags[] = { + &hf_bootp_pkt_mdc_mib_cl_mta, + &hf_bootp_pkt_mdc_mib_cl_signaling, + &hf_bootp_pkt_mdc_mib_cl_management_event, + &hf_bootp_pkt_mdc_mib_cl_mta_extension, + &hf_bootp_pkt_mdc_mib_cl_mta_signaling_extension, + &hf_bootp_pkt_mdc_mib_cl_mta_mem_extention, + &hf_bootp_pkt_mdc_mib_cl_reserved, + NULL + }; + + proto_tree_add_bitmask_list_value(subtree2, tvb, subopt_off, 2, cl_flags, mib_val); + } break; - case PKT_MDC_MIB_IETF: - subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option); - - for (i = 0; i < 8; i++) { - if (mib_val & pkt_mdc_ietf_mib_vals[i].value) { - decode_bitfield_value(bit_fld, mib_val, pkt_mdc_ietf_mib_vals[i].value, 8); - proto_tree_add_text(subtree2, tvb, subopt_off, 2, - "%s%s", bit_fld, pkt_mdc_ietf_mib_vals[i].strptr); - } - } + case PKT_MDC_MIB_IETF: { + static const int * ietf_flags[] = { + &hf_bootp_pkt_mdc_mib_ietf_mta, + &hf_bootp_pkt_mdc_mib_ietf_signaling, + &hf_bootp_pkt_mdc_mib_ietf_management_event, + &hf_bootp_pkt_mdc_mib_ietf_reserved, + NULL + }; + + proto_tree_add_bitmask_list_value(subtree2, tvb, subopt_off, 2, ietf_flags, mib_val); + } break; - case PKT_MDC_MIB_EURO: - subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option); - - for (i = 0; i < 8; i++) { - if (mib_val & pkt_mdc_euro_mib_vals[i].value) { - decode_bitfield_value(bit_fld, mib_val, pkt_mdc_euro_mib_vals[i].value, 8); - proto_tree_add_text(subtree2, tvb, subopt_off, 2, - "%s%s", bit_fld, pkt_mdc_euro_mib_vals[i].strptr); - } - } + case PKT_MDC_MIB_EURO: { + static const int * euro_flags[] = { + &hf_bootp_pkt_mdc_mib_euro_mta, + &hf_bootp_pkt_mdc_mib_euro_signaling, + &hf_bootp_pkt_mdc_mib_euro_management_event, + &hf_bootp_pkt_mdc_mib_euro_mta_extension, + &hf_bootp_pkt_mdc_mib_euro_mta_signaling_extension, + &hf_bootp_pkt_mdc_mib_euro_mta_mem_extention, + &hf_bootp_pkt_mdc_mib_euro_reserved, + NULL + }; + + proto_tree_add_bitmask_list_value(subtree2, tvb, subopt_off, 2, euro_flags, mib_val); + } break; default: @@ -4081,6 +5196,26 @@ dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len } } +static gboolean +dissect_packetcable_mta_vendor_id_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ ) +{ + guint8* vendor_id; + + if (tvb_reported_length(tvb) < 8) { + return FALSE; + } + + vendor_id = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, 8, ENC_ASCII|ENC_NA); + if ((strcmp((const char*)vendor_id, PACKETCABLE_MTA_CAP10) == 0) || + (strcmp((const char*)vendor_id, PACKETCABLE_MTA_CAP15) == 0) || + (strcmp((const char*)vendor_id, PACKETCABLE_MTA_CAP20) == 0)) { + dissect_packetcable_mta_cap(tree, pinfo, tvb, 0, tvb_reported_length(tvb)); + return TRUE; + } + + return FALSE; +} + /* DOCSIS Cable Modem device capabilities (option 60/option 125). */ #define DOCSIS_CM_CAP_TLV_OFF 12 @@ -4170,8 +5305,8 @@ static const value_string docsis_cm_cap_type_vals[] = { { DOCSIS_CM_CAP_IPV6_SUP, "IPv6 Support" }, { DOCSIS_CM_CAP_ExUsTrPow, "Extended Upstream Transmit Power Capability (1/4 dB)" }, { DOCSIS_CM_CAP_Opt802MPLSSup, "Optional 802.1ad, 802.1ah, MPLS Classification Support" }, - { DOCSIS_CM_CAP_DounEnc, "D-ONU Capabilities Encoding" }, - { DOCSIS_CM_CAP_EnrgMang, "Energy Management Capabilities" }, + { DOCSIS_CM_CAP_DounEnc, "D-ONU Capabilities Encoding" }, + { DOCSIS_CM_CAP_EnrgMang, "Energy Management Capabilities" }, { 0, NULL } }; @@ -4195,13 +5330,10 @@ static const value_string docsis_cm_cap_privacy_vals[] = { { 0, NULL } }; -static const value_string docsis_cm_cap_ranging_hold_off_vals[] = { - { 1 << 0, "CM" }, - { 1 << 1, "ePS or eRouter" }, - { 1 << 2, "EMTA or EDVA" }, - { 1 << 3, "DSG/eSTB" }, - { 0, NULL } -}; +static int hf_bootp_docsis_cm_cap_ranging_hold_off_cm = -1; +static int hf_bootp_docsis_cm_cap_ranging_hold_off_eps = -1; +static int hf_bootp_docsis_cm_cap_ranging_hold_off_emta = -1; +static int hf_bootp_docsis_cm_cap_ranging_hold_off_dsg = -1; static const value_string docsis_cm_cap_l2vpn_vals[] = { { 0x00, "CM not compliant with DOCSIS L2VPN Section 7 (default)" }, @@ -4215,34 +5347,31 @@ static const value_string docsis_cm_cap_filt_vals[] = { { 0, NULL } }; -static const value_string docsis_cm_cap_mpls_vals[] = { - { 1 << 0, "[IEEE 802.1ad] S-TPID" }, - { 1 << 1, "[IEEE 802.1ad] S-VID" }, - { 1 << 2, "[IEEE 802.1ad] S-PCP" }, - { 1 << 3, "[IEEE 802.1ad] S-DEI" }, - { 1 << 4, "[IEEE 802.1ad] C-TPID" }, - { 1 << 5, "[IEEE 802.1ad] C-VID" }, - { 1 << 6, "[IEEE 802.1ad] C-PCP" }, - { 1 << 7, "[IEEE 802.1ad] C-CFI" }, - { 1 << 8, "[IEEE 802.1ad] S-TCI" }, - { 1 << 9, "[IEEE 802.1ad] C-TCI" }, - { 1 << 10, "[IEEE 802.1ah] I-TPID" }, - { 1 << 11, "[IEEE 802.1ah] I-SID" }, - { 1 << 12, "[IEEE 802.1ah] I-TCI" }, - { 1 << 13, "[IEEE 802.1ah] I-PCP" }, - { 1 << 14, "[IEEE 802.1ah] I-DEI" }, - { 1 << 15, "[IEEE 802.1ah] I-UCA" }, - { 1 << 16, "[IEEE 802.1ah] B-TPID" }, - { 1 << 17, "[IEEE 802.1ah] B-TCI" }, - { 1 << 18, "[IEEE 802.1ah] B-PCP" }, - { 1 << 19, "[IEEE 802.1ah] B-DEI" }, - { 1 << 20, "[IEEE 802.1ah] B-VID" }, - { 1 << 21, "[IEEE 802.1ah] B-DA" }, - { 1 << 22, "[IEEE 802.1ah] B-SA" }, - { 1 << 23, "MPLS TC" }, - { 1 << 24, "MPLS Label" }, - { 0, NULL } -}; +static int hf_bootp_docsis_cm_cap_mpls_stpid = -1; +static int hf_bootp_docsis_cm_cap_mpls_svid = -1; +static int hf_bootp_docsis_cm_cap_mpls_spcp = -1; +static int hf_bootp_docsis_cm_cap_mpls_sdei = -1; +static int hf_bootp_docsis_cm_cap_mpls_ctpid = -1; +static int hf_bootp_docsis_cm_cap_mpls_cvid = -1; +static int hf_bootp_docsis_cm_cap_mpls_cpcp = -1; +static int hf_bootp_docsis_cm_cap_mpls_ccfi = -1; +static int hf_bootp_docsis_cm_cap_mpls_stci = -1; +static int hf_bootp_docsis_cm_cap_mpls_ctci = -1; +static int hf_bootp_docsis_cm_cap_mpls_itpid = -1; +static int hf_bootp_docsis_cm_cap_mpls_isid = -1; +static int hf_bootp_docsis_cm_cap_mpls_itci = -1; +static int hf_bootp_docsis_cm_cap_mpls_ipcp = -1; +static int hf_bootp_docsis_cm_cap_mpls_idei = -1; +static int hf_bootp_docsis_cm_cap_mpls_iuca = -1; +static int hf_bootp_docsis_cm_cap_mpls_btpid = -1; +static int hf_bootp_docsis_cm_cap_mpls_btci = -1; +static int hf_bootp_docsis_cm_cap_mpls_bpcp = -1; +static int hf_bootp_docsis_cm_cap_mpls_bdei = -1; +static int hf_bootp_docsis_cm_cap_mpls_bvid = -1; +static int hf_bootp_docsis_cm_cap_mpls_bda = -1; +static int hf_bootp_docsis_cm_cap_mpls_bsa = -1; +static int hf_bootp_docsis_cm_cap_mpls_tc = -1; +static int hf_bootp_docsis_cm_cap_mpls_label = -1; static const value_string docsis_cm_cap_enrgmang_vals[] = { { 0x00, "Energy Management 1x1 Feature" }, @@ -4289,15 +5418,12 @@ static const value_string docsis_cm_cap_map_l2vpn_esafe_index_support_vals[] = { { 0, NULL } }; -static const value_string docsis_cm_cap_ussymrate_vals[] = { - { 1 << 0, "160 ksps symbol rate supported" }, - { 1 << 1, "320 ksps symbol rate supported" }, - { 1 << 2, "640 ksps symbol rate supported" }, - { 1 << 3, "1280 ksps symbol rate supported" }, - { 1 << 4, "2560 ksps symbol rate supported" }, - { 1 << 5, "5120 ksps symbol rate supported" }, - { 0, NULL } -}; +static int hf_bootp_docsis_cm_cap_ussymrate_160 = -1; +static int hf_bootp_docsis_cm_cap_ussymrate_320 = -1; +static int hf_bootp_docsis_cm_cap_ussymrate_640 = -1; +static int hf_bootp_docsis_cm_cap_ussymrate_1280 = -1; +static int hf_bootp_docsis_cm_cap_ussymrate_2560 = -1; +static int hf_bootp_docsis_cm_cap_ussymrate_5120 = -1; static void display_uint_with_range_checking(proto_item *ti, guint8 val_byte, guint16 val_uint16, int min_value, int max_value) @@ -4332,7 +5458,7 @@ static void get_opt125_tlv(tvbuff_t *tvb, guint off, guint8 *tlvtype, guint8 *tl static void get_opt60_tlv(tvbuff_t *tvb, guint off, guint8 *tlvtype, guint8 *tlvlen, guint8 **value) { - guint i; + guint i; guint8 *val_asc; val_asc = (guint8 *)wmem_alloc0(wmem_packet_scope(), 4); @@ -4355,17 +5481,15 @@ static void get_opt60_tlv(tvbuff_t *tvb, guint off, guint8 *tlvtype, guint8 *tlv static void dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len, gboolean opt125) { - guint8 *asc_val; - guint i; + guint8 *asc_val; proto_item *ti; proto_tree *subtree; - char bit_fld[64]; - guint8 tlv_type; - guint8 tlv_len; - guint8 val_byte = 0; - guint16 val_uint16 = 0; - guint8 *val_other = NULL; - guint off = voff; + guint8 tlv_type; + guint8 tlv_len; + guint8 val_byte = 0; + guint16 val_uint16 = 0; + guint8 *val_other = NULL; + guint off = voff; asc_val = (guint8*)wmem_alloc0(wmem_packet_scope(), 4); @@ -4376,8 +5500,7 @@ dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len, gboo tlv_type = tvb_get_guint8(tvb, off); /* Length */ tlv_len = tvb_get_guint8(tvb, off+1); - proto_tree_add_uint_format_value(v_tree, hf_bootp_docsis_cm_cap_len, tvb, off+1, 1, - tlv_len, "%d", tlv_len); + proto_tree_add_uint(v_tree, hf_bootp_docsis_cm_cap_len, tvb, off+1, 1, tlv_len); } else { @@ -4613,37 +5736,64 @@ dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len, gboo subtree = proto_item_add_subtree(ti, ett_bootp_option); if (tlv_type == DOCSIS_CM_CAP_RNGHLDOFF_SUP && tlv_len >= 4) { - for (i = 0 ; i < 4; i++) - { - decode_bitfield_value(bit_fld, - (val_other[2] << sizeof(guint8)) + val_other[3], - docsis_cm_cap_ranging_hold_off_vals[i].value, - 16); - proto_tree_add_text(subtree, tvb, off + 2, 4, "%s%s", - bit_fld, docsis_cm_cap_ranging_hold_off_vals[i].strptr); - } + const int * flags[] = { + &hf_bootp_docsis_cm_cap_ranging_hold_off_cm, + &hf_bootp_docsis_cm_cap_ranging_hold_off_eps, + &hf_bootp_docsis_cm_cap_ranging_hold_off_emta, + &hf_bootp_docsis_cm_cap_ranging_hold_off_dsg, + NULL + }; + val_uint16 = (val_other[2] << sizeof(guint8)) + val_other[3]; + + proto_tree_add_bitmask_list_value(subtree, tvb, off + 2, 4, flags, val_uint16); } if (tlv_type == DOCSIS_CM_CAP_USSYMRATE_SUP) { - for (i = 0 ; i < 6; i++) - { - decode_bitfield_value(bit_fld, val_byte,docsis_cm_cap_ussymrate_vals[i].value, 8); - proto_tree_add_text(subtree, tvb, off + 2, 1, "%s%s", - bit_fld, docsis_cm_cap_ussymrate_vals[i].strptr); - - } + const int * flags[] = { + &hf_bootp_docsis_cm_cap_ussymrate_160, + &hf_bootp_docsis_cm_cap_ussymrate_320, + &hf_bootp_docsis_cm_cap_ussymrate_640, + &hf_bootp_docsis_cm_cap_ussymrate_1280, + &hf_bootp_docsis_cm_cap_ussymrate_2560, + &hf_bootp_docsis_cm_cap_ussymrate_5120, + NULL + }; + + proto_tree_add_bitmask_list_value(subtree, tvb, off + 2, 1, flags, val_byte); } if (tlv_type == DOCSIS_CM_CAP_Opt802MPLSSup && tlv_len >= 4) { - for (i = 0 ; i < 25; i++) - { - decode_bitfield_value(bit_fld, - (val_other[2] << sizeof(guint8)) + val_other[3], - docsis_cm_cap_mpls_vals[i].value, - 32); - proto_tree_add_text(subtree, tvb, off + 2, 4, "%s%s", - bit_fld, docsis_cm_cap_mpls_vals[i].strptr); - } + const int * flags[] = { + &hf_bootp_docsis_cm_cap_mpls_stpid, + &hf_bootp_docsis_cm_cap_mpls_svid, + &hf_bootp_docsis_cm_cap_mpls_spcp, + &hf_bootp_docsis_cm_cap_mpls_sdei, + &hf_bootp_docsis_cm_cap_mpls_ctpid, + &hf_bootp_docsis_cm_cap_mpls_cvid, + &hf_bootp_docsis_cm_cap_mpls_cpcp, + &hf_bootp_docsis_cm_cap_mpls_ccfi, + &hf_bootp_docsis_cm_cap_mpls_stci, + &hf_bootp_docsis_cm_cap_mpls_ctci, + &hf_bootp_docsis_cm_cap_mpls_itpid, + &hf_bootp_docsis_cm_cap_mpls_isid, + &hf_bootp_docsis_cm_cap_mpls_itci, + &hf_bootp_docsis_cm_cap_mpls_ipcp, + &hf_bootp_docsis_cm_cap_mpls_idei, + &hf_bootp_docsis_cm_cap_mpls_iuca, + &hf_bootp_docsis_cm_cap_mpls_btpid, + &hf_bootp_docsis_cm_cap_mpls_btci, + &hf_bootp_docsis_cm_cap_mpls_bpcp, + &hf_bootp_docsis_cm_cap_mpls_bdei, + &hf_bootp_docsis_cm_cap_mpls_bvid, + &hf_bootp_docsis_cm_cap_mpls_bda, + &hf_bootp_docsis_cm_cap_mpls_bsa, + &hf_bootp_docsis_cm_cap_mpls_tc, + &hf_bootp_docsis_cm_cap_mpls_label, + NULL + }; + val_uint16 = (val_other[2] << sizeof(guint8)) + val_other[3]; + + proto_tree_add_bitmask_list_value(subtree, tvb, off + 2, 4, flags, val_uint16); } if (opt125) { @@ -4657,6 +5807,47 @@ dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len, gboo } } +static gboolean +dissect_packetcable_cm_vendor_id_heur( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_ ) +{ + guint8* vendor_id; + + if (tvb_reported_length(tvb) < 10) { + return FALSE; + } + + vendor_id = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, 10, ENC_ASCII|ENC_NA); + if ((strcmp((const char*)vendor_id, PACKETCABLE_CM_CAP11) == 0) || + (strcmp((const char*)vendor_id, PACKETCABLE_CM_CAP20) == 0)) { + dissect_docsis_cm_cap(tree, tvb, 0, tvb_reported_length(tvb), FALSE); + return TRUE; + } + + if ((strcmp((const char*)vendor_id, PACKETCABLE_CM_CAP30) == 0)) { + proto_tree_add_item(tree, hf_bootp_option_vendor_class_data, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA); + return TRUE; + } + + return FALSE; +} + +static gboolean +dissect_packetcable_bsdpd_vendor_id_heur( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_ ) +{ + int vendor_id_len = (int)strlen(PACKETCABLE_BSDPD); + if ((int)tvb_reported_length(tvb) < vendor_id_len) { + return FALSE; + } + + if (tvb_memeql(tvb, 0, (const guint8*)PACKETCABLE_BSDPD, vendor_id_len) == 0 ) { + proto_tree_add_item(tree, hf_bootp_option_vendor_class_data, tvb, vendor_id_len, tvb_reported_length_remaining(tvb, vendor_id_len), ENC_ASCII|ENC_NA); + return TRUE; + } + + return FALSE; +} + + /* Definitions specific to PKT-SP-PROV-I05-021127 begin with "PKT_CCC_I05". Definitions specific to IETF draft 5 and RFC 3495 begin with "PKT_CCC_IETF". Shared definitions begin with "PKT_CCC". @@ -4718,8 +5909,8 @@ static int dissect_packetcable_i05_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend) { - int suboptoff = optoff; - guint8 subopt, subopt_len, fetch_tgt, timer_val, ticket_ctl; + int suboptoff = optoff; + guint8 subopt, subopt_len, fetch_tgt, timer_val, ticket_ctl; proto_tree *pkt_s_tree; proto_item *vti; @@ -4735,9 +5926,9 @@ dissect_packetcable_i05_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_ subopt_len = tvb_get_guint8(tvb, optoff); suboptoff++; - vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2, - "Suboption %u: %s: ", subopt, - val_to_str_const(subopt, pkt_i05_ccc_opt_vals, "unknown/reserved") ); + vti = proto_tree_add_uint(v_tree, hf_bootp_pc_i05_ccc_suboption, tvb, optoff, 1, subopt); + proto_item_set_len(vti, subopt_len + 2); + proto_item_append_text(vti, ": "); switch (subopt) { @@ -4793,15 +5984,9 @@ dissect_packetcable_i05_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_ subopt_len != 12 ? " [Invalid]" : ""); if (subopt_len == 12) { pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4, - "pktcMtaDevRealmUnsolicitedKeyNomTimeout: %u", - tvb_get_ntohl(tvb, suboptoff)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4, - "pktcMtaDevRealmUnsolicitedKeyMaxTimeout: %u", - tvb_get_ntohl(tvb, suboptoff + 4)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4, - "pktcMtaDevRealmUnsolicitedKeyMaxRetries: %u", - tvb_get_ntohl(tvb, suboptoff + 8)); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_realm_unc_key_nom_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_timeout, tvb, suboptoff + 4, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_retries, tvb, suboptoff + 8, 4, ENC_BIG_ENDIAN); } suboptoff += subopt_len; break; @@ -4816,15 +6001,9 @@ dissect_packetcable_i05_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_ subopt_len != 12 ? " [Invalid]" : ""); if (subopt_len == 12) { pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4, - "pktcMtaDevProvUnsolicitedKeyNomTimeout: %u", - tvb_get_ntohl(tvb, suboptoff)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4, - "pktcMtaDevProvUnsolicitedKeyMaxTimeout: %u", - tvb_get_ntohl(tvb, suboptoff + 4)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4, - "pktcMtaDevProvUnsolicitedKeyMaxRetries: %u", - tvb_get_ntohl(tvb, suboptoff + 8)); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_prov_unc_key_nom_timeout, tvb, suboptoff + 8, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_timeout, tvb, suboptoff + 8, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_retries, tvb, suboptoff + 8, 4, ENC_BIG_ENDIAN); } suboptoff += subopt_len; break; @@ -4852,27 +6031,22 @@ dissect_packetcable_i05_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_ return suboptoff; } - -static const value_string sec_tcm_vals[] = { - { 1 << 0, "PacketCable Provisioning Server" }, - { 1 << 1, "All PacketCable Call Management Servers" }, - { 0, NULL } -}; +static int hf_bootp_ccc_ietf_sec_tkt_pc_provision_server = -1; +static int hf_bootp_ccc_ietf_sec_tkt_all_pc_call_management = -1; static int dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v_tree, tvbuff_t *tvb, int optoff, int optend, int revision) { - int suboptoff = optoff; - guint8 subopt, subopt_len; - guint32 ipv4addr; - guint8 prov_type, fetch_tgt, timer_val; - guint16 sec_tcm; + int suboptoff = optoff; + guint8 subopt, subopt_len; + guint8 prov_type, fetch_tgt, timer_val; + guint16 sec_tcm; proto_tree *pkt_s_tree; proto_item *vti; - int max_timer_val = 255, i; + int max_timer_val = 255; const guchar *dns_name; - char bit_fld[24]; + guint dns_name_len; subopt = tvb_get_guint8(tvb, suboptoff); suboptoff++; @@ -4885,9 +6059,9 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v subopt_len = tvb_get_guint8(tvb, suboptoff); suboptoff++; - vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2, - "Suboption %u: %s: ", subopt, - val_to_str_const(subopt, pkt_draft5_ccc_opt_vals, "unknown/reserved") ); + vti = proto_tree_add_uint(v_tree, hf_bootp_pc_ietf_ccc_suboption, tvb, optoff, 1, subopt); + proto_item_set_len(vti, subopt_len + 2); + proto_item_append_text(vti, ": "); switch (subopt) { @@ -4897,9 +6071,8 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v expert_add_info(pinfo, vti, &ei_bootp_missing_subopt_value); return (optend); } - ipv4addr = tvb_get_ipv4(tvb, suboptoff); proto_item_append_text(vti, "%s (%u byte%s%s)", - ip_to_str((guint8 *)&ipv4addr), + tvb_ip_to_str(tvb, suboptoff), subopt_len, plurality(subopt_len, "", "s"), subopt_len != 4 ? " [Invalid]" : ""); @@ -4916,8 +6089,8 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v switch (prov_type) { case 0: - get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name); - proto_item_append_text(vti, "%s (%u byte%s)", dns_name, + get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name, &dns_name_len); + proto_item_append_text(vti, "%s (%u byte%s)", format_text(wmem_packet_scope(), dns_name, dns_name_len), subopt_len - 1, plurality(subopt_len, "", "s") ); break; @@ -4926,9 +6099,8 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v expert_add_info(pinfo, vti, &ei_bootp_missing_subopt_value); return (optend); } - ipv4addr = tvb_get_ipv4(tvb, suboptoff); proto_item_append_text(vti, "%s (%u byte%s%s)", - ip_to_str((guint8 *)&ipv4addr), + tvb_ip_to_str(tvb, suboptoff), subopt_len, plurality(subopt_len, "", "s"), subopt_len != 5 ? " [Invalid]" : ""); @@ -4954,15 +6126,9 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v subopt_len != 12 ? " [Invalid]" : ""); if (subopt_len == 12) { pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4, - "pktcMtaDevRealmUnsolicitedKeyNomTimeout: %u", - tvb_get_ntohl(tvb, suboptoff)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4, - "pktcMtaDevRealmUnsolicitedKeyMaxTimeout: %u", - tvb_get_ntohl(tvb, suboptoff + 4)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4, - "pktcMtaDevRealmUnsolicitedKeyMaxRetries: %u", - tvb_get_ntohl(tvb, suboptoff + 8)); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_realm_unc_key_nom_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_timeout, tvb, suboptoff + 4, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_retries, tvb, suboptoff + 8, 4, ENC_BIG_ENDIAN); } suboptoff += subopt_len; break; @@ -4973,22 +6139,16 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v subopt_len != 12 ? " [Invalid]" : ""); if (subopt_len == 12) { pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4, - "pktcMtaDevProvUnsolicitedKeyNomTimeout: %u", - tvb_get_ntohl(tvb, suboptoff)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4, - "pktcMtaDevProvUnsolicitedKeyMaxTimeout: %u", - tvb_get_ntohl(tvb, suboptoff + 4)); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4, - "pktcMtaDevProvUnsolicitedKeyMaxRetries: %u", - tvb_get_ntohl(tvb, suboptoff + 8)); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_prov_unc_key_nom_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_timeout, tvb, suboptoff + 4, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pkt_s_tree, hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_retries, tvb, suboptoff + 8, 4, ENC_BIG_ENDIAN); } suboptoff += subopt_len; break; case PKT_CCC_KRB_REALM: /* String values */ - get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name); - proto_item_append_text(vti, "%s (%u byte%s)", dns_name, + get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name, &dns_name_len); + proto_item_append_text(vti, "%s (%u byte%s)", format_text(wmem_packet_scope(), dns_name, dns_name_len), subopt_len, plurality(subopt_len, "", "s") ); suboptoff += subopt_len; break; @@ -5034,13 +6194,8 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v subopt_len != 2 ? " [Invalid]" : ""); if (subopt_len == 2) { pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (i = 0; i < 2; i++) { - if (sec_tcm & sec_tcm_vals[i].value) { - decode_bitfield_value(bit_fld, sec_tcm, sec_tcm_vals[i].value, 16); - proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 2, "%sInvalidate %s", - bit_fld, sec_tcm_vals[i].strptr); - } - } + proto_tree_add_boolean(pkt_s_tree, hf_bootp_ccc_ietf_sec_tkt_pc_provision_server, tvb, suboptoff, 2, sec_tcm); + proto_tree_add_boolean(pkt_s_tree, hf_bootp_ccc_ietf_sec_tkt_all_pc_call_management, tvb, suboptoff, 2, sec_tcm); } suboptoff += subopt_len; break; @@ -5052,6 +6207,29 @@ dissect_packetcable_ietf_ccc(packet_info *pinfo, proto_item *v_ti, proto_tree *v return suboptoff; } +static int +dissect_bootpopt_packetcable_ccc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + switch (pkt_ccc_protocol_version) { + + case PACKETCABLE_CCC_I05: + offset = dissect_packetcable_i05_ccc(pinfo, tree, tree, tvb, offset, tvb_reported_length(tvb)); + break; + case PACKETCABLE_CCC_DRAFT5: + case PACKETCABLE_CCC_RFC_3495: + offset = dissect_packetcable_ietf_ccc(pinfo, tree, tree, tvb, offset, tvb_reported_length(tvb), pkt_ccc_protocol_version); + break; + default: /* XXX Should we do something here? */ + break; + } + } + + return tvb_captured_length(tvb); +} + #define BOOTREQUEST 1 #define BOOTREPLY 2 @@ -5061,27 +6239,32 @@ static const value_string op_vals[] = { { 0, NULL } }; -static void -dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int +dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_tree *bp_tree; - proto_item *ti; - proto_tree *flag_tree; + proto_item *bp_ti, *ti; proto_item *fi, *hidden_item; guint8 op; guint8 htype, hlen; int voff, eoff, tmpvoff; /* vendor offset, end offset */ guint32 ip_addr; gboolean at_end; - const char *dhcp_type = NULL; - const guint8 *vendor_class_id = NULL; + const char *dhcp_type = NULL; + const guint8 *vendor_class_id = NULL; guint16 flags, secs; int offset_delta; - guint8 overload = 0; /* DHCP option overload */ + guint8 overload = 0; /* DHCP option overload */ + static const int * bootp_flags[] = { + &hf_bootp_flags_broadcast, + &hf_bootp_flags_reserved, + NULL + }; + rfc3396_dns_domain_search_list.total_number_of_block = 0; - rfc3396_dns_domain_search_list.tvb_composite = NULL; - rfc3396_sip_server.total_number_of_block = 0; - rfc3396_sip_server.tvb_composite = NULL; + rfc3396_dns_domain_search_list.tvb_composite = NULL; + rfc3396_sip_server.total_number_of_block = 0; + rfc3396_sip_server.tvb_composite = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BOOTP"); /* @@ -5099,7 +6282,7 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) && hlen == 6) { col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s (%s)", tvb_arphrdaddr_to_str(tvb, 28, hlen, htype), - get_ether_name(tvb_get_ptr(tvb, 28, hlen))); + tvb_get_ether_name(tvb, 28)); } else { col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s", @@ -5127,6 +6310,9 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } eoff = tvb_reported_length(tvb); + bp_ti = proto_tree_add_item(tree, proto_bootp, tvb, 0, -1, ENC_NA); + bp_tree = proto_item_add_subtree(bp_ti, ett_bootp); + /* * In the first pass, we just look for the DHCP message type * and Vendor class identifier options. @@ -5136,10 +6322,12 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) rfc3396_dns_domain_search_list.index_current_block = 0; rfc3396_sip_server.index_current_block = 0; while (tmpvoff < eoff && !at_end) { - offset_delta = bootp_option(tvb, pinfo, 0, tmpvoff, eoff, TRUE, &at_end, + offset_delta = bootp_option(tvb, pinfo, NULL, tmpvoff, eoff, TRUE, &at_end, &dhcp_type, &vendor_class_id, &overload); if (offset_delta <= 0) { - THROW(ReportedBoundsError); + proto_tree_add_expert(bp_tree, pinfo, &ei_bootp_option_parse_err, + tvb, tmpvoff, eoff); + return tmpvoff; } tmpvoff += offset_delta; } @@ -5161,12 +6349,9 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } /* - * OK, now build the protocol tree. + * OK, now populate the protocol tree. */ - ti = proto_tree_add_item(tree, proto_bootp, tvb, 0, -1, ENC_NA); - bp_tree = proto_item_add_subtree(ti, ett_bootp); - proto_tree_add_uint(bp_tree, hf_bootp_type, tvb, 0, 1, op); @@ -5185,23 +6370,18 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) */ secs = tvb_get_letohs(tvb, 8); if (secs > 0 && secs <= 0xff) { - ti = proto_tree_add_uint_format_value(bp_tree, hf_bootp_secs, tvb, - 8, 2, secs, "%u", secs); + ti = proto_tree_add_uint(bp_tree, hf_bootp_secs, tvb, 8, 2, secs); expert_add_info_format(pinfo, ti, &ei_bootp_secs_le, "Seconds elapsed appears to be encoded as little-endian"); } else { proto_tree_add_item(bp_tree, hf_bootp_secs, tvb, 8, 2, ENC_BIG_ENDIAN); } flags = tvb_get_ntohs(tvb, 10); - fi = proto_tree_add_uint(bp_tree, hf_bootp_flags, tvb, - 10, 2, flags); + fi = proto_tree_add_bitmask(bp_tree, tvb, 10, hf_bootp_flags, + ett_bootp_flags, bootp_flags, ENC_NA); proto_item_append_text(fi, " (%s)", (flags & BOOTP_BC) ? "Broadcast" : "Unicast"); - flag_tree = proto_item_add_subtree(fi, ett_bootp_flags); - proto_tree_add_boolean(flag_tree, hf_bootp_flags_broadcast, tvb, - 10, 2, flags); - proto_tree_add_uint(flag_tree, hf_bootp_flags_reserved, tvb, - 10, 2, flags); + proto_tree_add_item(bp_tree, hf_bootp_ip_client, tvb, 12, 4, ENC_BIG_ENDIAN); proto_tree_add_item(bp_tree, hf_bootp_ip_your, tvb, @@ -5223,14 +6403,12 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) if ((16 - hlen) > 0) proto_tree_add_item(bp_tree, hf_bootp_hw_addr_padding, tvb, 28+hlen, 16-hlen, ENC_NA); } else { - proto_tree_add_text(bp_tree, tvb, - 28, 16, "Client address not given"); + proto_tree_add_expert(bp_tree, pinfo, &ei_bootp_client_address_not_given, tvb, 28, 16); } if (overload & OPT_OVERLOAD_SNAME) { - proto_tree_add_text (bp_tree, tvb, - SERVER_NAME_OFFSET, SERVER_NAME_LEN, - "Server name option overloaded by DHCP"); + proto_tree_add_expert(bp_tree, pinfo, &ei_bootp_server_name_overloaded_by_dhcp, tvb, + SERVER_NAME_OFFSET, SERVER_NAME_LEN); } else { /* The server host name is optional */ if (tvb_get_guint8(tvb, SERVER_NAME_OFFSET) != '\0') { @@ -5247,9 +6425,8 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } if (overload & OPT_OVERLOAD_FILE) { - proto_tree_add_text (bp_tree, tvb, - FILE_NAME_OFFSET, FILE_NAME_LEN, - "Boot file name option overloaded by DHCP"); + proto_tree_add_expert(bp_tree, pinfo, &ei_bootp_boot_filename_overloaded_by_dhcp, tvb, + FILE_NAME_OFFSET, FILE_NAME_LEN); } else { /* Boot file is optional */ if (tvb_get_guint8(tvb, FILE_NAME_OFFSET) != '\0') { @@ -5276,8 +6453,8 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) voff, 4, ip_addr, "DHCP"); voff += 4; } else { - proto_tree_add_text(bp_tree, tvb, - voff, 64, "Bootp vendor specific options"); + proto_tree_add_item(bp_tree, hf_bootp_vendor_specific_options, tvb, + voff, 64, ENC_NA); voff += 64; } @@ -5288,20 +6465,24 @@ dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset_delta = bootp_option(tvb, pinfo, bp_tree, voff, eoff, FALSE, &at_end, &dhcp_type, &vendor_class_id, &overload); if (offset_delta <= 0) { - THROW(ReportedBoundsError); + proto_tree_add_expert(bp_tree, pinfo, &ei_bootp_option_parse_err, + tvb, voff, eoff); + return voff; } voff += offset_delta; } if ((dhcp_type != NULL) && (!at_end)) { - expert_add_info(pinfo, ti, &ei_bootp_end_option_missing); + expert_add_info(pinfo, bp_ti, &ei_bootp_end_option_missing); } if (voff < eoff) { /* * Padding after the end option. */ - proto_tree_add_text(bp_tree, tvb, voff, eoff - voff, "Padding"); + proto_tree_add_item(bp_tree, hf_bootp_option_padding, tvb, voff, eoff - voff, ENC_NA); } + + return tvb_captured_length(tvb); } static void @@ -5310,11 +6491,11 @@ bootp_init_protocol(void) guint i; /* first copy default_bootp_opt[] to bootp_opt[]. This resets all values to default */ - for(i=0; i 0) && (saved_uat_opts == NULL)) { - bootp_opt[i].text = default_bootp_opt[i].text; - bootp_opt[i].ftype = default_bootp_opt[i].ftype; - bootp_opt[i].phf = default_bootp_opt[i].phf; + saved_uat_opts = wmem_list_new(NULL); } /* Now apply the custom options */ @@ -5323,6 +6504,98 @@ bootp_init_protocol(void) bootp_opt[uat_bootp_records[i].opt].text = wmem_strdup(wmem_file_scope(), uat_bootp_records[i].text); bootp_opt[uat_bootp_records[i].opt].ftype = uat_bootp_records[i].ftype; bootp_opt[uat_bootp_records[i].opt].phf = NULL; + + /* Apply the custom option to the dissection table*/ + dissector_change_uint("bootp.option", uat_bootp_records[i].opt, bootpopt_basic_handle); + + /* Save the option so it can be cleared later */ + wmem_list_append(saved_uat_opts, GUINT_TO_POINTER(uat_bootp_records[i].opt)); + } +} + +static void +bootp_clear_uat_bootpopt(gpointer data, gpointer user_data _U_) +{ + dissector_reset_uint("bootp.option", GPOINTER_TO_UINT(data)); +} + +static void +bootp_cleanup_protocol(void) +{ + if (saved_uat_opts != NULL) { + wmem_list_foreach(saved_uat_opts, bootp_clear_uat_bootpopt, + NULL); + + wmem_destroy_list(saved_uat_opts); + saved_uat_opts = NULL; + } +} + + +/* TAP STAT INFO */ +typedef enum +{ + MESSAGE_TYPE_COLUMN = 0, + PACKET_COLUMN +} bootp_stat_columns; + +static stat_tap_table_item bootp_stat_fields[] = {{TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "DHCP Message Type", "%-25s"}, {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Packets", "%d"}}; + +static void bootp_stat_init(stat_tap_table_ui* new_stat, stat_tap_gui_init_cb gui_callback, void* gui_data) +{ + int num_fields = sizeof(bootp_stat_fields)/sizeof(stat_tap_table_item); + stat_tap_table* table = stat_tap_init_table("DHCP Statistics", num_fields, 0, NULL, gui_callback, gui_data); + int i = 0; + stat_tap_table_item_type items[sizeof(bootp_stat_fields)/sizeof(stat_tap_table_item)]; + + stat_tap_add_table(new_stat, table); + + /* Add a row for each value type */ + while (opt53_text[i].strptr) + { + items[MESSAGE_TYPE_COLUMN].type = TABLE_ITEM_STRING; + items[MESSAGE_TYPE_COLUMN].value.string_value = opt53_text[i].strptr; + items[PACKET_COLUMN].type = TABLE_ITEM_UINT; + items[PACKET_COLUMN].value.uint_value = 0; + + stat_tap_init_table_row(table, i, num_fields, items); + i++; + } +} + +static gboolean +bootp_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *data) +{ + stat_data_t* stat_data = (stat_data_t*)tapdata; + const char* value = (const char*)data; + stat_tap_table* table; + stat_tap_table_item_type* msg_data; + guint i = 0; + gint idx; + + idx = str_to_val_idx(value, opt53_text); + if (idx < 0) + return FALSE; + + table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, i); + msg_data = stat_tap_get_field_data(table, idx, PACKET_COLUMN); + msg_data->value.uint_value++; + stat_tap_set_field_data(table, idx, PACKET_COLUMN, msg_data); + + return TRUE; +} + +static void +bootp_stat_reset(stat_tap_table* table) +{ + guint element; + stat_tap_table_item_type* item_data; + + for (element = 0; element < table->num_elements; element++) + { + item_data = stat_tap_get_field_data(table, element, PACKET_COLUMN); + item_data->value.uint_value = 0; + stat_tap_set_field_data(table, element, PACKET_COLUMN, item_data); } } @@ -5330,15 +6603,15 @@ void proto_register_bootp(void) { static const value_string bootp_custom_type_vals[] = { - { ipv4, "IP Address"}, - { ipv4_list, "IP Address List" }, - { string, "string" }, - { bytes, "bytes" }, - { val_boolean, "boolean" }, - { val_u_byte, "byte" }, - { val_u_short, "unsigned short" }, + { ipv4, "IP Address"}, + { ipv4_list, "IP Address List" }, + { string, "string" }, + { bytes, "bytes" }, + { val_boolean, "boolean" }, + { val_u_byte, "byte" }, + { val_u_short, "unsigned short" }, { val_u_short_list, "unsigned short list" }, - { val_u_long, "unsigned long" }, + { val_u_long, "unsigned long" }, { time_in_s_secs, "integer time in seconds" }, { time_in_u_secs, "unsigned integer time in seconds" }, { 0x00, NULL } @@ -5445,6 +6718,11 @@ proto_register_bootp(void) FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_bootp_vendor_specific_options, + { "Bootp vendor specific options", "bootp.vendor_specific_options", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_bootp_fqdn_s, { "Server", "bootp.fqdn.s", FT_BOOLEAN, 8, TFS(&tfs_fqdn_s), F_FQDN_S, @@ -5465,6 +6743,11 @@ proto_register_bootp(void) FT_BOOLEAN, 8, TFS(&tfs_fqdn_n), F_FQDN_N, "If true, server should not do any DDNS updates", HFILL }}, + { &hf_bootp_fqdn_flags, + { "Flags", "bootp.fqdn.flags", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_bootp_fqdn_mbz, { "Reserved flags", "bootp.fqdn.mbz", FT_UINT8, BASE_HEX, NULL, F_FQDN_MBZ, @@ -5495,6 +6778,116 @@ proto_register_bootp(void) FT_UINT8, BASE_DEC, NULL, 0x0, "PacketCable MTA Device Capabilities Length", HFILL }}, + { &hf_bootp_pkt_mta_cap_type, + { "Type", "bootp.vendor.pktc.mta_cap_type", + FT_UINT8, BASE_DEC, VALS(pkt_mdc_type_vals), 0x0, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_supp_flow_secure, + { "Secure Flow (Full Secure Provisioning Flow)", "bootp.vendor.pktc.mdc.supp_flow.secure", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x01, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_supp_flow_hybrid, + { "Hybrid Flow", "bootp.vendor.pktc.mdc.supp_flow.hybrid", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x02, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_supp_flow_basic, + { "Basic Flow", "bootp.vendor.pktc.mdc.supp_flow.basic", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x04, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_mta, + { "PacketCable 1.5 MTA MIB", "bootp.vendor.pktc.mdc_cl.mib.mta", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_signaling, + { "PacketCable 1.5 Signaling MIB", "bootp.vendor.pktc.mdc_cl.mib.signaling", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x02, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_management_event, + { "PacketCable 1.5 Management Event MIB", "bootp.vendor.pktc.mdc_cl.mib.management_event", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_mta_extension, + { "PacketCable 1.5 MTA Extension MIB", "bootp.vendor.pktc.mdc_cl.mib.mta_extension", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x08, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_mta_signaling_extension, + { "PacketCable 1.5 Signaling Extension MIB", "bootp.vendor.pktc.mdc_cl.mib.signaling_extension", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_mta_mem_extention, + { "PacketCable 1.5 MEM Extension MIB", "bootp.vendor.pktc.mdc_cl.mib.mem_extention", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x20, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_cl_reserved, + { "Reserved", "bootp.vendor.pktc.mdc_cl.mib.reserved", + FT_UINT8, BASE_HEX, NULL, 0xC0, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_ietf_mta, + { "IETF MTA MIB", "bootp.vendor.pktc.mdc_ietf.mib.mta", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_ietf_signaling, + { "IETF Signaling MIB", "bootp.vendor.pktc.mdc_ietf.mib.signaling", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x02, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_ietf_management_event, + { "IETF Management Event MIB", "bootp.vendor.pktc.mdc_ietf.mib.management_event", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_ietf_reserved, + { "Reserved", "bootp.vendor.pktc.mdc_ietf.mib.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF8, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_mta, + { "PacketCable 1.5 MTA MIB", "bootp.vendor.pktc.mdc_euro.mib.mta", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_signaling, + { "PacketCable 1.5 Signaling MIB", "bootp.vendor.pktc.mdc_euro.mib.signaling", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x02, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_management_event, + { "PacketCable 1.5 Management Event MIB", "bootp.vendor.pktc.mdc_euro.mib.management_event", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_mta_extension, + { "PacketCable 1.5 MTA Extension MIB", "bootp.vendor.pktc.mdc_euro.mib.mta_extension", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x08, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_mta_signaling_extension, + { "PacketCable 1.5 Signaling Extension MIB", "bootp.vendor.pktc.mdc_euro.mib.signaling_extension", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x10, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_mta_mem_extention, + { "PacketCable 1.5 MEM Extension MIB", "bootp.vendor.pktc.mdc_euro.mib.mem_extention", + FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x20, + NULL, HFILL }}, + + { &hf_bootp_pkt_mdc_mib_euro_reserved, + { "Reserved", "bootp.vendor.pktc.mdc_euro.mib.reserved", + FT_UINT8, BASE_HEX, NULL, 0xC0, + NULL, HFILL }}, + { &hf_bootp_docsis_cm_cap_len, { "CM DC Length", "bootp.vendor.docsis.cm_cap_len", FT_UINT8, BASE_DEC, NULL, 0x0, @@ -5505,21 +6898,241 @@ proto_register_bootp(void) FT_UINT16, BASE_DEC, VALS(docsis_cm_cap_type_vals), 0x0, "Docsis Cable Modem Device Capability type", HFILL }}, + { &hf_bootp_docsis_cm_cap_ranging_hold_off_cm, + { "CM", "bootp.docsis_cm_cap.ranging_hold_off.cm", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x01, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ranging_hold_off_eps, + { "ePS or eRouter", "bootp.docsis_cm_cap.ranging_hold_off.eps", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x02, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ranging_hold_off_emta, + { "EMTA or EDVA", "bootp.docsis_cm_cap.ranging_hold_off.emta", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x04, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ranging_hold_off_dsg, + { "DSG/eSTB", "bootp.docsis_cm_cap.ranging_hold_off.dsg", + FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x08, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_stpid, + { "[IEEE 802.1ad] S-TPID", "bootp.docsis_cm_cap.mpls.stpid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x01, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_svid, + { "[IEEE 802.1ad] S-VID", "bootp.docsis_cm_cap.mpls.svid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x02, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_spcp, + { "[IEEE 802.1ad] S-PCP", "bootp.docsis_cm_cap.mpls.spcp", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x04, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_sdei, + { "[IEEE 802.1ad] S-DEI", "bootp.docsis_cm_cap.mpls.sdei", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x08, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_ctpid, + { "[IEEE 802.1ad] C-TPID", "bootp.docsis_cm_cap.mpls.ctpid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x10, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_cvid, + { "[IEEE 802.1ad] C-VID", "bootp.docsis_cm_cap.mpls.cvid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x20, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_cpcp, + { "[IEEE 802.1ad] C-PCP", "bootp.docsis_cm_cap.mpls.cpcp", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x40, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_ccfi, + { "[IEEE 802.1ad] C-CFI", "bootp.docsis_cm_cap.mpls.ccfi", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x80, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_stci, + { "[IEEE 802.1ad] S-TCI", "bootp.docsis_cm_cap.mpls.stci", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x100, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_ctci, + { "[IEEE 802.1ad] C-TCI", "bootp.docsis_cm_cap.mpls.ctci", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x200, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_itpid, + { "[IEEE 802.1ad] I-TPID", "bootp.docsis_cm_cap.mpls.itpid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x400, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_isid, + { "[IEEE 802.1ad] I-SID", "bootp.docsis_cm_cap.mpls.isid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x800, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_itci, + { "[IEEE 802.1ad] I-TCI", "bootp.docsis_cm_cap.mpls.itci", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x1000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_ipcp, + { "[IEEE 802.1ad] I-PCP", "bootp.docsis_cm_cap.mpls.ipcp", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x2000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_idei, + { "[IEEE 802.1ad] I-DEI", "bootp.docsis_cm_cap.mpls.idei", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x4000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_iuca, + { "[IEEE 802.1ad] I-UCA", "bootp.docsis_cm_cap.mpls.iuca", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x8000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_btpid, + { "[IEEE 802.1ad] B-TPID", "bootp.docsis_cm_cap.mpls.btpid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x10000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_btci, + { "[IEEE 802.1ad] B-TCI", "bootp.docsis_cm_cap.mpls.btci", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x20000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_bpcp, + { "[IEEE 802.1ad] B-PCP", "bootp.docsis_cm_cap.mpls.bpcp", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x40000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_bdei, + { "[IEEE 802.1ad] B-DEI", "bootp.docsis_cm_cap.mpls.bdei", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x80000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_bvid, + { "[IEEE 802.1ad] B-VID", "bootp.docsis_cm_cap.mpls.bvid", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x100000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_bda, + { "[IEEE 802.1ad] B-DA", "bootp.docsis_cm_cap.mpls.bda", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x200000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_bsa, + { "[IEEE 802.1ad] B-SA", "bootp.docsis_cm_cap.mpls.bsa", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x200000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_tc, + { "MPLS TC", "bootp.docsis_cm_cap.mpls.tc", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x200000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_mpls_label, + { "MPLS Label", "bootp.docsis_cm_cap.mpls.label", + FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x200000, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ussymrate_160, + { "160 ksps symbol rate", "bootp.docsis_cm_cap.ussymrate.160", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x01, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ussymrate_320, + { "320 ksps symbol rate", "bootp.docsis_cm_cap.ussymrate.320", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x02, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ussymrate_640, + { "640 ksps symbol rate", "bootp.docsis_cm_cap.ussymrate.640", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x04, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ussymrate_1280, + { "1280 ksps symbol rate", "bootp.docsis_cm_cap.ussymrate.1280", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x08, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ussymrate_2560, + { "2560 ksps symbol rate", "bootp.docsis_cm_cap.ussymrate.2560", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x10, + NULL, HFILL }}, + + { &hf_bootp_docsis_cm_cap_ussymrate_5120, + { "5120 ksps symbol rate", "bootp.docsis_cm_cap.ussymrate.5120", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x20, + NULL, HFILL }}, + { &hf_bootp_client_identifier_uuid, - { "Client Identifier (UUID)", "bootp.client_id_uuid", + { "Client Identifier (UUID)", "bootp.client_id.uuid", FT_GUID, BASE_NONE, NULL, 0x0, "Client Machine Identifier (UUID)", HFILL }}, + { &hf_bootp_client_hardware_address, + { "Client hardware address", "bootp.client_hardware_address", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_id_iaid, + { "IAID", "bootp.client_id.iaid", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_id_duid_type, + { "DUID Type", "bootp.client_id.duid_type", + FT_UINT16, BASE_DEC, VALS(duidtype_vals), 0x0, + NULL, HFILL }}, + { &hf_bootp_client_identifier_duid_llt_hw_type, - { "Hardware type", "bootp.client_id_duid_llt_hw_type", + { "Hardware type", "bootp.client_id.duid_llt_hw_type", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0x0, "Client Identifier DUID LLT Hardware type", HFILL }}, { &hf_bootp_client_identifier_duid_ll_hw_type, - { "Hardware type", "bootp.client_id_duid_ll_hw_type", + { "Hardware type", "bootp.client_id.duid_ll_hw_type", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0x0, "Client Identifier DUID LL Hardware type", HFILL }}, + { &hf_bootp_client_identifier_time, + { "Time", "bootp.client_id.time", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_identifier_link_layer_address, + { "Link layer address", "bootp.client_id.link_layer_address", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_identifier_enterprise_num, + { "Enterprise-number", "bootp.client_id.enterprise_num", + FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_identifier, + { "Identifier", "bootp.client_id", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_identifier_type, + { "Type", "bootp.client_id.type", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_client_identifier_undef, + { "Client Identifier", "bootp.client_id.undef", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_bootp_option_type, { "Option", "bootp.option.type", FT_UINT8, BASE_DEC, NULL, 0x0, @@ -5582,7 +7195,7 @@ proto_register_bootp(void) { &hf_bootp_option_subnet_mask, { "Subnet Mask", "bootp.option.subnet_mask", - FT_IPv4, BASE_NONE, NULL, 0x00, + FT_IPv4, BASE_NETMASK, NULL, 0x00, "Option 1: Subnet Mask", HFILL }}, { &hf_bootp_option_time_offset, @@ -5682,7 +7295,7 @@ proto_register_bootp(void) { &hf_bootp_option_policy_filter_subnet_mask, { "Subnet Mask", "bootp.option.policy_filter.subnet_mask", - FT_IPv4, BASE_NONE, NULL, 0x00, + FT_IPv4, BASE_NETMASK, NULL, 0x00, "Option 21: Subnet Mask", HFILL }}, { &hf_bootp_option_non_local_source_routing, @@ -6079,6 +7692,137 @@ proto_register_bootp(void) FT_UINT8, BASE_DEC, NULL, 0x0, "Option 43:Alcatel 255 End", HFILL }}, + { &hf_bootp_option43_arubaap_controllerip, + { "Aruba Controller IP", "bootp.option.vendor.arubaap.controllerip", + FT_STRING, BASE_NONE, NULL, 0x0, + "Address IP of Aruba controller", HFILL }}, + + { &hf_bootp_option43_arubaiap, + { "Aruba Instant AP", "bootp.option.vendor.arubaiap", + FT_STRING, BASE_NONE, NULL, 0x0, + "nameorg,amp-ip-address,password", HFILL }}, + + { &hf_bootp_option43_arubaiap_nameorg, + { "Name Organisation", "bootp.option.vendor.arubaiap.name_org", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_arubaiap_ampip, + { "AMP IP Address", "bootp.option.vendor.arubaiap.amp_ip", + FT_STRING, BASE_NONE, NULL, 0x0, + "Address IP of Airwave server (AMP)", HFILL }}, + + { &hf_bootp_option43_arubaiap_password, + { "Password", "bootp.option.vendor.arubaiap.password", + FT_STRING, BASE_NONE, NULL, 0x0, + "Password for Instant AP Airwave server (AMP)", HFILL }}, + + + { &hf_bootp_option43_bsdp_suboption, + { "Option 43 Suboption", "bootp.option.vendor.bsdp.suboption", + FT_UINT8, BASE_DEC, VALS(option43_cl_suboption_vals), 0x0, + "Option 43:BSDP Suboption", HFILL }}, + + { &hf_bootp_option43_bsdp_message_type, + { "Message Type", "bootp.option.vendor.bsdp.message_type", + FT_UINT8, BASE_DEC, VALS(o43_bsdp_message_type_vals), 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_version, + { "Version", "bootp.option.vendor.bsdp.version", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_server_identifier, + { "Server Identifier", "bootp.option.vendor.bsdp.server_identifier", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_server_priority, + { "Server Priority", "bootp.option.vendor.bsdp.server_priority", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_reply_port, + { "Reply Port", "bootp.option.vendor.bsdp.reply_port", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_list_path, + { "Boot Image List Path", "bootp.option.vendor.bsdp.boot_image_list_path", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_index, + { "Boot Image Index", "bootp.option.vendor.bsdp.boot_image.index", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_default_boot_image_id, + { "Default Boot Image ID", "bootp.option.vendor.bsdp.default_boot_image_id", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_selected_boot_image_id, + { "Selected Boot Image ID", "bootp.option.vendor.bsdp.selected_boot_image_id", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_list, + { "Boot Image List", "bootp.option.vendor.bsdp.boot_image_list", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_image_desc, + { "Boot Image Description", "bootp.option.vendor.bsdp.boot_image.desc", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_name_len, + { "Boot Image Name Length", "bootp.option.vendor.bsdp.boot_image.name_len", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_name, + { "Boot Image Name", "bootp.option.vendor.bsdp.boot_image.name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_netboot_firmware, + { "NetBoot 1.0 Firmware", "bootp.option.vendor.bsdp.netboot_firmware", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_attributes_filter_list, + { "Boot Image Attributes Filter List", "bootp.option.vendor.bsdp.attributes_filter_list", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_attribute, + { "Boot Image Attribute", "bootp.option.vendor.bsdp.boot_image.attribute", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_attribute_install, + { "Install", "bootp.option.vendor.bsdp.boot_image.attribute.install", + FT_UINT16, BASE_HEX, VALS(o43_bsdp_boot_image_install_vals), 0x8000, + "Boot Image Attribute Install", HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_attribute_kind, + { "Kind", "bootp.option.vendor.bsdp.boot_image.attribute.kind", + FT_UINT16, BASE_HEX, VALS(o43_bsdp_boot_image_kind_vals), 0x7f00, + "Boot Image Attribute Kind", HFILL }}, + + { &hf_bootp_option43_bsdp_boot_image_attribute_reserved, + { "Reserved", "bootp.option.vendor.bsdp.boot_image.attribute.reserved", + FT_UINT16, BASE_HEX, NULL, 0x00ff, + "Boot Image Attribute Reserved", HFILL }}, + + { &hf_bootp_option43_bsdp_message_size, + { "Message Size", "bootp.option.vendor.bsdp.message_size", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_bootp_option_netbios_over_tcpip_name_server, { "NetBIOS over TCP/IP Name Server", "bootp.option.netbios_over_tcpip_name_server", @@ -6165,6 +7909,11 @@ proto_register_bootp(void) FT_STRINGZ, BASE_NONE, NULL, 0x0, "Option 60: Vendor class identifier", HFILL }}, + { &hf_bootp_option_vendor_class_data, + { "vendor-class-data", "bootp.option.vendor_class_data", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 60: Vendor class data", HFILL }}, + { &hf_bootp_option_novell_netware_ip_domain, { "Novell/Netware IP domain", "bootp.option.novell_netware_ip_domain", FT_STRINGZ, BASE_NONE, NULL, 0x0, @@ -6414,7 +8163,7 @@ proto_register_bootp(void) { &hf_bootp_option82_vi_enterprise, { "Enterprise", "bootp.option.agent_information_option.vi.enterprise", - FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0x0, + FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0x0, "Option 82:9 VI Enterprise", HFILL }}, { &hf_bootp_option82_vi_data_length, @@ -6457,23 +8206,38 @@ proto_register_bootp(void) FT_IPv4, BASE_NONE, NULL, 0x00, "Option 82:11 Server ID Override", HFILL }}, + { &hf_bootp_option82_relay_agent_id, + { "Relay Agent Identifier", "bootp.option.agent_information_option.relay_agent_id", + FT_BYTES, BASE_NONE, NULL, 0x00, + "Option 82:12 Relay Agent Identifier", HFILL }}, + { &hf_bootp_option82_link_selection_cisco, { "Link selection (Cisco proprietary)", "bootp.option.agent_information_option.link_selection_cisco", FT_IPv4, BASE_NONE, NULL, 0x00, "Option 82:150 Link selection (Cisco proprietary)", HFILL }}, { &hf_bootp_option82_vrf_name_vpn_id, - { "VRF name/VPN ID", "bootp.option.agent_information_option.vrf_name_vpn_id", + { "VRF name/VPN ID", "bootp.option.agent_information_option.vrf_name.vpn_id", FT_BYTES, BASE_NONE, NULL, 0x00, "Option 82:151 VRF name/VPN ID", HFILL }}, + { &hf_bootp_option82_vrf_name_global, + { "Global, default VPN", "bootp.option.agent_information_option.vrf_name.global", + FT_UINT8, BASE_DEC, NULL, 0x00, + "Option 82:151 Global, default VPN", HFILL }}, + + { &hf_bootp_option82_vrf_name, + { "VRF name", "bootp.option.agent_information_option.vrf_name", + FT_STRING, BASE_NONE, NULL, 0x00, + "Option 82:151 VRF name", HFILL }}, + { &hf_bootp_option82_vrf_name_vpn_id_oui, - { "VRF name/VPN ID OUI", "bootp.option.agent_information_option.vrf_name_vpn_id_oui", + { "VRF name/VPN ID OUI", "bootp.option.agent_information_option.vrf_name.vpn_id.oui", FT_UINT24, BASE_HEX, NULL, 0x00, "Option 82:151 VRF name/VPN ID OUI", HFILL }}, { &hf_bootp_option82_vrf_name_vpn_id_index, - { "VRF name/VPN ID Index", "bootp.option.agent_information_option.vrf_name_vpn_id_index", + { "VRF name/VPN ID Index", "bootp.option.agent_information_option.vrf_name.vpn_id.index", FT_UINT32, BASE_HEX, NULL, 0x00, "Option 82:151 VRF name/VPN ID Index", HFILL }}, @@ -6483,6 +8247,162 @@ proto_register_bootp(void) "Option 82:152 Server ID Override (Cisco proprietary)", HFILL }}, + { &hf_bootp_option_isns_functions, + { "iSNS Functions", "bootp.option.isns.functions", + FT_UINT16, BASE_HEX, NULL, 0x00, + "iSNS: the functions supported by the iSNS servers", HFILL }}, + + { &hf_bootp_option_isns_functions_enabled, + { "Function Fields Enabled", "bootp.option.isns.functions.enabled", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_FUNCTIONS_ENABLED, + "If set to zero, then the contents of all other iSNS Function fields MUST be ignored", HFILL }}, + + { &hf_bootp_option_isns_functions_dd_authorization, + { "Discovery Domain based Authorization", "bootp.option.isns.functions.dd_base_authorization", + FT_BOOLEAN, 16, TFS(&tfs_isns_function_dd_based_auth), F_ISNS_FUNCTIONS_DD_AUTH, + "If set to zero, then access authorization must be explicitly performed by each device", HFILL }}, + + { &hf_bootp_option_isns_functions_sec_policy_distibution, + { "Security Policy Distribution", "bootp.option.isns.functions.sec_policy_distribution", + FT_BOOLEAN, 16, TFS(&tfs_isns_functions_sec_distrib), F_ISNS_FUNCTIONS_SEC_POLICY, + NULL, HFILL }}, + + { &hf_bootp_option_isns_functions_reserved, + { "Reserved flags", "bootp.option.isns.functions.reserved", + FT_UINT16, BASE_HEX, NULL, F_ISNS_FUNCTIONS_RESERVED, + NULL, HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access, + { "Discovery Domain Access flags", "bootp.option.isns.discovery_domain_access", + FT_UINT16, BASE_HEX, NULL, 0x00, + "iSNS: the types of iSNS clients that are allowed to modify Discovery Domains", HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_enabled, + { "Discovery Domain Enabled", "bootp.option.isns.discovery_domain_access.enabled", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_DD_ACCESS_ENABLED, + "If set to zero, then the contents of the remainder of this field MUST be ignored", HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_control_node, + { "Control Node", "bootp.option.isns.discovery_domain_access_control.node", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_DD_ACCESS_CTRL_NODE, + NULL, HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_iscsi_target, + { "iSCSI Target", "bootp.option.isns.discovery_domain_access.iscsi_target", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_DD_ACCESS_ISCSI_TARGET, + NULL, HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_iscsi_inititator, + { "iSCSI Initiator", "bootp.option.isns.discovery_domain_access.iscsi_initiator", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_DD_ACCESS_ISCSI_INITIATOR, + NULL, HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_ifcp_target_port, + { "iFCP Target Port", "bootp.option.isns.discovery_domain_access.ifcp_target_port", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_DD_ACCESS_IFCP_TARGET_PORT, + NULL, HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_ifcp_initiator_port, + { "iFCP Initiator Port", "bootp.option.isns.discovery_domain_access.initiator_target_port", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_DD_ACCESS_IFCP_INITIATOR_PORT, + NULL, HFILL }}, + + { &hf_bootp_option_isns_discovery_domain_access_reserved, + { "Reserved Flags", "bootp.option.isns.discovery_domain_access.reserved", + FT_UINT16, BASE_HEX, NULL, F_ISNS_DD_ACCESS_RESERVED, + NULL, HFILL }}, + + { &hf_bootp_option_isns_administrative_flags, + { "Administrative Flags", "bootp.option.isns.administrative_flags", + FT_UINT16, BASE_HEX, NULL, 0x00, + "iSNS: administrative settings for the iSNS servers discovered through the DHCP query", HFILL }}, + + { &hf_bootp_option_isns_administrative_flags_enabled, + { "Administrative Flags Enabled", "bootp.option.isns.administrative_flags.enabled", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_ADMIN_FLAGS_ENABLED, + NULL, HFILL }}, + + { &hf_bootp_option_isns_administrative_flags_heartbeat, + { "Heartbeat", "bootp.option.isns.administrative_flags.heartbeat", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_ADMIN_FLAGS_HEARTBEAT, + NULL, HFILL }}, + + { &hf_bootp_option_isns_administrative_flags_management_scns, + { "Management SCNs", "bootp.option.isns.administrative_flags.management_scns", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_ADMIN_FLAGS_MANAGEMENT_SCNS, + NULL, HFILL }}, + + { &hf_bootp_option_isns_administrative_flags_default_dd, + { "Default Discovery Domain", "bootp.option.isns.administrative_flags.default_discovery_domain", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_ADMIN_FLAGS_DEFAULT_DD, + NULL, HFILL }}, + + { &hf_bootp_option_isns_administrative_flags_reserved, + { "Reserved Flags", "bootp.option.isns.administrative_flags.reserved", + FT_UINT16, BASE_HEX, NULL, F_ISNS_ADMIN_FLAGS_RESERVED, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap, + { "iSNS Server Security Bitmap", "bootp.option.isns.server_security_bitmap", + FT_UINT32, BASE_HEX, NULL, 0x00, + "iSNS: server security settings", HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_enabled, + { "Server Security Bitmap Enabled", "bootp.option.isns.server_security_bitmap.enabled", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), F_ISNS_SRV_SEC_BITMAP_ENABLED, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_ike_ipsec_enabled, + { "IKE/IPSec", "bootp.option.isns.server_security_bitmap.ike_ipsec_enabled", + FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), F_ISNS_SRV_SEC_BITMAP_IKE_IPSEC, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_main_mode, + { "Main Mode", "bootp.option.isns.server_security_bitmap.main_mode", + FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), F_ISNS_SRV_SEC_BITMAP_MAIN_MODE, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_aggressive_mode, + { "Aggresive Mode", "bootp.option.isns.server_security_bitmap.aggressive_mode", + FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), F_ISNS_SRV_SEC_BITMAP_AGGRESSIVE, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_pfs, + { "PFS", "bootp.option.isns.server_security_bitmap.pfs", + FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), F_ISNS_SRV_SEC_BITMAP_PFS, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_transport_mode, + { "Transport Mode", "bootp.option.isns.server_security_bitmap.transport_mode", + FT_BOOLEAN, 16, TFS(&tfs_preferred_no_preference), F_ISNS_SRV_SEC_BITMAP_TRASPORT_MODE, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_tunnel_mode, + { "Tunnel Mode", "bootp.option.isns.server_security_bitmap.tunnel_mode", + FT_BOOLEAN, 16, TFS(&tfs_preferred_no_preference), F_ISNS_SRV_SEC_BITMAP_TUNNEL_MODE, + NULL, HFILL }}, + + { &hf_bootp_option_isns_server_security_bitmap_reserved, + { "Reserved Flags", "bootp.option.isns.server_security_bitmap.reserved", + FT_UINT16, BASE_HEX, NULL, F_ISNS_SRV_SEC_BITMAP_RESERVED, + NULL, HFILL }}, + + { &hf_bootp_option_isns_primary_server_addr, + { "Primary Server Address", "bootp.option.isns.primary_server_addr", + FT_IPv4, BASE_NONE, NULL, 0x00, + "iSNS: IP address of the primary server", HFILL }}, + + { &hf_bootp_option_isns_heartbeat_originator_addr, + { "Heartbeat Originator Address", "bootp.option.isns.heartbeat_originator_addr", + FT_IPv4, BASE_NONE, NULL, 0x00, + "iSNS: IP address from which the iSNS heartbeat originates", HFILL }}, + + { &hf_bootp_option_isns_secondary_server_addr_list, + { "Secondary Server Address", "bootp.option.isns.secondary_server_addr", + FT_IPv4, BASE_NONE, NULL, 0x00, + "iSNS: a list of IP addresses of the secondary iSNS servers", HFILL }}, + + { &hf_bootp_option_novell_dss_string, { "Novell Directory Services Servers String", "bootp.option.novell_dss.string", FT_STRINGZ, BASE_NONE, NULL, 0x0, @@ -6598,6 +8518,16 @@ proto_register_bootp(void) FT_STRINGZ, BASE_NONE, NULL, 0x0, "Option 99: CA Value", HFILL }}, + { &hf_bootp_option_tz_pcode, + { "TZ PCode", "bootp.option.tz_pcode", + FT_STRING, BASE_NONE, NULL, 0x0, + "Option 100: TZ PCode", HFILL }}, + + { &hf_bootp_option_tz_tcode, + { "TZ TCode", "bootp.option.tz_tcode", + FT_STRING, BASE_NONE, NULL, 0x0, + "Option 101: TZ TCode", HFILL }}, + { &hf_bootp_option_netinfo_parent_server_address, { "NetInfo Parent Server Address", "bootp.option.netinfo_parent_server_address", FT_IPv4, BASE_NONE, NULL, 0x00, @@ -6658,10 +8588,55 @@ proto_register_bootp(void) FT_IPv4, BASE_NONE, NULL, 0x0, "Option 120: SIP Server Address", HFILL }}, - { &hf_bootp_option_sip_server_address_stringz, - { "SIP Server Address", "bootp.option.sip_server.address.stringz", - FT_STRINGZ, BASE_NONE, NULL, 0x0, - "Option 120: SIP Server Address", HFILL }}, + { &hf_bootp_option_classless_static_route, + { "Subnet/MaskWidth-Router", "bootp.option.classless_static_route.", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Option 121: Subnet/MaskWidth-Router", HFILL }}, + + { &hf_bootp_option_rfc3825_error, + { "Error", "bootp.option.rfc3825.error", + FT_UINT8, BASE_DEC, VALS(rfc3825_error_types), 0x0, + "Option 123: Error", HFILL }}, + + { &hf_bootp_option_rfc3825_latitude, + { "Latitude", "bootp.option.rfc3825.latitude", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + "Option 123: Latitude", HFILL }}, + + { &hf_bootp_option_rfc3825_longitude, + { "Longitude", "bootp.option.rfc3825.longitude", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + "Option 123: Longitude", HFILL }}, + + { &hf_bootp_option_rfc3825_latitude_res, + { "Latitude resolution", "bootp.option.rfc3825.latitude_res", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + "Option 123: Latitude resolution", HFILL }}, + + { &hf_bootp_option_rfc3825_longitude_res, + { "Longitude resolution", "bootp.option.rfc3825.longitude_res", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + "Option 123: Longitude resolution", HFILL }}, + + { &hf_bootp_option_rfc3825_altitude, + { "Altitude", "bootp.option.rfc3825.altitude", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + "Option 123: Altitude", HFILL }}, + + { &hf_bootp_option_rfc3825_altitide_res, + { "Altitude resolution", "bootp.option.rfc3825.altitide_res", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + "Option 123: Altitude resolution", HFILL }}, + + { &hf_bootp_option_rfc3825_altitude_type, + { "Altitude type", "bootp.option.rfc3825.altitude_type", + FT_UINT8, BASE_DEC, VALS(altitude_type_values), 0x0, + "Option 123: Altitude type", HFILL }}, + + { &hf_bootp_option_rfc3825_map_datum, + { "Map Datum", "bootp.option.cl_dss_id.option", + FT_UINT8, BASE_DEC, VALS(map_datum_type_values), 0x0, + "Option 123: Map Datum", HFILL }}, { &hf_bootp_option_cl_dss_id_option, { "DSS_ID Type", "bootp.option.cl_dss_id.option", @@ -6685,7 +8660,7 @@ proto_register_bootp(void) { &hf_bootp_option_vi_class_enterprise, { "Enterprise", "bootp.option.vi_class.enterprise", - FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0x00, + FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0x00, "Option 124: Enterprise", HFILL }}, { &hf_bootp_option_vi_class_data_length, @@ -6700,9 +8675,14 @@ proto_register_bootp(void) { &hf_bootp_option125_enterprise, { "Enterprise", "bootp.option.vi.enterprise", - FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0x00, + FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0x00, "Option 125: Enterprise", HFILL }}, + { &hf_bootp_option125_length, + { "Length", "bootp.option.vi.length", + FT_UINT8, BASE_DEC, NULL, 0x00, + "Option 125: Length", HFILL }}, + { &hf_bootp_option125_value, { "Value", "bootp.option.vi.value", FT_BYTES, BASE_NONE, NULL, 0x0, @@ -6735,7 +8715,7 @@ proto_register_bootp(void) { &hf_bootp_option125_tr111_device_manufacturer_oui, { "DeviceManufacturerOUI", "bootp.option.vi.tr111.device_manufacturer_oui", - FT_STRINGZ, BASE_NONE, NULL, 0x0, + FT_UINT24, BASE_OUI, NULL, 0x0, "Option 125:TR 111 1 DeviceManufacturerOUI", HFILL }}, { &hf_bootp_option125_tr111_device_serial_number, @@ -6770,7 +8750,7 @@ proto_register_bootp(void) { &hf_bootp_option125_cl_option_request, { "Option Request", "bootp.option.vi.cl.option_request", - FT_UINT8, BASE_DEC, NULL, 0x0, + FT_BYTES, SEP_SPACE, NULL, 0x0, "Option 125:CL 1 Option Request", HFILL }}, { &hf_bootp_option125_cl_tftp_server_addresses, @@ -6808,11 +8788,131 @@ proto_register_bootp(void) FT_IPv4, BASE_NONE, NULL, 0x00, "Option 138: CAPWAP Access Controllers", HFILL }}, + { &hf_bootp_option_andsf_server, + { "ANDSF Server", "bootp.option.andsf_server", + FT_IPv4, BASE_NONE, NULL, 0x00, + "ANDSF (Access Network Discovery and Selection Function) Server", HFILL }}, + + { &hf_bootp_option_forcerenew_nonce_algo, + { "Algorithm", "bootp.option.forcerenew_nonce.algorithm", + FT_UINT8, BASE_DEC, VALS(forcerenew_nonce_algo_vals), 0x00, + "Forcenew Nonce Algorithm", HFILL }}, + + { &hf_bootp_option_rdnss_reserved, + { "Reserved", "bootp.option.rdnss.reserved", + FT_UINT8, BASE_HEX, NULL, 0xfc, + "RDNSS Reserved", HFILL }}, + + { &hf_bootp_option_rdnss_pref, + { "Preference", "bootp.option.rdnss.preference", + FT_UINT8, BASE_DEC, VALS(rdnss_pref_vals), 0x03, + "RDNSS (Recursive DNS Server) Preference", HFILL }}, + + { &hf_bootp_option_rdnss_prim_dns_server, + { "Primary DNS", "bootp.option.rdnss.primary_dns", + FT_IPv4, BASE_NONE, NULL, 0x00, + "RDNSS Primary DNS-recursive-name-server's IPv4 address", HFILL }}, + + { &hf_bootp_option_rdnss_sec_dns_server, + { "Secondary DNS", "bootp.option.rdnss.secondary_dns", + FT_IPv4, BASE_NONE, NULL, 0x00, + "RDNSS Secondary DNS-recursive-name-server's IPv4 address", HFILL }}, + + { &hf_bootp_option_rdnss_domain, + { "Domains and networks", "bootp.option.rdnss.domain", + FT_STRING, BASE_NONE, NULL, 0x00, + "RDNSS Domains and networks", HFILL }}, + { &hf_bootp_option_tftp_server_address, { "TFTP Server Address", "bootp.option.tftp_server_address", FT_IPv4, BASE_NONE, NULL, 0x00, "Option 150: TFTP Server Address", HFILL }}, + { &hf_bootp_option_bulk_lease_status_code, + { "Status Code", "bootp.option.bulk_lease.status_code", + FT_UINT8, BASE_DEC, VALS(bulk_lease_dhcp_status_code_vals), 0x00, + "DHCPv4 Bulk Leasequery Status Code", HFILL }}, + + { &hf_bootp_option_bulk_lease_status_message, + { "Status Code Message", "bootp.option.bulk_lease.status_code_message", + FT_STRING, BASE_NONE, NULL, 0x00, + "DHCPv4 Bulk Leasequery Status Code Message", HFILL }}, + + { &hf_bootp_option_bulk_lease_base_time, + { "Base Time", "bootp.option.bulk_lease.base_time", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00, + "DHCPv4 Bulk Leasequery Base Time", HFILL }}, + + { &hf_bootp_option_bulk_lease_start_time_of_state, + { "Start Time Of State", "bootp.option.bulk_lease.start_time_of_state", + FT_UINT32, BASE_DEC, NULL, 0x00, + "DHCPv4 Bulk Leasequery Start Time Of State", HFILL }}, + + { &hf_bootp_option_bulk_lease_query_start, + { "Query Start Time", "bootp.option.bulk_lease.query_start_time", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00, + "DHCPv4 Bulk Leasequery Query Start Time", HFILL }}, + + { &hf_bootp_option_bulk_lease_query_end, + { "Query End Time", "bootp.option.bulk_lease.query_end_time", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00, + "DHCPv4 Bulk Leasequery Query End Time", HFILL }}, + + { &hf_bootp_option_bulk_lease_dhcp_state, + { "Dhcp State", "bootp.option.bulk_lease.dhcp_state", + FT_UINT8, BASE_DEC, VALS(bulk_lease_dhcp_state_vals), 0x00, + "DHCPv4 Bulk Leasequery Dhcp State", HFILL }}, + + { &hf_bootp_option_bulk_lease_data_source, + { "Data Source", "bootp.option.bulk_lease.data_source", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_bulk_lease_data_source), 0x00, + "DHCPv4 Bulk Leasequery Data Source", HFILL }}, + + { &hf_bootp_option_pcp_list_length, + { "List-Length", "bootp.option.pcp.list_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Port Control Protocol (PCP) List Length", HFILL }}, + + { &hf_bootp_option_pcp_server, + { "PCP Server", "bootp.option.pcp.server", + FT_IPv4, BASE_NONE, NULL, 0x0, + "Port Control Protocol (PCP) Server", HFILL }}, + + { &hf_bootp_option_portparams_offset, + { "Offset", "bootp.option.portparams.offset", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Port Set ID (PSID) offset", HFILL }}, + + { &hf_bootp_option_portparams_psid_length, + { "PSID-Length", "bootp.option.portparams.psid_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Port Set ID (PSID) Length", HFILL }}, + + { &hf_bootp_option_portparams_psid, + { "PSID", "bootp.option.portparams.psid", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Port Set ID (PSID)", HFILL }}, + + { &hf_bootp_option_mudurl, + { "MUDURL", "bootp.option.mudurl", + FT_STRING, BASE_NONE, NULL, 0x0, + "Option 161: MUDURL", HFILL }}, + + { &hf_bootp_option_pxe_config_file, + { "PXELINUX configuration file", "bootp.option.pxe_config_file", + FT_STRING, BASE_NONE, NULL, 0x0, + "Option 209: PXE Configuration File", HFILL }}, + + { &hf_bootp_option_pxe_path_prefix, + { "PXELINUX path prefix", "bootp.option.pxe_path_prefix", + FT_STRING, BASE_NONE, NULL, 0x0, + "Option 210: PXE Path Prefix", HFILL }}, + + { &hf_bootp_option_captive_portal, + { "Captive Portal", "bootp.option.captive_portal", + FT_STRING, BASE_NONE, NULL, 0x0, + "The contact URI for the captive portal that the user should connect to", HFILL }}, + { &hf_bootp_option_6RD_ipv4_mask_len, { "6RD IPv4 Mask Length", "bootp.option.6RD.ipv4_mask_len", FT_UINT8, BASE_DEC, NULL, 0x0, @@ -6848,6 +8948,160 @@ proto_register_bootp(void) FT_UINT8, BASE_DEC, NULL, 0x0, "Option 255: End (Overload)", HFILL }}, + { &hf_bootp_vendor_unknown_suboption, + { "Option 125 Suboption", "bootp.vendor.suboption", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_suboption_data, + { "Data", "bootp.vendor.data", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_pc_ietf_ccc_suboption, + { "Suboption", "bootp.vendor.pc.ietf_ccc.suboption", + FT_UINT8, BASE_DEC, VALS(pkt_draft5_ccc_opt_vals), 0x0, + NULL, HFILL }}, + + { &hf_bootp_pc_i05_ccc_suboption, + { "Suboption", "bootp.vendor.pc.i05_ccc.suboption", + FT_UINT8, BASE_DEC, VALS(pkt_i05_ccc_opt_vals), 0x0, + NULL, HFILL }}, + + { &hf_bootp_cl_ietf_ccc_dev_realm_unc_key_nom_timeout, + { "pktcMtaDevRealmUnsolicitedKeyNomTimeout", "bootp.cl.ietf_ccc.dev_realm_unc_key_nom_timeout", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_timeout, + { "pktcMtaDevRealmUnsolicitedKeyMaxTimeout", "bootp.cl.ietf_ccc.dev_realm_unc_key_max_timeout", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_cl_ietf_ccc_dev_realm_unc_key_max_retries, + { "pktcMtaDevRealmUnsolicitedKeyMaxRetries", "bootp.cl.ietf_ccc.dev_realm_unc_key_max_retries", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_cl_ietf_ccc_dev_prov_unc_key_nom_timeout, + { "pktcMtaDevProvUnsolicitedKeyNomTimeout", "bootp.cl.ietf_ccc.dev_prov_unc_key_nom_timeout", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_timeout, + { "pktcMtaDevProvUnsolicitedKeyMaxTimeout", "bootp.cl.ietf_ccc.dev_prov_unc_key_max_timeout", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_cl_ietf_ccc_dev_prov_unc_key_max_retries, + { "pktcMtaDevProvUnsolicitedKeyMaxRetries", "bootp.cl.ietf_ccc.dev_prov_unc_key_max_retries", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_bootp_ccc_ietf_sec_tkt_pc_provision_server, + { "Invalidate PacketCable Provisioning Server", "bootp.ccc.ietf.sec_tkt.pc_provision_server", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x01, + NULL, HFILL }}, + + { &hf_bootp_ccc_ietf_sec_tkt_all_pc_call_management, + { "Invalidate All PacketCable Call Management Servers", "bootp.ccc.ietf.sec_tkt.all_pc_call_management", + FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x02, + NULL, HFILL }}, + + { &hf_bootp_option242_avaya, + { "Private/Avaya IP Telephone", "bootp.option.vendor.avaya", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: Private/Avaya IP Telephone", HFILL }}, + + { &hf_bootp_option242_avaya_tlssrvr, + { "TLSSRVR", "bootp.option.vendor.avaya.tlssrvr", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: TLSSRVR (HTTPS server(s) to download configuration)", HFILL }}, + + { &hf_bootp_option242_avaya_httpsrvr, + { "HTTPSRVR", "bootp.option.vendor.avaya.httpsrvr", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: HTTPSRVR (HTTP server(s) to download configuration)", HFILL }}, + + { &hf_bootp_option242_avaya_httpdir, + { "HTTPDIR", "bootp.option.vendor.avaya.httpdir", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: HTTPDIR (Path to configuration files)", HFILL }}, + + { &hf_bootp_option242_avaya_static, + { "STATIC", "bootp.option.vendor.avaya.static", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: STATIC (Static programming override flag)", HFILL }}, + + { &hf_bootp_option242_avaya_mcipadd, + { "MCIPADD", "bootp.option.vendor.avaya.mcipadd", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: MCIPADD (List of CM server(s))", HFILL }}, + + { &hf_bootp_option242_avaya_dot1x, + { "DOT1X", "bootp.option.vendor.avaya.dot1x", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: DOT1X (802.1X Supplicant operation mode)", HFILL }}, + + { &hf_bootp_option242_avaya_icmpdu, + { "ICMPDU", "bootp.option.vendor.avaya.icmpdu", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: ICMPDU (ICMP Destination Unreachable processing)", HFILL }}, + + { &hf_bootp_option242_avaya_icmpred, + { "ICMPRED", "bootp.option.vendor.avaya.icmpred", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: ICMPRED (ICMP Redirect handling)", HFILL }}, + + { &hf_bootp_option242_avaya_l2q, + { "L2Q", "bootp.option.vendor.avaya.l2q", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: L2Q (Controls 802.1Q tagging)", HFILL }}, + + { &hf_bootp_option242_avaya_l2qvlan, + { "L2QVLAN", "bootp.option.vendor.avaya.l2qvlan", + FT_INT32, BASE_DEC, NULL, 0x0, + "Option 242: L2QVLAN (VLAN ID)", HFILL }}, + + { &hf_bootp_option242_avaya_loglocal, + { "LOGLOCAL", "bootp.option.vendor.avaya.loglocal", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: LOGLOCAL (Log level)", HFILL }}, + + { &hf_bootp_option242_avaya_phy1stat, + { "PHY1STAT", "bootp.option.vendor.avaya.phy1stat", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: PHY1STAT (Interface configuration)", HFILL }}, + + { &hf_bootp_option242_avaya_phy2stat, + { "PHY2STAT", "bootp.option.vendor.avaya.phy2stat", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: PHY2STAT (Interface configuration)", HFILL }}, + + { &hf_bootp_option242_avaya_procpswd, + { "PROCPSWD", "bootp.option.vendor.avaya.procpswd", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: PROCPSWD (Security string used to access local procedures)", HFILL }}, + + { &hf_bootp_option242_avaya_procstat, + { "PROCSTAT", "bootp.option.vendor.avaya.procstat", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: PROCSTAT (Local (dialpad) Administrative access)", HFILL }}, + + { &hf_bootp_option242_avaya_snmpadd, + { "SNMPADD", "bootp.option.vendor.avaya.snmpadd", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: SNMPADD (Allowable source IP Address(es) for SNMP queries)", HFILL }}, + + { &hf_bootp_option242_avaya_snmpstring, + { "SNMPSTRING", "bootp.option.vendor.avaya.snmpstring", + FT_STRINGZ, BASE_NONE, NULL, 0x0, + "Option 242: SNMPSTRING (SNMP community string)", HFILL }}, + + { &hf_bootp_option242_avaya_vlantest, + { "VLANTEST", "bootp.option.vendor.avaya.vlantest", + FT_INT32, BASE_DEC, NULL, 0x0, + "Option 242: VLANTEST (Timeout in seconds)", HFILL }}, }; static uat_field_t bootp_uat_flds[] = { @@ -6867,18 +9121,35 @@ proto_register_bootp(void) &ett_bootp_option82_suboption, &ett_bootp_option82_suboption9, &ett_bootp_option125_suboption, + &ett_bootp_option125_tr111_suboption, + &ett_bootp_option125_cl_suboption, + &ett_bootp_option242_suboption, &ett_bootp_fqdn, + &ett_bootp_filename_option, + &ett_bootp_server_hostname, + &ett_bootp_fqdn_flags, + &ett_bootp_isns_functions, + &ett_bootp_isns_discovery_domain_access, + &ett_bootp_isns_administrative_flags, + &ett_bootp_isns_server_security_bitmap, + &ett_bootp_isns_secondary_server_addr, + &ett_bootp_o43_bsdp_boot_image, + &ett_bootp_o43_bsdp_attributes, + &ett_bootp_o43_bsdp_image_desc_list, + &ett_bootp_o43_bsdp_image_desc, + &ett_bootp_o43_bsdp_attributes_flags, + &ett_bootp_option158_pcp_list, }; static ei_register_info ei[] = { { &ei_bootp_bad_length, { "bootp.bad_length", PI_PROTOCOL, PI_ERROR, "length isn't 0", EXPFILL }}, + { &ei_bootp_bad_bitfield, { "bootp.bad_bitfield", PI_PROTOCOL, PI_ERROR, "Bogus bitfield", EXPFILL }}, { &ei_bootp_missing_subopt_length, { "bootp.missing_subopt_length", PI_PROTOCOL, PI_ERROR, "no room left in option for suboption length", EXPFILL }}, { &ei_bootp_missing_subopt_value, { "bootp.missing_subopt_value", PI_PROTOCOL, PI_ERROR, "no room left in option for suboption value", EXPFILL }}, { &ei_bootp_mal_duid, { "bootp.malformed.duid", PI_PROTOCOL, PI_ERROR, "DUID: malformed option", EXPFILL }}, { &hf_bootp_opt_overload_file_end_missing, { "bootp.option.option_overload.file_end_missing", PI_PROTOCOL, PI_ERROR, "file overload end option missing", EXPFILL }}, { &hf_bootp_opt_overload_sname_end_missing, { "bootp.option.option_overload.sname_end_missing", PI_PROTOCOL, PI_ERROR, "sname overload end option missing", EXPFILL }}, { &hf_bootp_subopt_unknown_type, { "bootp.subopt.unknown_type", PI_PROTOCOL, PI_ERROR, "ERROR, please report: Unknown subopt type handler", EXPFILL }}, - { &ei_bootp_option77_user_class_malformed, { "bootp.option.user_class.malformed", PI_PROTOCOL, PI_ERROR, "User Class Information: malformed option", EXPFILL }}, { &ei_bootp_option_civic_location_bad_cattype, { "bootp.option.civic_location.bad_cattype", PI_PROTOCOL, PI_ERROR, "Error with CAType", EXPFILL }}, { &ei_bootp_option_dhcp_name_service_invalid, { "bootp.option.dhcp_name_service.invalid", PI_PROTOCOL, PI_ERROR, "Invalid Name Service", EXPFILL }}, { &ei_bootp_option_sip_server_address_encoding, { "bootp.option.sip_server_address.encoding", PI_PROTOCOL, PI_ERROR, "RFC 3361 defines only 0 and 1 for Encoding byte", EXPFILL }}, @@ -6886,16 +9157,43 @@ proto_register_bootp(void) { &ei_bootp_option125_enterprise_malformed, { "bootp.option.enterprise.malformed", PI_PROTOCOL, PI_ERROR, "no room left in option for enterprise data", EXPFILL }}, { &ei_bootp_option_6RD_malformed, { "bootp.option.6RD.malformed", PI_PROTOCOL, PI_ERROR, "6RD: malformed option", EXPFILL }}, { &ei_bootp_option82_vi_cl_tag_unknown, { "bootp.option.option.vi.cl.tag_unknown", PI_PROTOCOL, PI_ERROR, "Unknown tag", EXPFILL }}, + { &ei_bootp_option_parse_err, { "bootp.option.parse_err", PI_PROTOCOL, PI_ERROR, "Parse error", EXPFILL }}, + { &ei_bootp_nonstd_option_data, { "bootp.option.nonstd_data", PI_PROTOCOL, PI_NOTE, "Non standard compliant option data", EXPFILL }}, { &ei_bootp_suboption_invalid, { "bootp.suboption_invalid", PI_PROTOCOL, PI_ERROR, "Invalid suboption", EXPFILL }}, { &ei_bootp_secs_le, { "bootp.secs_le", PI_PROTOCOL, PI_NOTE, "Seconds elapsed appears to be encoded as little-endian", EXPFILL }}, { &ei_bootp_end_option_missing, { "bootp.end_option_missing", PI_PROTOCOL, PI_ERROR, "End option missing", EXPFILL }}, + { &ei_bootp_client_address_not_given, { "bootp.client_address_not_given", PI_PROTOCOL, PI_NOTE, "Client address not given", EXPFILL }}, + { &ei_bootp_server_name_overloaded_by_dhcp, { "bootp.server_name_overloaded_by_dhcp", PI_PROTOCOL, PI_NOTE, "Server name option overloaded by DHCP", EXPFILL }}, + { &ei_bootp_boot_filename_overloaded_by_dhcp, { "bootp.boot_filename_overloaded_by_dhcp", PI_PROTOCOL, PI_NOTE, "Boot file name option overloaded by DHCP", EXPFILL }}, + { &ei_bootp_option_isns_ignored_bitfield, { "bootp.option.isns.ignored_bitfield", PI_PROTOCOL, PI_NOTE, "Enabled field is not set - non-zero bitmask ignored", EXPFILL }}, + { &ei_bootp_option242_avaya_l2qvlan_invalid, { "bootp.option.vendor.avaya.l2qvlan.invalid", PI_PROTOCOL, PI_ERROR, "Option 242 (L2QVLAN) invalid", EXPFILL }}, + { &ei_bootp_option242_avaya_vlantest_invalid, { "bootp.option.vendor.avaya.vlantest.invalid", PI_PROTOCOL, PI_ERROR, "Option 242 (avaya vlantest) invalid", EXPFILL }} + }; + + static tap_param bootp_stat_params[] = { + { PARAM_FILTER, "filter", "Filter", NULL, TRUE } + }; + + static stat_tap_table_ui bootp_stat_table = { + REGISTER_STAT_GROUP_UNSORTED, + "DHCP (BOOTP) Statistics", + "bootp", + "bootp,stat", + bootp_stat_init, + bootp_stat_packet, + bootp_stat_reset, + NULL, + NULL, + sizeof(bootp_stat_fields)/sizeof(stat_tap_table_item), bootp_stat_fields, + sizeof(bootp_stat_params)/sizeof(tap_param), bootp_stat_params, + NULL, + 0 }; module_t *bootp_module; expert_module_t* expert_bootp; - proto_bootp = proto_register_protocol("Bootstrap Protocol", "BOOTP/DHCP", - "bootp"); + proto_bootp = proto_register_protocol("Bootstrap Protocol", "BOOTP/DHCP", "bootp"); proto_register_field_array(proto_bootp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); bootp_dhcp_tap = register_tap("bootp"); @@ -6903,8 +9201,14 @@ proto_register_bootp(void) expert_bootp = expert_register_protocol(proto_bootp); expert_register_field_array(expert_bootp, ei, array_length(ei)); - /* register init routine to setup the custom bootp options */ + bootp_option_table = register_dissector_table("bootp.option", "BOOTP Options", proto_bootp, FT_UINT8, BASE_DEC); + bootp_vendor_id_subdissector = register_heur_dissector_list("bootp.vendor_id", proto_bootp); + bootp_vendor_info_subdissector = register_heur_dissector_list("bootp.vendor_info", proto_bootp); + bootp_enterprise_table = register_dissector_table("bootp.enterprise", "V-I Vendor Specific Enterprise", proto_bootp, FT_UINT32, BASE_DEC); + + /* register init/cleanup routine to handle the custom bootp options */ register_init_routine(&bootp_init_protocol); + register_cleanup_routine(&bootp_cleanup_protocol); /* Allow dissector to find be found by name. */ bootp_handle = register_dissector("bootp", dissect_bootp, proto_bootp); @@ -6929,38 +9233,120 @@ proto_register_bootp(void) 10, &pkt_ccc_option); + prefs_register_enum_preference(bootp_module, "uuid.endian", + "Endianness of UUID", + "Endianness applied to UUID fields", + &bootp_uuid_endian, + bootp_uuid_endian_vals, + FALSE); + prefs_register_obsolete_preference(bootp_module, "displayasstring"); bootp_uat = uat_new("Custom BootP/DHCP Options (Excl. suboptions)", - sizeof(uat_bootp_record_t), /* record size */ - "custom_bootp", /* filename */ - TRUE, /* from_profile */ - (void**) &uat_bootp_records,/* data_ptr */ - &num_bootp_records_uat, /* numitems_ptr */ - UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ - NULL, /* help */ - uat_bootp_record_copy_cb, /* copy callback */ - uat_bootp_record_update_cb, /* update callback */ - uat_bootp_record_free_cb, /* free callback */ + sizeof(uat_bootp_record_t), /* record size */ + "custom_bootp", /* filename */ + TRUE, /* from_profile */ + &uat_bootp_records, /* data_ptr */ + &num_bootp_records_uat, /* numitems_ptr */ + UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ + NULL, /* help */ + uat_bootp_record_copy_cb, /* copy callback */ + uat_bootp_record_update_cb, /* update callback */ + uat_bootp_record_free_cb, /* free callback */ NULL, /* post update callback */ + NULL, /* reset callback */ bootp_uat_flds); /* UAT field definitions */ prefs_register_uat_preference(bootp_module, - "custom_bootp_table", - "Custom BootP/DHCP Options (Excl. suboptions)", - "Custom BootP/DHCP Options (Excl. suboptions)", - bootp_uat); + "custom_bootp_table", + "Custom BootP/DHCP Options (Excl. suboptions)", + "Custom BootP/DHCP Options (Excl. suboptions)", + bootp_uat); + + register_stat_tap_table_ui(&bootp_stat_table); } void proto_reg_handoff_bootp(void) { - dissector_add_uint("udp.port", UDP_PORT_BOOTPS, bootp_handle); - dissector_add_uint("udp.port", UDP_PORT_BOOTPC, bootp_handle); + range_t *bootopt_basictype_range; + + dissector_add_uint_range_with_preference("udp.port", BOOTP_UDP_PORT_RANGE, bootp_handle); + + /* Create dissection function handles for all BOOTP options */ + bootpopt_basic_handle = create_dissector_handle( dissect_bootpopt_basic_type, -1 ); + range_convert_str(wmem_epan_scope(), &bootopt_basictype_range, BOOTP_OPTION_BASICTYPE_RANGE, 0xFF); + dissector_add_uint_range("bootp.option", bootopt_basictype_range, bootpopt_basic_handle); + + dissector_add_uint("bootp.option", 21, create_dissector_handle( dissect_bootpopt_policy_filter, -1 )); + dissector_add_uint("bootp.option", 33, create_dissector_handle( dissect_bootpopt_static_route, -1 )); + dissector_add_uint("bootp.option", 43, create_dissector_handle( dissect_bootpopt_vendor_specific_info, -1 )); + dissector_add_uint("bootp.option", 52, create_dissector_handle( dissect_bootpopt_option_overload, -1 )); + dissector_add_uint("bootp.option", 53, create_dissector_handle( dissect_bootpopt_dhcp, -1 )); + dissector_add_uint("bootp.option", 55, create_dissector_handle( dissect_bootpopt_param_request_list, -1 )); + dissector_add_uint("bootp.option", 60, create_dissector_handle( dissect_bootpopt_vendor_class_identifier, -1 )); + dissector_add_uint("bootp.option", 61, create_dissector_handle( dissect_bootpopt_client_identifier, -1 )); + dissector_add_uint("bootp.option", 63, create_dissector_handle( dissect_bootpopt_netware_ip, -1 )); + dissector_add_uint("bootp.option", 77, create_dissector_handle( dissect_bootpopt_user_class_information, -1 )); + dissector_add_uint("bootp.option", 78, create_dissector_handle( dissect_bootpopt_slp_directory_agent, -1 )); + dissector_add_uint("bootp.option", 79, create_dissector_handle( dissect_bootpopt_slp_service_scope, -1 )); + dissector_add_uint("bootp.option", 81, create_dissector_handle( dissect_bootpopt_client_full_domain_name, -1 )); + dissector_add_uint("bootp.option", 82, create_dissector_handle( dissect_bootpopt_relay_agent_info, -1 )); + dissector_add_uint("bootp.option", 83, create_dissector_handle( dissect_bootpopt_isns, -1 )); + dissector_add_uint("bootp.option", 85, create_dissector_handle( dissect_bootpopt_novell_servers, -1 )); + dissector_add_uint("bootp.option", 90, create_dissector_handle( dissect_bootpopt_dhcp_authentication, -1 )); + dissector_add_uint("bootp.option", 94, create_dissector_handle( dissect_bootpopt_client_network_interface_id, -1 )); + dissector_add_uint("bootp.option", 97, create_dissector_handle( dissect_bootpopt_client_identifier_uuid, -1 )); + dissector_add_uint("bootp.option", 99, create_dissector_handle( dissect_bootpopt_civic_location, -1 )); + dissector_add_uint("bootp.option", 117, create_dissector_handle( dissect_bootpopt_name_server_search, -1 )); + dissector_add_uint("bootp.option", 119, create_dissector_handle( dissect_bootpopt_dhcp_domain_search, -1 )); + dissector_add_uint("bootp.option", 120, create_dissector_handle( dissect_bootpopt_sip_servers, -1 )); + dissector_add_uint("bootp.option", 121, create_dissector_handle( dissect_bootpopt_classless_static_route, -1 )); + /* The PacketCable CCC option number can vary. Still handled through preference */ + dissector_add_uint("bootp.option", 122, create_dissector_handle( dissect_bootpopt_packetcable_ccc, -1 )); + + dissector_add_uint("bootp.option", 123, create_dissector_handle( dissect_bootpopt_coordinate_based_location, -1 )); + dissector_add_uint("bootp.option", 124, create_dissector_handle( dissect_bootpopt_vi_vendor_class, -1 )); + dissector_add_uint("bootp.option", 125, create_dissector_handle( dissect_bootpopt_vi_vendor_specific_info, -1 )); + dissector_add_uint("bootp.option", 145, create_dissector_handle( dissect_bootpopt_forcerenew_nonce, -1 )); + dissector_add_uint("bootp.option", 146, create_dissector_handle( dissect_bootpopt_rdnss, -1 )); + dissector_add_uint("bootp.option", 151, create_dissector_handle( dissect_bootpopt_bulk_lease_status_code, -1 )); + dissector_add_uint("bootp.option", 152, create_dissector_handle( dissect_bootpopt_bulk_lease_base_time, -1 )); + dissector_add_uint("bootp.option", 154, create_dissector_handle( dissect_bootpopt_bulk_lease_query_start, -1 )); + dissector_add_uint("bootp.option", 155, create_dissector_handle( dissect_bootpopt_bulk_lease_query_end, -1 )); + dissector_add_uint("bootp.option", 158, create_dissector_handle( dissect_bootpopt_pcp_server, -1 )); + dissector_add_uint("bootp.option", 159, create_dissector_handle( dissect_bootpopt_portparams, -1 )); + dissector_add_uint("bootp.option", 160, create_dissector_handle( dissect_bootpopt_dhcp_captive_portal, -1 )); + dissector_add_uint("bootp.option", 212, create_dissector_handle( dissect_bootpopt_6RD_option, -1 )); + dissector_add_uint("bootp.option", 242, create_dissector_handle( dissect_bootpopt_avaya_ip_telephone, -1 )); + dissector_add_uint("bootp.option", 249, create_dissector_handle( dissect_bootpopt_classless_static_route, -1 )); + + /* Create heuristic dissection for BOOTP vendor class id */ + heur_dissector_add( "bootp.vendor_id", dissect_packetcable_mta_vendor_id_heur, "PacketCable MTA", "packetcable_mta_bootp", proto_bootp, HEURISTIC_ENABLE ); + heur_dissector_add( "bootp.vendor_id", dissect_packetcable_cm_vendor_id_heur, "PacketCable CM", "packetcable_cm_bootp", proto_bootp, HEURISTIC_ENABLE ); + heur_dissector_add( "bootp.vendor_id", dissect_packetcable_bsdpd_vendor_id_heur, "PacketCable BSDPD", "packetcable_bsdpd_bootp", proto_bootp, HEURISTIC_ENABLE ); + + /* Create heuristic dissection for BOOTP vendor specific information */ + + /* Note that this is a rather weak (permissive) heuristic, + it's put first so it ends up at the end of the list, I guess this is OK. + Add any stronger (less permissive) heuristics after this! + XXX - Should we just disable by default? */ + heur_dissector_add( "bootp.vendor_info", dissect_alcatel_lucent_vendor_info_heur, "Alcatel-Lucent", "alcatel_lucent_bootp", proto_bootp, HEURISTIC_ENABLE ); + + heur_dissector_add( "bootp.vendor_info", dissect_pxeclient_vendor_info_heur, "PXEClient", "pxeclient_bootp", proto_bootp, HEURISTIC_ENABLE ); + heur_dissector_add( "bootp.vendor_info", dissect_cablelabs_vendor_info_heur, "CableLabs", "cablelabs_bootp", proto_bootp, HEURISTIC_ENABLE ); + heur_dissector_add( "bootp.vendor_info", dissect_aruba_ap_vendor_info_heur, ARUBA_AP, "aruba_ap_bootp", proto_bootp, HEURISTIC_ENABLE ); + heur_dissector_add( "bootp.vendor_info", dissect_aruba_instant_ap_vendor_info_heur, ARUBA_INSTANT_AP, "aruba_instant_ap_bootp", proto_bootp, HEURISTIC_ENABLE ); + heur_dissector_add( "bootp.vendor_info", dissect_packetcable_bsdpd_vendor_info_heur, "PacketCable BSDPD", "packetcable_bsdpd_info_bootp", proto_bootp, HEURISTIC_ENABLE ); + + /* Create dissection function handles for BOOTP Enterprise dissection */ + dissector_add_uint("bootp.enterprise", 4491, create_dissector_handle( dissect_vendor_cl_suboption, -1 )); + dissector_add_uint("bootp.enterprise", 3561, create_dissector_handle( dissect_vendor_tr111_suboption, -1 )); } /* - * Editor modelines - http://www.wireshark.org/tools/modelines.html + * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8