dissectors: more SPDX license convertions.
[metze/wireshark/wip.git] / epan / dissectors / packet-bootp.c
index 02c2361585e3be0710db9165576a5a520e409e34..2bc1f50dba5e2d3a34a6fb3460dfd68409229a89 100644 (file)
@@ -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 <jerome.laforge [AT] gmail.com>
  *
- * $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
  * 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
  *     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 <gerald@wireshark.org>
  * 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
  */
 
 /*
 #include "config.h"
 
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
 
 #include <epan/packet.h>
 #include <epan/exceptions.h>
 #include <epan/addr_resolv.h>
 #include <epan/prefs.h>
 #include <epan/tap.h>
+#include <epan/stat_tap_ui.h>
 #include <epan/arptypes.h>
-#include <epan/sminmpec.h>
+#include <epan/addr_resolv.h>
 #include <epan/expert.h>
 #include <epan/uat.h>
-#include <epan/wmem/wmem.h>
-
+#include <epan/strutil.h>
+#include <wsutil/str_util.h>
+#include <wsutil/strtoi.h>
 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<BOOTP_OPT_NUM; i++)
+       memcpy(bootp_opt, default_bootp_opt, sizeof(bootp_opt));
+
+       if ((num_bootp_records_uat > 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