1 /* packet-dhcpv6.c
2  * Routines for DHCPv6 packet disassembly
3  * Copyright 2004, Nicolas DICHTEL - 6WIND - <nicolas.dichtel@6wind.com>
4  * Jun-ichiro itojun Hagino <itojun@iijlab.net>
5  * IItom Tsutomu MIENO <iitom@utouto.com>
6  * SHIRASAKI Yasuhiro <yasuhiro@gnome.gr.jp>
7  * Tony Lindstrom <tony.lindstrom@ericsson.com>
8  * Copyright 2012, Jerome LAFORGE <jerome.laforge@gmail.com>
9  *
10  * The information used comes from:
11  * RFC1034 (DOMAIN NAMES - CONCEPTS AND FACILITIES)
12  * RFC1035 (DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION)
13  * RFC1535 (A Security Problem with DNS) [clear definition of Partial names]
14  * RFC2181 (Clarifications to the DNS Specification)
15  * RFC3319 (SIP options)
16  * RFC3633 (Prefix options) replaces draft-ietf-dhc-dhcpv6-opt-lifetime-00
17  * RFC3646 (DNS Configuration options for DHCP for IPv6 (DHCPv6))
18  * RFC3898 (NIS options)
19  * RFC4075 (SNTP - Configuration Option for DHCPv6)
20                  - replaces "draft-ietf-dhc-dhcpv6-opt-timeconfig-03"
21  * RFC4242 (Information Refresh Time Option)
22  * RFC4280 (Broadcast and Multicast Control Servers Options)
23  * RFC4649 (Remote ID option)
24  * RFC4704 (DHCPv6 Client FQDN Option)
25  * RFC5007 (DHCPv6 Leasequery)
26  * RFC5417 (CAPWAP Access Controller DHCP Option)
27  * RFC5460 (DHCPv6 Bulk Leasequery)
28  * RFC5908 (Network Time Protocol (NTP) Server Option)
29  * RFC6334 (Dual-Stack Lite Option)
30  * RFC6603 (Prefix Exclude Option)
31  * RFC7598 (Configuration of Softwire Address and Port-Mapped Clients)
32  * RFC8415 (Dynamic Host Configuration Protocol for IPv6 (DHCPv6))
33  * RFC8520 (Manufacturer Usage Descriptions) replaces "draft-ietf-opsawg-mud-02"
34  * CL-SP-CANN-DHCP-Reg-I15-180509 (CableLabs' DHCP Options Registry) latest
35  *
36  * Note that protocol constants are still subject to change, based on IANA
37  * assignment decisions.
38  *
39  * Wireshark - Network traffic analyzer
40  * By Gerald Combs <gerald@wireshark.org>
41  * Copyright 1998 Gerald Combs
42  *
43  * SPDX-License-Identifier: GPL-2.0-or-later
44  */
45 
46 #include "config.h"
47 
48 #include <epan/packet.h>
49 #include <epan/addr_resolv.h>
50 #include <epan/expert.h>
51 #include <epan/prefs.h>
52 #include <epan/arptypes.h>
53 #include <epan/strutil.h>
54 #include "packet-tcp.h"
55 #include "packet-arp.h"
56 #include "packet-dns.h"
57 
58 void proto_register_dhcpv6(void);
59 void proto_reg_handoff_dhcpv6(void);
60 
61 static gboolean dhcpv6_bulk_leasequery_desegment  = TRUE;
62 static gboolean cablelabs_interface_id = FALSE;
63 
64 static int proto_dhcpv6 = -1;
65 static int proto_dhcpv6_bulk_leasequery = -1;
66 static int hf_dhcpv6_msgtype = -1;
67 static int hf_clientfqdn_bad_msgtype = -1;
68 static int hf_clientfqdn_flags = -1;
69 static int hf_clientfqdn_client_n = -1;
70 static int hf_clientfqdn_client_s = -1;
71 static int hf_clientfqdn_server_n = -1;
72 static int hf_clientfqdn_server_o = -1;
73 static int hf_clientfqdn_server_s = -1;
74 static int hf_option_type_str=-1;
75 static int hf_option_type_num = -1;
76 static int hf_option_length = -1;
77 static int hf_empty_domain_name = -1;
78 static int hf_remoteid_enterprise = -1;
79 static int hf_vendoropts_enterprise = -1;
80 static int hf_duid_bytes = -1;
81 static int hf_duid_type = -1;
82 static int hf_duidllt_time = -1;
83 static int hf_duidllt_link_layer_addr = -1;
84 static int hf_duidllt_hwtype = -1;
85 static int hf_duidll_hwtype = -1;
86 static int hf_duiden_enterprise = -1;
87 static int hf_duiden_identifier = -1;
88 static int hf_duidll_link_layer_addr = -1;
89 static int hf_duiduuid_bytes = -1;
90 static int hf_iaid = -1;
91 static int hf_iaid_t1 = -1;
92 static int hf_iaid_t2 = -1;
93 static int hf_iata = -1;
94 static int hf_iaaddr_ip = -1;
95 static int hf_iaaddr_pref_lifetime = -1;
96 static int hf_iaaddr_valid_lifetime = -1;
97 static int hf_requested_option_code = -1;
98 static int hf_option_preference = -1;
99 static int hf_elapsed_time = -1;
100 static int hf_auth_protocol = -1;
101 static int hf_auth_algorithm = -1;
102 static int hf_auth_rdm = -1;
103 static int hf_auth_replay_detection = -1;
104 static int hf_auth_info = -1;
105 static int hf_auth_realm = -1;
106 static int hf_auth_key_id = -1;
107 static int hf_auth_md5_data = -1;
108 static int hf_opt_unicast = -1;
109 static int hf_opt_status_code = -1;
110 static int hf_opt_status_msg = -1;
111 static int hf_vendorclass_enterprise = -1;
112 static int hf_vendorclass_data = -1;
113 static int hf_vendoropts_enterprise_option_code = -1;
114 static int hf_vendoropts_enterprise_option_length = -1;
115 static int hf_vendoropts_enterprise_option_data = -1;
116 static int hf_interface_id = -1;
117 static int hf_reconf_msg = -1;
118 static int hf_sip_server_domain_search_fqdn = -1;
119 static int hf_sip_server_a = -1;
120 static int hf_dns_servers = -1;
121 static int hf_domain_search_list_entry = -1;
122 static int hf_nis_servers = -1;
123 static int hf_nisp_servers = -1;
124 static int hf_nis_fqdn = -1;
125 static int hf_nisp_fqdn = -1;
126 static int hf_sntp_servers = -1;
127 static int hf_opt_lifetime = -1;
128 static int hf_bcmcs_servers_fqdn = -1;
129 static int hf_bcmcs_servers_a = -1;
130 static int hf_remoteid_enterprise_id = -1;
131 static int hf_subscriber_id = -1;
132 static int hf_client_fqdn = -1;
133 static int hf_pana_agent = -1;
134 static int hf_opt_timezone = -1;
135 static int hf_opt_tzdb = -1;
136 static int hf_lq_query = -1;
137 static int hf_lq_query_link_address = -1;
138 static int hf_clt_time = -1;
139 static int hf_lq_relay_data_peer_addr = -1;
140 static int hf_lq_relay_data_msg = -1;
141 static int hf_lq_client_link = -1;
142 static int hf_capwap_ac_v6 = -1;
143 static int hf_aftr_name = -1;
144 static int hf_iaprefix_pref_lifetime = -1;
145 static int hf_iaprefix_valid_lifetime = -1;
146 static int hf_iaprefix_pref_len = -1;
147 static int hf_iaprefix_pref_addr = -1;
148 static int hf_mip6_ha = -1;
149 static int hf_mip6_hoa = -1;
150 static int hf_nai = -1;
151 static int hf_pd_exclude_pref_len = -1;
152 static int hf_pd_exclude_subnet_id = -1;
153 static int hf_option_captive_portal = -1;
154 static int hf_option_s46_option_code = -1;
155 static int hf_option_failover_binding_status = -1;
156 static int hf_option_failover_connect_flags = -1;
157 static int hf_option_failover_connect_reserved_flag = -1;
158 static int hf_option_failover_connect_f_flag = -1;
159 static int hf_option_failover_dns_hostname = -1;
160 static int hf_option_failover_dns_zonename = -1;
161 static int hf_option_failover_dns_flags = -1;
162 static int hf_option_failover_dns_reserved_flag = -1;
163 static int hf_option_failover_dns_u_flag = -1;
164 static int hf_option_failover_dns_s_flag = -1;
165 static int hf_option_failover_dns_r_flag = -1;
166 static int hf_option_failover_dns_f_flag = -1;
167 static int hf_option_failover_expiration_time = -1;
168 static int hf_option_failover_max_unacked_bndupd = -1;
169 static int hf_option_failover_mclt = -1;
170 static int hf_option_failover_partner_lifetime = -1;
171 static int hf_option_failover_partner_lifetime_sent = -1;
172 static int hf_option_failover_partner_downtime = -1;
173 static int hf_option_failover_partner_raw_clt_time = -1;
174 static int hf_option_failover_major_version = -1;
175 static int hf_option_failover_minor_version = -1;
176 static int hf_option_failover_keepalive_time = -1;
177 static int hf_option_failover_reconfigure_time = -1;
178 static int hf_option_failover_reconfigure_key = -1;
179 static int hf_option_failover_relationship_name = -1;
180 static int hf_option_failover_server_flags = -1;
181 static int hf_option_failover_server_reserved_flag = -1;
182 static int hf_option_failover_server_a_flag = -1;
183 static int hf_option_failover_server_s_flag = -1;
184 static int hf_option_failover_server_c_flag = -1;
185 static int hf_option_failover_server_state = -1;
186 static int hf_option_failover_start_time_of_state = -1;
187 static int hf_option_failover_state_expiration_time = -1;
188 static int hf_option_relay_port = -1;
189 static int hf_dhcpv6_hopcount = -1;
190 static int hf_dhcpv6_xid = -1;
191 static int hf_dhcpv6_peeraddr = -1;
192 static int hf_dhcpv6_linkaddr = -1;
193 static int hf_opt_mudurl = -1;
194 static int hf_option_userclass_length = -1;
195 static int hf_option_userclass_opaque_data = -1;
196 static int hf_option_ntpserver_type = -1;
197 static int hf_option_ntpserver_length = -1;
198 static int hf_option_ntpserver_addr = -1;
199 static int hf_option_ntpserver_mc_addr = -1;
200 static int hf_option_ntpserver_fqdn = -1;
201 static int hf_packetcable_ccc_suboption = -1;
202 static int hf_packetcable_ccc_pri_dhcp = -1;
203 static int hf_packetcable_ccc_sec_dhcp = -1;
204 static int hf_packetcable_cccV6_suboption = -1;
205 static int hf_packetcable_cccV6_pri_dss = -1;
206 static int hf_packetcable_cccV6_sec_dss = -1;
207 static int hf_packetcable_cccV6_prov_srv_type = -1;
208 static int hf_packetcable_cccV6_prov_srv_fqdn = -1;
209 static int hf_packetcable_cccV6_prov_srv_ipv6 = -1;
210 static int hf_packetcable_cccV6_as_krb_nominal_timeout = -1;
211 static int hf_packetcable_cccV6_as_krb_max_timeout = -1;
212 static int hf_packetcable_cccV6_as_krb_max_retry_count = -1;
213 static int hf_packetcable_cccV6_ap_krb_nominal_timeout = -1;
214 static int hf_packetcable_cccV6_ap_krb_max_timeout = -1;
215 static int hf_packetcable_cccV6_ap_krb_max_retry_count = -1;
216 static int hf_packetcable_cccV6_krb_realm = -1;
217 static int hf_packetcable_cccV6_tgt_flag = -1;
218 static int hf_packetcable_cccV6_tgt_flag_fetch = -1;
219 static int hf_packetcable_cccV6_prov_timer = -1;
220 static int hf_packetcable_cccV6_sec_tcm = -1;
221 static int hf_packetcable_cccV6_sec_tcm_provisioning_server = -1;
222 static int hf_packetcable_cccV6_sec_tcm_call_manager_server = -1;
223 static int hf_cablelabs_opts = -1;
224 static int hf_modem_capabilities_encoding_type = -1;
225 static int hf_eue_capabilities_encoding_type = -1;
226 static int hf_capabilities_encoding_length = -1;
227 static int hf_capabilities_encoding_bytes = -1;
228 static int hf_capabilities_encoding_number = -1;
229 static int hf_cablelabs_ipv6_server = -1;
230 static int hf_cablelabs_docsis_version_number = -1;
231 static int hf_cablelabs_interface_id = -1;
232 static int hf_cablelabs_interface_id_link_address = -1;
233 static int hf_option_s46_rule_flags = -1;
234 static int hf_option_s46_rule_reserved_flag = -1;
235 static int hf_option_s46_rule_fmr_flag = -1;
236 static int hf_option_s46_rule_ea_len = -1;
237 static int hf_option_s46_rule_ipv4_pref_len = -1;
238 static int hf_option_s46_rule_ipv4_prefix = -1;
239 static int hf_option_s46_rule_ipv6_pref_len = -1;
240 static int hf_option_s46_rule_ipv6_prefix = -1;
241 static int hf_option_s46_br_address = -1;
242 static int hf_option_s46_dmr_pref_len = -1;
243 static int hf_option_s46_dmr_prefix = -1;
244 static int hf_option_s46_v4v6bind_ipv4_address = -1;
245 static int hf_option_s46_v4v6bind_ipv6_pref_len = -1;
246 static int hf_option_s46_v4v6bind_ipv6_prefix = -1;
247 static int hf_option_s46_portparam_offset = -1;
248 static int hf_option_s46_portparam_psid_len = -1;
249 static int hf_option_s46_portparam_psid = -1;
250 
251 static int hf_dhcpv6_non_dns_encoded_name = -1;
252 static int hf_dhcpv6_domain_field_len_exceeded = -1;
253 static int hf_dhcpv6_decoded_portion = -1;
254 static int hf_dhcpv6_encoded_fqdn_len_gt_255 = -1;
255 static int hf_dhcpv6_root_only_domain_name = -1;
256 static int hf_dhcpv6_tld = -1;
257 static int hf_dhcpv6_partial_name_preceded_by_fqdn = -1;
258 
259 static gint ett_dhcpv6 = -1;
260 static gint ett_dhcpv6_option = -1;
261 static gint ett_dhcpv6_option_vsoption = -1;
262 static gint ett_dhcpv6_vendor_option = -1;
263 static gint ett_dhcpv6_pkt_option = -1;
264 static gint ett_dhcpv6_userclass_option = -1;
265 static gint ett_dhcpv6_netserver_option = -1;
266 static gint ett_dhcpv6_tlv5_type = -1;
267 static gint ett_dhcpv6_sip_server_domain_search_list_option = -1;
268 static gint ett_dhcpv6_dns_domain_search_list_option = -1;
269 static gint ett_dhcpv6_nis_domain_name_option = -1;
270 static gint ett_dhcpv6_nisp_domain_name_option = -1;
271 static gint ett_dhcpv6_bcmcs_servers_domain_search_list_option = -1;
272 static gint ett_dhcpv6_s46_rule_flags = -1;
273 static gint ett_dhcpv6_failover_connect_flags = -1;
274 static gint ett_dhcpv6_failover_dns_flags = -1;
275 static gint ett_dhcpv6_failover_server_flags = -1;
276 static gint ett_clientfqdn_flags = -1;
277 static gint ett_clientfqdn_expert = -1;
278 
279 /* Expert fields relating to domain names */
280 static expert_field ei_dhcpv6_non_dns_encoded_name=EI_INIT;
281 static expert_field ei_dhcpv6_domain_field_len_exceeded=EI_INIT;
282 static expert_field ei_dhcpv6_encoded_fqdn_len_gt_255=EI_INIT;
283 static expert_field ei_dhcpv6_root_only_domain_name=EI_INIT;
284 static expert_field ei_dhcpv6_tld_lookup=EI_INIT;
285 static expert_field ei_dhcpv6_partial_name_preceded_by_fqdn=EI_INIT;
286 /*
287  * Expert fields triggered in dhcpv6_option() and others */
288 static expert_field ei_dhcpv6_bogus_length = EI_INIT;
289 static expert_field ei_dhcpv6_malformed_option = EI_INIT;
290 static expert_field ei_dhcpv6_no_suboption_len = EI_INIT;
291 static expert_field ei_dhcpv6_invalid_time_value = EI_INIT;
292 static expert_field ei_dhcpv6_invalid_type = EI_INIT;
293 static expert_field ei_dhcpv6_error_hopcount = EI_INIT;
294 static expert_field ei_dhcpv6_clientfqdn_bad_msgtype=EI_INIT;
295 static expert_field ei_dhcpv6_s_bit_should_be_zero=EI_INIT;
296 
297 
298 static int hf_dhcpv6_bulk_leasequery_size = -1;
299 static int hf_dhcpv6_bulk_leasequery_msgtype = -1;
300 static int hf_dhcpv6_bulk_leasequery_reserved = -1;
301 static int hf_dhcpv6_bulk_leasequery_trans_id = -1;
302 
303 static gint ett_dhcpv6_bulk_leasequery = -1;
304 static gint ett_dhcpv6_bulk_leasequery_options = -1;
305 
306 static expert_field ei_dhcpv6_bulk_leasequery_bad_query_type = EI_INIT;
307 static expert_field ei_dhcpv6_bulk_leasequery_bad_msg_type = EI_INIT;
308 
309 static dissector_handle_t dhcpv6_handle;
310 
311 #define TCP_PORT_DHCPV6_UPSTREAM        547
312 #define UDP_PORT_DHCPV6_RANGE      "546-547" /* Downstream + Upstream */
313 
314 #define DHCPV6_LEASEDURATION_INFINITY   0xffffffff
315 #define HOP_COUNT_LIMIT                 32
316 
317 /********************************************************************************************/
318 /********************************** MESSAGE TYPES *******************************************/
319 /********************************************************************************************/
320 /*                                     SENT BY                                              */
321 /*                                     -------                                              */
322 #define SOLICIT                  1  /* CLIENT                                               */
323 #define ADVERTISE                2  /* SERVER(S)                                            */
324 #define REQUEST                  3  /* CLIENT                                               */
325 #define CONFIRM                  4  /* CLIENT                                               */
326 #define RENEW                    5  /* CLIENT                                               */
327 #define REBIND                   6  /* CLIENT                                               */
328 #define REPLY                    7  /* SERVER(S)                                            */
329 #define RELEASE                  8  /* CLIENT                                               */
330 #define DECLINE                  9  /* CLIENT                                               */
331 #define RECONFIGURE             10  /* SERVER(S)  (see 18-19)                               */
332 #define INFORMATION_REQUEST     11  /* CLIENT                                               */
333 #define RELAY_FORW              12  /* relay agents                                         */
334 #define RELAY_REPLY             13  /* relay agents                                         */
335 #define LEASEQUERY              14  /*                                                      */
336 #define LEASEQUERY_REPLY        15  /*                                                      */
337 #define LEASEQUERY_DONE         16  /*                                                      */
338 #define LEASEQUERY_DATA         17  /*                                                      */
339 #define RECONFIGURE_REQUEST     18  /* SERVER  (Server requests client to send requests)    */
340 #define RECONFIGURE_REPLY       19  /* CLIENT  (Client replies with the requested requests) */
341 
342 /* TODO: add support the following message types
343 #define DHCPV4-QUERY            20  [RFC7341]
344 #define DHCPV4-RESPONSE         21  [RFC7341]
345 #define ACTIVELEASEQUERY        22  [RFC7653]
346 #define STARTTLS                23  [RFC7653]
347 #define BNDUPD                  24  [RFC8156]
348 #define BNDREPLY                25  [RFC8156]
349 #define POOLREQ                 26  [RFC8156]
350 #define POOLRESP                27  [RFC8156]
351 #define UPDREQ                  28  [RFC8156]
352 #define UPDREQALL               29  [RFC8156]
353 #define UPDDONE                 30  [RFC8156]
354 #define CONNECT                 31  [RFC8156]
355 #define CONNECTREPLY            32  [RFC8156]
356 #define DISCONNECT              33  [RFC8156]
357 #define STATE                   34  [RFC8156]
358 #define CONTACT                 35  [RFC8156]
359                                 36-255 Unassigned
360 *********************************************************************************************/
361 
362 /********************************************************************************************/
363 /**************************************** OPTIONS *******************************************/
364 /********************************************************************************************/
365 #define OPTION_CLIENTID                1
366 #define OPTION_SERVERID                2
367 #define OPTION_IA_NA                   3
368 #define OPTION_IA_TA                   4
369 #define OPTION_IAADDR                  5
370 #define OPTION_ORO                     6
371 #define OPTION_PREFERENCE              7
372 #define OPTION_ELAPSED_TIME            8
373 #define OPTION_RELAY_MSG               9
374 /* #define      OPTION_SERVER_MSG     10 */
375 #define OPTION_AUTH                   11
376 #define OPTION_UNICAST                12
377 #define OPTION_STATUS_CODE            13
378 #define OPTION_RAPID_COMMIT           14
379 #define OPTION_USER_CLASS             15
380 #define OPTION_VENDOR_CLASS           16
381 #define OPTION_VENDOR_OPTS            17
382 #define OPTION_INTERFACE_ID           18
383 #define OPTION_RECONF_MSG             19
384 #define OPTION_RECONF_ACCEPT          20
385 #define OPTION_SIP_SERVER_D           21 /* RFC 3319 */
386 #define OPTION_SIP_SERVER_A           22 /* RFC 3319 */
387 #define OPTION_DNS_SERVERS            23 /* RFC 3646 */
388 #define OPTION_DOMAIN_LIST            24 /* RFC 3646 */
389 #define OPTION_IA_PD                  25 /* RFC 3633 */
390 #define OPTION_IAPREFIX               26 /* RFC 3633 */
391 #define OPTION_NIS_SERVERS            27 /* RFC 3898 */
392 #define OPTION_NISP_SERVERS           28 /* RFC 3898 */
393 #define OPTION_NIS_DOMAIN_NAME        29 /* RFC 3898 */
394 #define OPTION_NISP_DOMAIN_NAME       30 /* RFC 3898 */
395 #define OPTION_SNTP_SERVERS           31 /* RFC 4075 */
396 #define OPTION_LIFETIME               32 /* RFC 4242: OPTION_INFORMATION_REFRESH_TIME */
397 #define OPTION_BCMCS_SERVER_D         33 /* RFC 4280 */
398 #define OPTION_BCMCS_SERVER_A         34 /* RFC 4280 */
399 /* 35 - Unassigned */
400 #define OPTION_GEOCONF_CIVIC          36 /* RFC 4776 */
401 #define OPTION_REMOTE_ID              37 /* RFC 4649 */
402 #define OPTION_SUBSCRIBER_ID          38 /* RFC 4580 */
403 #define OPTION_CLIENT_FQDN            39 /* RFC 4704 */
404 #define OPTION_PANA_AGENT             40 /* RFC 5192 */
405 #define OPTION_TIME_ZONE              41 /* RFC 4833: OPTION_NEW_POSIX_TIMEZONE */
406 #define OPTION_TZDB                   42 /* RFC 4833: OPTION_NEW_TZDB_TIMEZONE */
407 #define OPTION_ERO                    43 /* RFC 4994 */
408 #define OPTION_LQ_QUERY               44 /* RFC 5007 */
409 #define OPTION_CLIENT_DATA            45 /* RFC 5007 */
410 #define OPTION_CLT_TIME               46 /* RFC 5007 */
411 #define OPTION_LQ_RELAY_DATA          47 /* RFC 5007 */
412 #define OPTION_LQ_CLIENT_LINK         48 /* RFC 5007 */
413 #define OPTION_MIP6_HNIDF             49 /* RFC 6610 */
414 #define OPTION_MIP6_VDINF             50 /* RFC 6610 */
415 #define OPTION_V6_LOST                51 /* RFC 5223 */
416 #define OPTION_CAPWAP_AC_V6           52 /* RFC 5417 */
417 #define OPTION_RELAYID                53 /* RFC 5460 */
418 #define OPTION_IPV6_ADDRESS_MOS       54 /* RFC 5678: OPTION-IPv6_Address-MoS */
419 #define OPTION_IPV6_FQDN_MOS          55 /* RFC 5678: OPTION-IPv6_FQDN-MoS */
420 #define OPTION_NTP_SERVER             56 /* RFC 5908 */
421 #define OPTION_V6_ACCESS_DOMAIN       57 /* RFC 5986 */
422 #define OPTION_SIP_UA_CS_LIST         58 /* RFC 6011 */
423 #define OPTION_BOOTFILE_URL           59 /* RFC 5970: OPT_BOOTFILE_URL */
424 #define OPTION_BOOTFILE_PARAM         60 /* RFC 5970: OPT_BOOTFILE_PARAM */
425 #define OPTION_CLIENT_ARCH_TYPE       61 /* RFC 5970 */
426 #define OPTION_NII                    62 /* RFC 5970 */
427 #define OPTION_GEOLOCATION            63 /* RFC 6225 */
428 #define OPTION_AFTR_NAME              64 /* RFC 6334 */
429 #define OPTION_ERP_LOCAL_DOMAIN_NAME  65 /* RFC 6440 */
430 #define OPTION_RSOO                   66 /* RFC 6422 */
431 #define OPTION_PD_EXCLUDE             67 /* RFC 6603 */
432 #define OPTION_VSS                    68 /* RFC 6607 */
433 #define OPTION_MIP6_IDINF             69 /* RFC 6610 */
434 #define OPTION_MIP6_UDINF             70 /* RFC 6610 */
435 #define OPTION_MIP6_HNP               71 /* RFC 6610 */
436 #define OPTION_MIP6_HAA               72 /* RFC 6610 */
437 #define OPTION_MIP6_HAF               73 /* RFC 6610 */
438 #define OPTION_RDNSS_SELECTION        74 /* RFC 6731 */
439 #define OPTION_KRB_PRINCIPAL_NAME     75 /* RFC 6784 */
440 #define OPTION_KRB_REALM_NAME         76 /* RFC 6784 */
441 #define OPTION_KRB_DEFAULT_REALM_NAME 77 /* RFC 6784 */
442 #define OPTION_KRB_KDC                78 /* RFC 6784 */
443 #define OPTION_CLIENT_LINKLAYER_ADDR  79 /* RFC 6939 */
444 #define OPTION_LINK_ADDRESS           80 /* RFC 6977 */
445 #define OPTION_RADIUS                 81 /* RFC 7037 */
446 #define OPTION_SOL_MAX_RT             82 /* RFC 7083 */
447 #define OPTION_INF_MAX_RT             83 /* RFC 7083 */
448 #define OPTION_ADDRSEL                84 /* RFC 7078 */
449 #define OPTION_ADDRSEL_TABLE          85 /* RFC 7078 */
450 #define OPTION_V6_PCP_SERVER          86 /* RFC 7291 */
451 #define OPTION_DHCPV4_MSG             87 /* RFC 7341 */
452 #define OPTION_DHCP4_O_DHCP6_SERVER   88 /* RFC 7341 */
453 #define OPTION_S46_RULE               89 /* RFC 7598 */
454 #define OPTION_S46_BR                 90 /* RFC 7598 */
455 #define OPTION_S46_DMR                91 /* RFC 7598 */
456 #define OPTION_S46_V4V6BIND           92 /* RFC 7598 */
457 #define OPTION_S46_PORTPARAMS         93 /* RFC 7598 */
458 #define OPTION_S46_CONT_MAPE          94 /* RFC 7598 */
459 #define OPTION_S46_CONT_MAPT          95 /* RFC 7598 */
460 #define OPTION_S46_CONT_LW            96 /* RFC 7598 */
461 #define OPTION_4RD                    97 /* RFC 7600 */
462 #define OPTION_4RD_MAP_RULE           98 /* RFC 7600 */
463 #define OPTION_4RD_NON_MAP_RULE       99 /* RFC 7600 */
464 #define OPTION_LQ_BASE_TIME          100 /* RFC 7653 */
465 #define OPTION_LQ_START_TIME         101 /* RFC 7653 */
466 #define OPTION_LQ_END_TIME           102 /* RFC 7653 */
467 #define OPTION_CAPTIVE_PORTAL        103 /* RFC 7710: DHCP Captive-Portal */
468 #define OPTION_MPL_PARAMETERS        104 /* RFC 7774 */
469 #define OPTION_ANI_ATT               105 /* RFC 7839 */
470 #define OPTION_ANI_NETWORK_NAME      106 /* RFC 7839 */
471 #define OPTION_ANI_AP_NAME           107 /* RFC 7839 */
472 #define OPTION_ANI_AP_BSSID          108 /* RFC 7839 */
473 #define OPTION_ANI_OPERATOR_ID       109 /* RFC 7839 */
474 #define OPTION_ANI_OPERATOR_REALM    110 /* RFC 7839 */
475 #define OPTION_S46_PRIORITY          111 /* RFC 8026 */
476 #define OPTION_MUDURL                112 /* MUDURL */
477 #define OPTION_V6_PREFIX64           113 /* RFC 8115 */
478 #define OPTION_F_BINDING_STATUS      114 /* RFC 8156 */
479 #define OPTION_F_CONNECT_FLAGS       115 /* RFC 8156 */
480 #define OPTION_F_DNS_REMOVAL_INFO    116 /* RFC 8156 */
481 #define OPTION_F_DNS_HOST_NAME       117 /* RFC 8156 */
482 #define OPTION_F_DNS_ZONE_NAME       118 /* RFC 8156 */
483 #define OPTION_F_DNS_FLAGS           119 /* RFC 8156 */
484 #define OPTION_F_EXPIRATION_TIME     120 /* RFC 8156 */
485 #define OPTION_F_MAX_UNACKED_BNDUPD  121 /* RFC 8156 */
486 #define OPTION_F_MCLT                  122  /* RFC 8156 */
487 #define OPTION_F_PARTNER_LIFETIME      123  /* RFC 8156 */
488 #define OPTION_F_PARTNER_LIFETIME_SENT 124  /* RFC 8156 */
489 #define OPTION_F_PARTNER_DOWN_TIME     125  /* RFC 8156 */
490 #define OPTION_F_PARTNER_RAW_CLT_TIME  126  /* RFC 8156 */
491 #define OPTION_F_PROTOCOL_VERSION      127  /* RFC 8156 */
492 #define OPTION_F_KEEPALIVE_TIME        128  /* RFC 8156 */
493 #define OPTION_F_RECONFIGURE_DATA      129  /* RFC 8156 */
494 #define OPTION_F_RELATIONSHIP_NAME     130  /* RFC 8156 */
495 #define OPTION_F_SERVER_FLAGS          131  /* RFC 8156 */
496 #define OPTION_F_SERVER_STATE          132  /* RFC 8156 */
497 #define OPTION_F_START_TIME_OF_STATE   133  /* RFC 8156 */
498 #define OPTION_F_STATE_EXPIRATION_TIME 134  /* RFC 8156 */
499 #define OPTION_RELAY_PORT              135  /* RFC 8357 */
500 #define OPTION_V6_SZTP_REDIRECT        136  /* RFC-ietf-netconf-zerotouch-29 */
501 #define OPTION_S46_BIND_IPV6_PREFIX    137  /* RFC 8539 */
502 #define OPTION_IPv6_ADDRESS_ANDSF      143  /* RFC 6153 */
503 
504 /* temporary value until defined by IETF */
505 #define OPTION_MIP6_HA                 165
506 #define OPTION_MIP6_HOA                166
507 #define OPTION_NAI                     167
508 /********************************************************************************************/
509 
510 #define DUID_LLT                1
511 #define DUID_EN                 2
512 #define DUID_LL                 3
513 #define DUID_UUID               4
514 
515 static const value_string msgtype_vals[] = {
516     { SOLICIT,                       "Solicit" },
517     { ADVERTISE,                     "Advertise" },
518     { REQUEST,                       "Request" },
519     { CONFIRM,                       "Confirm" },
520     { RENEW,                         "Renew" },
521     { REBIND,                        "Rebind" },
522     { REPLY,                         "Reply" },
523     { RELEASE,                       "Release" },
524     { DECLINE,                       "Decline" },
525     { RECONFIGURE,                   "Reconfigure" },
526     { INFORMATION_REQUEST,           "Information-request" },
527     { RELAY_FORW,                    "Relay-forw" },
528     { RELAY_REPLY,                   "Relay-reply" },
529     { LEASEQUERY,                    "Leasequery" },
530     { LEASEQUERY_REPLY,              "Leasequery-reply" },
531     { LEASEQUERY_DONE,               "Leasequery-done" },
532     { LEASEQUERY_DATA,               "Leasequery-data" },
533     { RECONFIGURE_REQUEST,           "Reconfigure-request" },
534     { RECONFIGURE_REPLY,             "Reconfigure-reply" },
535     { 0, NULL }
536 };
537 static value_string_ext msgtype_vals_ext = VALUE_STRING_EXT_INIT(msgtype_vals);
538 
539 static const value_string opttype_vals[] = {
540     { OPTION_CLIENTID,               "Client Identifier" },
541     { OPTION_SERVERID,               "Server Identifier" },
542     { OPTION_IA_NA,                  "Identity Association for Non-temporary Address" },
543     { OPTION_IA_TA,                  "Identity Association for Temporary Address" },
544     { OPTION_IAADDR,                 "IA Address" },
545     { OPTION_ORO,                    "Option Request" },
546     { OPTION_PREFERENCE,             "Preference" },
547     { OPTION_ELAPSED_TIME,           "Elapsed time" },
548     { OPTION_RELAY_MSG,              "Relay Message" },
549 /*  { OPTION_SERVER_MSG,             "Server message" }, */
550     { OPTION_AUTH,                   "Authentication" },
551     { OPTION_UNICAST,                "Server unicast" },
552     { OPTION_STATUS_CODE,            "Status code" },
553     { OPTION_RAPID_COMMIT,           "Rapid Commit" },
554     { OPTION_USER_CLASS,             "User Class" },
555     { OPTION_VENDOR_CLASS,           "Vendor Class" },
556     { OPTION_VENDOR_OPTS,            "Vendor-specific Information" },
557     { OPTION_INTERFACE_ID,           "Interface-Id" },
558     { OPTION_RECONF_MSG,             "Reconfigure Message" },
559     { OPTION_RECONF_ACCEPT,          "Reconfigure Accept" },
560     { OPTION_SIP_SERVER_D,           "SIP Server Domain Name List" },
561     { OPTION_SIP_SERVER_A,           "SIP Servers IPv6 Address List" },
562     { OPTION_DNS_SERVERS,            "DNS recursive name server" },
563     { OPTION_DOMAIN_LIST,            "Domain Search List" },
564     { OPTION_IA_PD,                  "Identity Association for Prefix Delegation" },
565     { OPTION_IAPREFIX,               "IA Prefix" },
566     { OPTION_NIS_SERVERS,            "Network Information Server" },
567     { OPTION_NISP_SERVERS,           "Network Information Server V2" },
568     { OPTION_NIS_DOMAIN_NAME,        "Network Information Server Domain Name" },
569     { OPTION_NISP_DOMAIN_NAME,       "Network Information Server V2 Domain Name" },
570     { OPTION_SNTP_SERVERS,           "Simple Network Time Protocol Server" },
571     { OPTION_LIFETIME,               "Lifetime" },
572     { OPTION_BCMCS_SERVER_D,         "BCMCS Server Domain" },
573     { OPTION_BCMCS_SERVER_A,         "BCMCS Servers IPv6 Address List" },
574     { OPTION_GEOCONF_CIVIC,          "Geoconf Civic Address" },
575     { OPTION_REMOTE_ID,              "Remote Identifier" },
576     { OPTION_SUBSCRIBER_ID,          "Subscriber Identifier" },
577     { OPTION_CLIENT_FQDN,            "Client Fully Qualified Domain Name" },
578     { OPTION_PANA_AGENT,             "PANA Agents IPv6 Address List" },
579     { OPTION_TIME_ZONE,              "Time Zone" },
580     { OPTION_TZDB,                   "Time Zone Database" },
581     { OPTION_ERO,                    "Echo Request Option" },
582     { OPTION_LQ_QUERY,               "Leasequery Query" },
583     { OPTION_CLIENT_DATA,            "Leasequery Client Data" },
584     { OPTION_CLT_TIME,               "Client Last Transaction Time" },
585     { OPTION_LQ_RELAY_DATA,          "Leasequery Relay Data" },
586     { OPTION_LQ_CLIENT_LINK,         "Leasequery Client Link Address List" },
587     { OPTION_MIP6_HNIDF,             "Home Network Identifier FQDN" },
588     { OPTION_MIP6_VDINF,             "Visited Home Network Information" },
589     { OPTION_V6_LOST,                "LoST Server" },
590     { OPTION_CAPWAP_AC_V6,           "CAPWAP Access Controllers" },
591     { OPTION_RELAYID,                "Relay-ID" },
592     { OPTION_IPV6_ADDRESS_MOS,       "MoS IPv6 Address" },
593     { OPTION_IPV6_FQDN_MOS,          "MoS Domain Name List" },
594     { OPTION_NTP_SERVER,             "NTP Server" },
595     { OPTION_V6_ACCESS_DOMAIN,       "Access Network Domain Name" },
596     { OPTION_SIP_UA_CS_LIST,         "SIP User Agent Configuration Service Domains" },
597     { OPTION_BOOTFILE_URL,           "Boot File URL" },
598     { OPTION_BOOTFILE_PARAM,         "Boot File Parameters" },
599     { OPTION_CLIENT_ARCH_TYPE,       "Client System Architecture Type" },
600     { OPTION_NII,                    "Client Network Interface Identifier" },
601     { OPTION_GEOLOCATION,            "Geolocation" },
602     { OPTION_AFTR_NAME,              "Dual-Stack Lite AFTR Name" },
603     { OPTION_ERP_LOCAL_DOMAIN_NAME,  "ERP Local Domain Name" },
604     { OPTION_RSOO,                   "Relay-Supplied Options" },
605     { OPTION_PD_EXCLUDE,             "Prefix Exclude" },
606     { OPTION_VSS,                    "Virtual Subnet Selection" },
607     { OPTION_MIP6_IDINF,             "Identified Home Network Information" },
608     { OPTION_MIP6_UDINF,             "Unrestricted Home Network Information" },
609     { OPTION_MIP6_HNP,               "Home Network Prefix" },
610     { OPTION_MIP6_HAA,               "Home Agent Address" },
611     { OPTION_MIP6_HAF,               "Home Agent FQDN" },
612     { OPTION_RDNSS_SELECTION,        "RDNSS Selection" },
613     { OPTION_KRB_PRINCIPAL_NAME,     "Kerberos Principal Name" },
614     { OPTION_KRB_REALM_NAME,         "Kerberos Realm Name" },
615     { OPTION_KRB_DEFAULT_REALM_NAME, "Kerberos Default Realm Name" },
616     { OPTION_KRB_KDC,                "Kerberos KDC" },
617     { OPTION_CLIENT_LINKLAYER_ADDR,  "Client Link-Layer Address" },
618     { OPTION_LINK_ADDRESS,           "Link Address" },
619     { OPTION_RADIUS,                 "RADIUS" },
620     { OPTION_SOL_MAX_RT,             "SOL_MAX_RT" },
621     { OPTION_INF_MAX_RT,             "INF_MAX_RT" },
622     { OPTION_ADDRSEL,                "Address Selection" },
623     { OPTION_ADDRSEL_TABLE,          "Address Selection table" },
624     { OPTION_V6_PCP_SERVER,          "PCP Server" },
625     { OPTION_DHCPV4_MSG,             "DHCPv4 Message" },
626     { OPTION_DHCP4_O_DHCP6_SERVER,   "DHCP 4o6 Servers Address" },
627     { OPTION_S46_RULE,               "S46 Rule" },
628     { OPTION_S46_BR,                 "S46 BR" },
629     { OPTION_S46_DMR,                "S46 DMR" },
630     { OPTION_S46_V4V6BIND,           "S46 IPv4/IPv6 Address Binding" },
631     { OPTION_S46_PORTPARAMS,         "S46 Port Parameters" },
632     { OPTION_S46_CONT_MAPE,          "S46 MAP-E Container" },
633     { OPTION_S46_CONT_MAPT,          "S46 MAP-T Container" },
634     { OPTION_S46_CONT_LW,            "S46 Lightweight 4over6 Container" },
635     { OPTION_4RD,                    "4rd Options" },
636     { OPTION_4RD_MAP_RULE,           "4rd Mapping Rule" },
637     { OPTION_4RD_NON_MAP_RULE,       "4rd Non-Mapping Rule" },
638     { OPTION_LQ_BASE_TIME,           "LQ Server Base Time" },
639     { OPTION_LQ_START_TIME,          "LQ Server Query Start Time" },
640     { OPTION_LQ_END_TIME,            "LQ Server Query End Time" },
641     { OPTION_CAPTIVE_PORTAL,         "Captive Portal" },
642     { OPTION_MPL_PARAMETERS,         "MPL Parameter Configuration" },
643     { OPTION_ANI_ATT,                "Access Technology Type" },
644     { OPTION_ANI_NETWORK_NAME,       "Access Network Name" },
645     { OPTION_ANI_AP_NAME,            "Access Point Name" },
646     { OPTION_ANI_AP_BSSID,           "Access Point BSSID" },
647     { OPTION_ANI_OPERATOR_ID,        "Access Network Operator ID" },
648     { OPTION_ANI_OPERATOR_REALM,     "Access Network Operator Realm" },
649     { OPTION_S46_PRIORITY,           "S46 Priority" },
650     { OPTION_MUDURL,                 "Manufacturer Usage Description" },
651     { OPTION_V6_PREFIX64,            "IPv4/IPv6 Multicast Prefixes" },
652     { OPTION_F_BINDING_STATUS,       "Failover Binding Status" },
653     { OPTION_F_CONNECT_FLAGS,        "Failover Connect Flags" },
654     { OPTION_F_DNS_REMOVAL_INFO,     "Failover DNS Removal Info" },
655     { OPTION_F_DNS_HOST_NAME,        "Failover DNS Hostname" },
656     { OPTION_F_DNS_ZONE_NAME,        "Failover DNS Zone Name" },
657     { OPTION_F_DNS_FLAGS,            "Failover DNS Flags" },
658     { OPTION_F_EXPIRATION_TIME,      "Failover Expiration Time" },
659     { OPTION_F_MAX_UNACKED_BNDUPD,   "Failover Maximum Number Unacked BNDUPD Messages" },
660     { OPTION_F_MCLT,                 "Failover Maximum Client Lead Time (MCLT)" },
661     { OPTION_F_PARTNER_LIFETIME,     "Failover Partner Lifetime" },
662     { OPTION_F_PARTNER_LIFETIME_SENT,"Failover Partner Lifetime Sent" },
663     { OPTION_F_PARTNER_DOWN_TIME,    "Failover Partner Down Time" },
664     { OPTION_F_PARTNER_RAW_CLT_TIME, "Failover Partner Raw Client Time" },
665     { OPTION_F_PROTOCOL_VERSION,     "Failover Protocol Version" },
666     { OPTION_F_KEEPALIVE_TIME,       "Failover Keepalive Time" },
667     { OPTION_F_RECONFIGURE_DATA,     "Failover Reconfigure Data" },
668     { OPTION_F_RELATIONSHIP_NAME,    "Failover Relationship Name" },
669     { OPTION_F_SERVER_FLAGS,         "Failover Server Flags" },
670     { OPTION_F_SERVER_STATE,         "Failover Server State" },
671     { OPTION_F_START_TIME_OF_STATE,  "Failover Start Time of State" },
672     { OPTION_F_STATE_EXPIRATION_TIME,"Failover State Expiration Time" },
673     { OPTION_RELAY_PORT,             "Relay Source Port" },
674     { OPTION_V6_SZTP_REDIRECT,       "SZTP Redirect" },
675     { OPTION_S46_BIND_IPV6_PREFIX,   "Softwire Source Binding Prefix Hint" },
676     { OPTION_IPv6_ADDRESS_ANDSF,     "ANDSF IPv6 Address" },
677     { OPTION_MIP6_HA,                "Mobile IPv6 Home Agent" },
678     { OPTION_MIP6_HOA,               "Mobile IPv6 Home Address" },
679     { OPTION_NAI,                    "Network Access Identifier" },
680     { 0,        NULL }
681 };
682 static value_string_ext opttype_vals_ext = VALUE_STRING_EXT_INIT(opttype_vals);
683 
684 static const value_string statuscode_vals[] =
685 {
686     { 0, "Success" },
687     { 1, "UnspecFail" },
688     { 2, "NoAddrAvail" },
689     { 3, "NoBinding" },
690     { 4, "NotOnLink" },
691     { 5, "UseMulticast" },
692     { 6, "NoPrefixAvail" },
693     { 7, "UnknownQueryType" },
694     { 8, "MalformedQuery" },
695     { 9, "NotConfigured" },
696     {10, "NotAllowed" },
697     {11, "QueryTerminated" },
698     {12, "DataMissing" },           /* RFC 7653 */
699     {13, "CatchUpComplete" },       /* RFC 7653 */
700     {14, "NotSupported" },          /* RFC 7653 */
701     {15, "TLSConnectionRefused" },  /* RFC 7653 */
702     {0, NULL }
703 };
704 static value_string_ext statuscode_vals_ext = VALUE_STRING_EXT_INIT(statuscode_vals);
705 
706 static const value_string duidtype_vals[] =
707 {
708     { DUID_LLT,  "link-layer address plus time" },
709     { DUID_EN,   "assigned by vendor based on Enterprise number" },
710     { DUID_LL,   "link-layer address" },
711     { DUID_UUID, "Universally Unique IDentifier (UUID)" },
712     { 0, NULL }
713 };
714 
715 #define NTP_SUBOPTION_SRV_ADDR  1
716 #define NTP_SUBOPTION_MC_ADDR   2
717 #define NTP_SUBOPTION_SRV_FQDN  3
718 
719 static const value_string ntp_server_opttype_vals[] =
720 {
721     { NTP_SUBOPTION_SRV_ADDR,    "NTP Server Address" },
722     { NTP_SUBOPTION_MC_ADDR,     "NTP Multicast Address" },
723     { NTP_SUBOPTION_SRV_FQDN,    "NTP Server FQDN" },
724 
725     { 0, NULL }
726 };
727 
728 
729 static const true_false_string fqdn_n = {
730     "Server SHOULD NOT perform PTR RR updates",
731     "Server SHOULD perform PTR RR updates"
732 };
733 
734 static const true_false_string fqdn_o = {
735     "Server HAS overridden client's S bit preference",
736     "Server HAS NOT overridden client's S bit preference"
737 };
738 
739 static const true_false_string fqdn_s = {
740     "Server SHOULD perform AAAA RR updates",
741     "Server SHOULD NOT perform AAAA RR updates"
742 };
743 
744 #define LQ_QUERY_ADDRESS        1
745 #define LQ_QUERY_CLIENTID       2
746 #define LQ_QUERY_RELAYID        3
747 #define LQ_QUERY_LINK_ADDRESS   4
748 #define LQ_QUERY_REMOTEID       5
749 
750 static const value_string lq_query_vals[] = {
751     { LQ_QUERY_ADDRESS,      "by-address" },
752     { LQ_QUERY_CLIENTID,     "by-clientID" },
753     { LQ_QUERY_RELAYID,      "by-relayID" },
754     { LQ_QUERY_LINK_ADDRESS, "by-linkAddress" },
755     { LQ_QUERY_REMOTEID,     "by-remoteID" },
756     { 0, NULL },
757 };
758 
759 /* CableLabs Common Vendor Specific Options */
760 #define CL_OPTION_ORO                     0x0001 /* 1 */
761 #define CL_OPTION_DEVICE_TYPE             0x0002 /* 2 */
762 #define CL_OPTION_EMBEDDED_COMPONENT_LIST 0x0003 /* 3 */
763 #define CL_OPTION_DEVICE_SERIAL_NUMBER    0x0004 /* 4 */
764 #define CL_OPTION_HARDWARE_VERSION_NUMBER 0x0005 /* 5 */
765 #define CL_OPTION_SOFTWARE_VERSION_NUMBER 0x0006 /* 6 */
766 #define CL_OPTION_BOOT_ROM_VERSION        0x0007 /* 7 */
767 #define CL_OPTION_VENDOR_OUI              0x0008 /* 8 */
768 #define CL_OPTION_MODEL_NUMBER            0x0009 /* 9 */
769 #define CL_OPTION_VENDOR_NAME             0x000a /* 10 */
770 /* 11-32 are currently reserved */
771 #define CL_OPTION_TFTP_SERVERS            0x0020 /* 32 */
772 #define CL_OPTION_CONFIG_FILE_NAME        0x0021 /* 33 */
773 #define CL_OPTION_SYSLOG_SERVERS          0x0022 /* 34 */
774 #define CL_OPTION_TLV5                    0x0023 /* 35 */
775 #define CL_OPTION_DEVICE_ID               0x0024 /* 36 */
776 #define CL_OPTION_RFC868_SERVERS          0x0025 /* 37 */
777 #define CL_OPTION_TIME_OFFSET             0x0026 /* 38 */
778 #define CL_OPTION_IP_PREF                 0x0027 /* 39 */
779 #define CL_OPTION_CCAP_CORES              0x003D /* 61 */
780 
781 /** CableLabs DOCSIS Project Vendor Specific Options */
782 #define CL_OPTION_DOCS_CMTS_CAP 0x0401  /* 1025 */
783 #define CL_CM_MAC_ADDR 0x0402 /* 1026 */
784 #define CL_EROUTER_CONTAINER_OPTION 0x403 /* 1027 */
785 
786 /** CableLabs PacketCable Project Vendor Specific Options **/
787 #define CL_OPTION_CCC            0x087a  /* 2170 */
788 #define CL_OPTION_CCCV6          0x087b  /* 2171 */
789 #define CL_OPTION_CORRELATION_ID 0x087c  /* 2172 */
790 
791 /** CableLabs TLVs for DOCS_CMTS_CAP Vendor Option **/
792 #define CL_OPTION_DOCS_CMTS_TLV_VERS_NUM 0x01 /* 1 */
793 
794 static const value_string cl_vendor_subopt_values[] = {
795     /*    1 */ { CL_OPTION_ORO,                     "Option Request = " },
796     /*    2 */ { CL_OPTION_DEVICE_TYPE,             "Device Type = " },
797     /*    3 */ { CL_OPTION_EMBEDDED_COMPONENT_LIST, "Embedded Components = " },
798     /*    4 */ { CL_OPTION_DEVICE_SERIAL_NUMBER,    "Serial Number = " },
799     /*    5 */ { CL_OPTION_HARDWARE_VERSION_NUMBER, "Hardware Version = " },
800     /*    6 */ { CL_OPTION_SOFTWARE_VERSION_NUMBER, "Software Version = " },
801     /*    7 */ { CL_OPTION_BOOT_ROM_VERSION,        "Boot ROM Version = " },
802     /*    8 */ { CL_OPTION_VENDOR_OUI,              "Organization Unique Identifier = " },
803     /*    9 */ { CL_OPTION_MODEL_NUMBER,            "Model Number = " },
804     /*   10 */ { CL_OPTION_VENDOR_NAME,             "Vendor Name = " },
805     /*   32 */ { CL_OPTION_TFTP_SERVERS,            "TFTP Server Addresses : " },
806     /*   33 */ { CL_OPTION_CONFIG_FILE_NAME,        "Configuration File Name = " },
807     /*   34 */ { CL_OPTION_SYSLOG_SERVERS,          "Syslog Servers : " },
808     /*   35 */ { CL_OPTION_TLV5,                    "TLV5 = " },
809     /*   36 */ { CL_OPTION_DEVICE_ID,               "Device Identifier = " },
810     /*   37 */ { CL_OPTION_RFC868_SERVERS,          "Time Protocol Servers : " },
811     /*   38 */ { CL_OPTION_TIME_OFFSET,             "Time Offset = " },
812     /*   39 */ { CL_OPTION_IP_PREF,                 "IP preference : " },
813     /*   61 */ { CL_OPTION_CCAP_CORES,              "CCAP-CORES : " },
814     /* 1025 */ { CL_OPTION_DOCS_CMTS_CAP,           "CMTS Capabilities Option : " },
815     /* 1026 */ { CL_CM_MAC_ADDR,                    "CM MAC Address Option = " },
816     /* 1027 */ { CL_EROUTER_CONTAINER_OPTION,       "eRouter Container Option : " },
817     /* 2170 */ { CL_OPTION_CCC,                     "CableLabs Client Configuration : " },
818     /* 2171 */ { CL_OPTION_CCCV6,                   "CableLabs Client Configuration IPv6 : " },
819     /* 2172 */ { CL_OPTION_CORRELATION_ID,          "CableLabs Correlation ID = " },
820     { 0, NULL }
821 };
822 static value_string_ext cl_vendor_subopt_values_ext = VALUE_STRING_EXT_INIT(cl_vendor_subopt_values);
823 
824 /* 17:2170: CL_OPTION_CCC */
825 #define PKT_CCC_PRI_DHCP       0x0001
826 #define PKT_CCC_SEC_DHCP       0x0002
827 
828 static const value_string pkt_ccc_opt_vals[] = {
829     { PKT_CCC_PRI_DHCP,      "TSP's Primary DHCP Server" },
830     { PKT_CCC_SEC_DHCP,      "TSP's Secondary DHCP Server" },
831     { 0, NULL },
832 };
833 
834 /* 17:2171: CL_OPTION_CCCV6 */
835 #define PKT_CCCV6_PRI_DSS       0x0001
836 #define PKT_CCCV6_SEC_DSS       0x0002
837 #define PKT_CCCV6_IETF_PROV_SRV 0x0003
838 #define PKT_CCCV6_IETF_AS_KRB   0x0004
839 #define PKT_CCCV6_IETF_AP_KRB   0x0005
840 #define PKT_CCCV6_KRB_REALM     0x0006
841 #define PKT_CCCV6_TGT_FLAG      0x0007
842 #define PKT_CCCV6_PROV_TIMER    0x0008
843 #define PKT_CCCV6_IETF_SEC_TKT  0x0009
844 /** 10 -255 Reserved for future extensions **/
845 
846 static const value_string pkt_cccV6_opt_vals[] = {
847     { PKT_CCCV6_PRI_DSS,        "TSP's Primary DHCPv6 Server Selector ID" },
848     { PKT_CCCV6_SEC_DSS,        "TSP's Secondary DHCPv6 Server Selector ID " },
849     { PKT_CCCV6_IETF_PROV_SRV,  "TSP's Provisioning Server" },
850     { PKT_CCCV6_IETF_AS_KRB,    "TSP's AS-REQ/AS-REP Backoff and Retry" },
851     { PKT_CCCV6_IETF_AP_KRB,    "TSP's AP-REQ/AP-REP Backoff and Retry" },
852     { PKT_CCCV6_KRB_REALM,      "TSP's Kerberos Realm Name" },
853     { PKT_CCCV6_TGT_FLAG,       "TSP's Ticket Granting Server Utilization" },
854     { PKT_CCCV6_PROV_TIMER,     "TSP's Provisioning Timer Value" },
855     { PKT_CCCV6_IETF_SEC_TKT,   "PacketCable Security Ticket Control" },
856     { 0, NULL }
857 };
858 static value_string_ext pkt_cccV6_opt_vals_ext = VALUE_STRING_EXT_INIT(pkt_cccV6_opt_vals);
859 
860 static const value_string pkt_cccV6_prov_srv_type_vals[] = {
861     { 0,      "FQDN" },
862     { 1,      "IPv6" },
863     { 0, NULL },
864 };
865 
866 #if 0
867 static const value_string sec_tcm_vals[] = {
868     { 1 << 0, "PacketCable Provisioning Server" },
869     { 1 << 1, "PacketCable Call Manager Servers" },
870     { 0, NULL },
871 };
872 #endif
873 
874 static const value_string modem_capabilities_encoding [] = {
875     {  1,     "Concatenation Support" },
876     {  2,     "DOCSIS Version" },
877     {  3,     "Fragmentation Support" },
878     {  4,     "Payload Header Suppression Support" },
879     {  5,     "IGMP Support" },
880     {  6,     "Privacy Support" },
881     {  7,     "Downstream SAID Support" },
882     {  8,     "Upstream Service Flow Support" },
883     {  9,     "Optional Filtering Support" },
884     { 10,      "Transmit Pre-Equalizer Taps per Modulation Interval" },
885     { 11,      "Number of Transmit Equalizer Taps" },
886     { 12,      "DCC Support" },
887     { 13,      "IP Filters Support" },
888     { 14,      "LLC Filters Support" },
889     { 15,      "Expanded Unicast SID Space" },
890     { 16,      "Ranging Hold-Off Support" },
891     { 17,      "L2VPN Capability" },
892     { 18,      "L2VPN eSAFE Host Capability" },
893     { 19,      "Downstream Unencrypted Traffic (DUT) Filtering" },
894     { 20,      "Upstream Frequency Range Support" },
895     { 21,      "Upstream Symbol Rate Support" },
896     { 22,      "Selectable Active Code Mode 2 Support" },
897     { 23,      "Code Hopping Mode 2 Support" },
898     { 24,      "Multiple Transmit Channel Support" },
899     { 25,      "5.12 Msps UpstreamTransmit Channel Support" },
900     { 26,      "2.56 Msps Upstream Transmit Channel Support" },
901     { 27,      "Total SID Cluster Support" },
902     { 28,      "SID Clusters per Service Flow Support" },
903     { 29,      "Multiple Receive Channel Support" },
904     { 30,      "Total Downstream Service ID (DSID) Support" },
905     { 31,      "Resequencing Downstream Service ID (DSID) Support" },
906     { 32,      "Multicast Downstream Service ID (DSID) Support" },
907     { 33,      "Multicast DSID Forwarding" },
908     { 34,      "Frame Control Type Forwarding Capability" },
909     { 35,      "DPV Capability" },
910     { 36,      "Unsolicited Grant Service/Upstream Service Flow Support" },
911     { 37,      "MAP and UCD Receipt Support" },
912     { 38,      "Upstream Drop Classifier Support" },
913     { 39,      "IPv6 Support" },
914     { 40,      "Extended Upstream Transmit Power Capability" },
915     { 41,      "Optional 802.1ad, 802.1ah, MPLS Classification Support" },
916     { 42,      "D-ONU Capabilities Encoding" },
917     { 43,      "Reserved" },
918     { 44,      "Energy Management Capabilities" },
919 /* Added TLV5.45-62 from CL-SP-CANN-I18-180509 */
920     { 45,      "C-DOCSIS Capability Encoding" },
921     { 46,      "CM-STATUS-ACK" },
922     { 47,      "Energy Management Preferences" },
923     { 48,      "Extended Packet Length Support Capability" },
924     { 49,      "Multiple Receive OFDM Channel Support" },
925     { 50,      "Multiple Transmit OFDMA Channel Support" },
926     { 51,      "Downstream OFDM Profile Support" },
927     { 52,      "Downstream OFDM channel subcarrier QAM modulation support" },
928     { 53,      "Upstream OFDM channel subcarrier QAM modulation support" },
929     { 54,      "Downstream Lower Band Edge Support" },
930     { 55,      "Downstream Upper Band Edge Support" },
931     { 56,      "Upstream Upper Band Edge Support" },
932     { 57,      "DOCSIS Time Protocol Support" },
933     { 58,      "DOCSIS Time Protocol Performance Support" },
934     { 59,      "Pmax" },
935     { 60,      "Diplexer Downstream Lower Band Edge" },
936     { 61,      "Diplexer Downstream Upper Band Edge" },
937     { 62,      "Diplexer Upstream Upper Band Edge" },
938     { 0, NULL },
939 };
940 static value_string_ext modem_capabilities_encoding_ext = VALUE_STRING_EXT_INIT(modem_capabilities_encoding);
941 
942 static const value_string eue_capabilities_encoding [] = {
943     {  1,      "PacketCable Version" },
944     {  2,      "Number Of Telephony Endpoints" },
945     {  3,      "TGT Support" },
946     {  4,      "HTTP Download File Access Method Support" },
947     {  5,      "MTA-24 Event SYSLOG Notification Support" },
948     {  6,      "NCS Service Flow Support" },
949     {  7,      "Primary Line Support" },
950     {  8,      "Vendor Specific TLV Type(s)" },
951     {  9,      "NVRAM Ticket/Ticket Information Storage Support" },
952     { 10,      "Provisioning Event Reporting Support" },
953     { 11,      "Supported CODEC(s)" },
954     { 12,      "Silence Suppression Support" },
955     { 13,      "Echo Cancellation Support" },
956     { 14,      "RSVP Support" },
957     { 15,      "UGS-AD Support" },
958     { 16,      "MTA's \"ifIndex\" starting number in \"ifTable\"" },
959     { 17,      "Provisioning Flow Logging Support" },
960     { 18,      "Supported Provisioning Flows" },
961     { 19,      "T38 Version Support" },
962     { 20,      "T38 Error Correction Support" },
963     { 21,      "RFC2833 DTMF Support" },
964     { 22,      "Voice Metrics Support" },
965     { 23,      "Device MIB Support" },
966     { 24,      "Multiple Grants Per Interval Support" },
967     { 25,      "V.152 Support" },
968     { 26,      "Certificate Bootstrapping Support" },
969     { 38,      "IP Address Provisioning Capability" },
970     { 0, NULL },
971 };
972 static value_string_ext eue_capabilities_encoding_ext = VALUE_STRING_EXT_INIT(eue_capabilities_encoding);
973 
974 static const value_string s46_opt_code_vals[] = {
975     { 64,      "DS-Lite" },
976     { 88,      "DHCPv4 over DHCPv6" },
977     { 94,      "MAP-E" },
978     { 95,      "MAP-T" },
979     { 96,      "Lightweight 4over6" },
980     { 0, NULL },
981 };
982 
983 static const value_string failover_binding_status_vals[] = {
984     { 0,       "reserved" },
985     { 1,       "ACTIVE" },
986     { 2,       "EXPIRED" },
987     { 3,       "RELEASED" },
988     { 4,       "PENDING-FREE" },
989     { 5,       "FREE" },
990     { 6,       "FREE-BACKUP" },
991     { 7,       "ABANDONED" },
992     { 8,       "RESET" },
993     { 0, NULL },
994 };
995 
996 static const value_string failover_server_state_vals[] = {
997     {  0,      "reserved" },
998     {  1,      "Startup state (1)" },
999     {  2,      "Normal state" },
1000     {  3,      "Communications interrupted" },
1001     {  4,      "Partner down" },
1002     {  5,      "Synchronizing" },
1003     {  6,      "Recovering bindings from partner" },
1004     {  7,      "Waiting out MCLT after RECOVER" },
1005     {  8,      "Interlock state prior to NORMAL" },
1006     {  9,      "Comm. failed during resolution" },
1007     { 10,      "Primary resolved its conflicts" },
1008     { 0, NULL },
1009 };
1010 
1011 static int * const dhcpv6_failover_connect_flags_fields[] = {
1012     &hf_option_failover_connect_reserved_flag,
1013     &hf_option_failover_connect_f_flag,
1014     NULL
1015 };
1016 
1017 static int * const dhcpv6_failover_dns_flags_fields[] = {
1018     &hf_option_failover_dns_reserved_flag,
1019     &hf_option_failover_dns_u_flag,
1020     &hf_option_failover_dns_s_flag,
1021     &hf_option_failover_dns_r_flag,
1022     &hf_option_failover_dns_f_flag,
1023     NULL
1024 };
1025 
1026 static int * const dhcpv6_failover_server_flags_fields[] = {
1027     &hf_option_failover_server_reserved_flag,
1028     &hf_option_failover_server_a_flag,
1029     &hf_option_failover_server_s_flag,
1030     &hf_option_failover_server_c_flag,
1031     NULL
1032 };
1033 
1034 typedef struct hopcount_info_t {
1035     guint8     hopcount;
1036     proto_item *pi;
1037     gboolean   relay_message_previously_detected;
1038 } hopcount_info;
1039 
1040 static int * const dhcpv6_s46_rule_flags_fields[] = {
1041     &hf_option_s46_rule_reserved_flag,
1042     &hf_option_s46_rule_fmr_flag,
1043     NULL
1044 };
1045 
1046 
1047 static void
initialize_hopount_info(hopcount_info * hpi)1048 initialize_hopount_info(hopcount_info *hpi) {
1049   memset(hpi, 0, sizeof(hopcount_info));
1050 }
1051 
1052 static void
1053 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1054                int off, int eoff, hopcount_info hpi);
1055 
1056 static int
1057 dissect_dhcpv6_s46_ipv6_prefix(tvbuff_t *tvb, int hf, int offset, int prefix_length, proto_tree *tree);
1058 
1059 
1060 static int
dissect_packetcable_ccc_option(proto_tree * v_tree,proto_item * v_item,packet_info * pinfo,tvbuff_t * tvb,int optoff,int optend)1061 dissect_packetcable_ccc_option(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int optoff,
1062                                int optend)
1063 {
1064     /** THE ENCODING OF THIS SUBOPTION HAS CHANGED FROM DHCPv4
1065         the code and length fields have grown from a single octet to
1066         two octets each. **/
1067     int         suboptoff = optoff;
1068     guint16     subopt, subopt_len;
1069     proto_item *vti;
1070     proto_tree *pkt_s_tree;
1071 
1072     subopt = tvb_get_ntohs(tvb, optoff);
1073     suboptoff += 2;
1074 
1075     subopt_len = tvb_get_ntohs(tvb, suboptoff);
1076     suboptoff += 2;
1077 
1078     /* There must be at least five octets left to be a valid sub element */
1079     if (optend <= 0) {
1080         expert_add_info_format(pinfo, v_item, &ei_dhcpv6_no_suboption_len, "Sub element %d: no room left in option for suboption length", subopt);
1081         return (suboptoff - optoff);
1082     }
1083     /* g_print("dissect packetcable ccc option subopt_len=%d optend=%d\n\n", subopt_len, optend); */
1084 
1085     vti = proto_tree_add_item(v_tree, hf_packetcable_ccc_suboption, tvb, optoff, 2, ENC_BIG_ENDIAN);
1086     pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
1087 
1088     switch (subopt) {
1089     case PKT_CCC_PRI_DHCP:      /* IPv4 address values */
1090         if (subopt_len == 4) {
1091             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_pri_dhcp, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
1092         }
1093         else {
1094             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1095         }
1096 
1097         suboptoff += subopt_len;
1098         break;
1099     case PKT_CCC_SEC_DHCP:
1100         if (subopt_len == 4) {
1101             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_sec_dhcp, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
1102         }
1103         else {
1104             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1105         }
1106 
1107         suboptoff += subopt_len;
1108         break;
1109     default:
1110         suboptoff += subopt_len;
1111         break;
1112 
1113     }
1114 
1115     /** Return the number of bytes processed **/
1116     return (suboptoff - optoff);
1117 }
1118 
1119 
1120 /** Dissect one or more domain names within an option's domain name field and verify conformance
1121  *  with RFCs 8415, 3646, 4704, 2181, 1535, 1035, and 1034. Sufficiently detailed info is provided
1122  *  as to the cause of each error.
1123  *
1124  * TERMINOLOGY:
1125  * field          An option's domain name field containing from 0-n domain names (DNs)
1126  * DN             Decoded FQDN or a partial (relative) name.
1127  * label          A DNS-encoded name consisting of length octet followed by a name of that many
1128  *                octets. Bits 7 and 8 of the length octet are 0 thus the maximum length of a
1129  *                name is 63 octets.
1130  * root           "the null length of the root". An encoded root label only consists of its length,
1131  *                [0] and decoded as a dot. The trailing dot of an FQDN should not be confused with
1132  *                dots within a DN which are used to delineate its names.
1133  * TLD or tld     A Top Level Domain name consisting of *two* encoded labels: name and root.
1134  *                For example, [3org0] are decoded as [org.]
1135  * FQDN:          Fully Qualified Domain Name: A "complete" or "absolute" domain name that consists
1136  *                of *three* or more labels the last of which is root [0].
1137  * partial name   One or more labels *not* terminated by root. Partial names consisting of two or
1138  *                more names are referred to as "multi-part partially qualified Domain Names"
1139  *                [RFC 1535 pg 4.]. They are also called "relative" names. "Relative names are either
1140  *                taken relative to a well known origin, or to a list of domains used as a search
1141  *                list." [RFC 1034 3.1]. A partial name must be the only DN in the field.
1142  *
1143  * TODO: Revise DNS routines such as dissect_dns_query(), get_dns_name(), and expand_dns_name()
1144  *       (a.) to be aware of relative/partial names
1145  *       (b.) to detect protocol violations per keywords "MUST" "REQUIRED" and "SHALL"
1146  */
1147 static void
dhcpv6_domain(proto_tree * subtree,proto_item * v_item _U_,packet_info * pinfo,int hfindex,tvbuff_t * tvb,int dn_field_off,guint16 dn_field_len)1148 dhcpv6_domain(proto_tree *subtree, proto_item *v_item _U_, packet_info *pinfo, int hfindex,
1149               tvbuff_t *tvb, int dn_field_off, guint16 dn_field_len)
1150 {
1151     int      final_field_off;        /* Last offset of in DN field */
1152     guint8   label_len;
1153     int      remlen;                 /* The number of remaining octets in a domain field */
1154     guint8   num_labels;
1155     int      first_lab_off;          /* Offset of the first label of a DN */
1156     char     decoded_name_str[320];  /* Array used to construct an FQDN or partial name. Although 255
1157                                         is the max allowed FQDN length, the array is longer in order
1158                                         to accommodate FQDNs greater than 255 for display in error
1159                                         messages.  */
1160     int      dpos;                   /* Current position within decoded_name_str[] */
1161     int      offset;
1162     gboolean fqdn_seen, inc;
1163     proto_item *exi;
1164     proto_tree *ex_subtree;
1165 
1166     /* Empty domain name
1167      * [RFC 4704 4.2.] "A client MAY also leave the Domain Name field empty if it desires the server
1168      * to provide a name." If the domain field is empty, dn_field_len = 0; however, if the field only
1169      * contains a root label(0), it consumes one octet so in that case dn_field_len = 1.
1170      * See [RFC 1034 3.1] for details.
1171      */
1172     if (dn_field_len == 0) {
1173         proto_tree_add_uint_format(subtree, hf_empty_domain_name, tvb, dn_field_off-3, 2, dn_field_len,
1174             "Empty domain field: the client requests the server to provide a domain name");
1175         return;
1176     }
1177     offset              = dn_field_off;
1178     first_lab_off       = dn_field_off;
1179     final_field_off     = dn_field_off + dn_field_len - 1;
1180     remlen              = dn_field_len;
1181     num_labels          = 0;
1182     dpos                = 0;
1183     decoded_name_str[0] = '\0';
1184     fqdn_seen           = FALSE;
1185     inc                 = TRUE;
1186 
1187     /* Decode one label of an FQDN or partial domain name per iteration. [RFC 1034 3.1] "labels are
1188      * separated by dots ('.'). Since a complete domain name ends with the root label, this leads to
1189      * a printed form which ends in a dot."
1190      */
1191     while (remlen) {
1192         label_len = tvb_get_guint8(tvb, offset);
1193         if (label_len > 63) {
1194             /*
1195              * Bits 7 and 8 of the label length octet are zero, so the max length of a label is 63
1196              * octets. If greater, it is likely the first char of a non-DNS-encoded name.
1197              */
1198             exi = proto_tree_add_uint_format(subtree, hf_dhcpv6_non_dns_encoded_name, tvb,
1199                     offset, 1, label_len,
1200                     "Label Length: %u\n"
1201                     "This is not a DNS record encoded domain name. The value in the first octet of\n"
1202                     "a label is the length of the name that follows and must be 63 octets or less.\n"
1203                     "However, in this case it is %u which typically means the name is not DNS encoded.\n",
1204                     label_len, label_len);
1205             ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
1206 
1207             if (num_labels) {
1208                 decoded_name_str[dpos] = '\0';
1209                 proto_tree_add_string_format(ex_subtree, hf_dhcpv6_decoded_portion, tvb,
1210                     first_lab_off, dpos, decoded_name_str,
1211                     "The decoded portion of this FQDN to this point is [%s]\n", decoded_name_str);
1212             }
1213             proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_non_dns_encoded_name, tvb, offset, 1);
1214             return;
1215         }
1216 
1217         if(!dpos)
1218             first_lab_off = offset;
1219         decoded_name_str[dpos] = '\0';
1220         offset++;
1221         remlen--;
1222 
1223         if (label_len > remlen) {
1224             /*
1225              * FQDN len exceeds domain field len.
1226              */
1227             col_append_str(pinfo->cinfo, COL_INFO, " [DOMAIN FIELD LEN EXCEEDED]");
1228 
1229             exi = proto_tree_add_uint_format(subtree, hf_dhcpv6_domain_field_len_exceeded, tvb,
1230                     offset-1, 1, label_len,
1231                     "ERROR: The length of this name, %u, exceeds the remaining length, %d, in the\n"
1232                     "domain name field.\n", label_len, remlen);
1233             ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
1234 
1235             if (num_labels) {
1236                 decoded_name_str[dpos] = '\0';
1237                 proto_tree_add_string_format(ex_subtree, hf_dhcpv6_decoded_portion, tvb,
1238                     first_lab_off, dpos, decoded_name_str,
1239                     "The successfully decoded portion of this FQDN: [%s]\n", decoded_name_str);
1240             }
1241             proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_domain_field_len_exceeded, tvb,
1242                 dn_field_off, dn_field_len);
1243             return;
1244         }
1245 
1246         if (dpos + label_len + 2 > 255) {
1247             /*
1248              * RFC 1034 Section 3.1: "To simplify implementations, the total number of octets that
1249              * represent a domain name (i.e., the sum of all label octets and label lengths) is
1250              * limited to 255."
1251              */
1252             col_append_str(pinfo->cinfo, COL_INFO, " [FQDN > 255]");
1253             /*
1254              * Since label_len is valid (<=63 and the name has not been truncated (i.e., its length
1255              * is <= remlen), display this oversized FQDN.
1256              */
1257             decoded_name_str[dpos] = '.';
1258             dpos++;
1259             tvb_memcpy(tvb, decoded_name_str + dpos, offset, label_len);
1260             offset += label_len;
1261             dpos   += label_len;
1262             if (tvb_get_guint8(tvb, offset) == 0) {
1263                 decoded_name_str[dpos]   = '.';
1264                 dpos++;
1265                 offset++;
1266                 inc = FALSE;
1267             }
1268             decoded_name_str[dpos] = '\0';
1269             exi = proto_tree_add_uint_format(subtree, hf_dhcpv6_encoded_fqdn_len_gt_255, tvb,
1270                       first_lab_off, dpos-1, dpos,
1271                 "FQDN: %s%s\n"
1272                 "ERROR: The total length of DNS-encoded names of this FQDN, %d, exceeds 255,\n"
1273                 "the maximum allowed.", decoded_name_str, (inc ? "<incomplete>" : " "), dpos);
1274             ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
1275             proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_encoded_fqdn_len_gt_255, tvb,
1276                first_lab_off, dpos-1);
1277             return;
1278         }
1279 
1280         if (label_len==0) {
1281             decoded_name_str[dpos] = '.';
1282             dpos++;
1283             decoded_name_str[dpos] = '\0';
1284 
1285             if (num_labels == 0) {
1286                 /*
1287                  * This a standalone root label thus the client has request the resolver to return
1288                  * the IP address of root.
1289                  */
1290                 col_append_str(pinfo->cinfo, COL_INFO, " [ROOT-ONLY DOMAIN NAME]");
1291                 exi = proto_tree_add_string(subtree, hf_dhcpv6_root_only_domain_name, tvb,
1292                     offset-1, 1, "['.' (0)]");
1293                 ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
1294                 proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_root_only_domain_name, tvb,
1295                     offset-1, 1);
1296                 return;
1297             }
1298             else if (num_labels == 1) {
1299                 /*
1300                  * TLDs consist of one DNS encoded label and a root label(0) (e.g., [com.] is
1301                  * encoded as [03 64 6F 6D 00]).
1302                  */
1303                 exi = proto_tree_add_string_format(subtree, hf_dhcpv6_tld, tvb, first_lab_off, dpos+1,
1304                     decoded_name_str, "Top Level Domain name (TLD): %s", decoded_name_str);
1305                 ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
1306                 proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_tld_lookup, tvb, first_lab_off, dpos+1);
1307 
1308                 num_labels = 0;
1309                 dpos = 0;
1310                 fqdn_seen = TRUE;
1311                 continue;   /* This was only a COMMENT/WARNING so continue */
1312             }
1313 
1314             /* This is a fully decoded FQDN. Add it to the tree with a trailing dot for root to
1315              * indicate that the domain name is in fact an FQDN and not a multi-part partially
1316              * qualified domain name.
1317              */
1318             proto_tree_add_string(subtree, hfindex, tvb, first_lab_off, dpos+1, decoded_name_str);
1319             num_labels = 0;
1320             dpos = 0;
1321             fqdn_seen = TRUE;
1322             continue;   /* Decode the next FQDN, if any */
1323         }
1324         /**************** End of label_len==0 (root) ****************/
1325 
1326         /* If a DN's last offset equals final_field_off, this marks the end of a partial name. Due
1327          * to the fact that they are root-terminated, only one partial name or 'multi-part partially
1328          * qualified domain name' is permitted per option field; otherwise, the labels of a
1329          * subsequent DN would be appended to it.
1330          *
1331          * If a client with a domain name suffix search list configured manually, via GPO, or
1332          * OPTION_DOMAIN_LIST response, appends each of the (rooted) list entries and queries the
1333          * DNS server for each. If a search list is unavailable, the client sends a partial name to
1334          * the server which will use its own search list. According to RFC 1535 Pg 4, "where a '.'
1335          * exists in a specified name it should be assumed to be a fully qualified domain name (FQDN)
1336          * and SHOULD be tried as a rooted name first." Some client implementations, most notably MS
1337          * Windows, do the opposite; the client issues several superfluous (silly-named) queries all
1338          * of which fail, followed by a successful rooted name query. See RFCs 1034 3.1 and 4704 4.2
1339          * for more info.
1340          */
1341         if (offset + label_len - 1 == final_field_off) {
1342             tvb_memcpy(tvb, decoded_name_str + dpos, first_lab_off + 1, label_len);
1343             dpos += label_len;
1344             decoded_name_str[dpos] = '\0';
1345             num_labels++;
1346 
1347             if (fqdn_seen) {
1348                 /*
1349                  * An FQDN precedes this partial name. Partial names must be the only DN in the
1350                  * domain field.
1351                  */
1352                 col_append_str(pinfo->cinfo, COL_INFO, " [PROTOCOL VIOLATION]");
1353 
1354                 exi = proto_tree_add_string_format(subtree, hf_dhcpv6_partial_name_preceded_by_fqdn,
1355                         tvb, first_lab_off, label_len, decoded_name_str,
1356                         "Partial name: %s\n"
1357                         "ERROR: A single or multi-part partial name must be the only name in "
1358                         "the domain field", decoded_name_str);
1359                 ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
1360                 proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_partial_name_preceded_by_fqdn,
1361                     tvb, first_lab_off, label_len);
1362                 return;
1363             }
1364 
1365             /* A conformant partial name
1366              */
1367             if (num_labels==1) {
1368                 proto_tree_add_string_format(subtree, hfindex, tvb, first_lab_off, dpos+1,
1369                     decoded_name_str, "Partial domain name: %s", decoded_name_str);
1370             }
1371             else {
1372                 proto_tree_add_string_format(subtree, hfindex, tvb, first_lab_off, dpos+1,
1373                     decoded_name_str, "Multi-part partially qualified Domain Name: %s",
1374                     decoded_name_str);
1375             }
1376             return;
1377         }
1378 
1379         /* Add this name it to the array. Prepend it with a dot unless it's the first name of the DN.
1380          * Dots are only used to separate (delineate) the decoded names of a DN; however, an FQDN's
1381          * trailing root label (0) is decoded as a dot. This is handled above.
1382          */
1383         if (num_labels) {
1384             decoded_name_str[dpos] = '.';
1385             dpos++;
1386         }
1387         tvb_memcpy(tvb, decoded_name_str + dpos, offset, label_len);
1388         offset += label_len;
1389         remlen -= label_len;
1390         dpos   += label_len;
1391         decoded_name_str[dpos] = '\0';
1392         num_labels++;
1393     }
1394     /* End of while() loop */
1395 }
1396 
1397 
1398 static int
dissect_packetcable_cccV6_option(proto_tree * v_tree,proto_item * v_item,packet_info * pinfo,tvbuff_t * tvb,int optoff,int optend)1399 dissect_packetcable_cccV6_option(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int optoff,
1400     int optend)
1401 {
1402     int         suboptoff = optoff;
1403     guint16     subopt, subopt_len;
1404     guint8      type;
1405     proto_item *vti, *ti;
1406     proto_tree *pkt_s_tree;
1407     int         i;
1408 
1409     subopt = tvb_get_ntohs(tvb, optoff);
1410     suboptoff += 2;
1411 
1412     subopt_len = tvb_get_ntohs(tvb, suboptoff);
1413     suboptoff += 2;
1414 
1415     /* There must be at least five octets left to be a valid sub element */
1416     if (optend <= 0) {
1417         expert_add_info_format(pinfo, v_item, &ei_dhcpv6_no_suboption_len, "Sub element %d: no room left in option for suboption length", subopt);
1418         return (suboptoff - optoff);
1419     }
1420 
1421     vti = proto_tree_add_item(v_tree, hf_packetcable_cccV6_suboption, tvb, optoff, 2, ENC_BIG_ENDIAN);
1422     pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
1423 
1424     switch (subopt) {
1425     case PKT_CCCV6_PRI_DSS:
1426         if (subopt_len < 35) {
1427             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_pri_dss, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA);
1428         } else {
1429             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1430         }
1431         suboptoff += subopt_len;
1432         break;
1433     case PKT_CCCV6_SEC_DSS:
1434         if (subopt_len < 35) {
1435             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_dss, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA);
1436         } else {
1437             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1438         }
1439         suboptoff += subopt_len;
1440         break;
1441     case PKT_CCCV6_IETF_PROV_SRV:
1442         proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_prov_srv_type, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1443         type = tvb_get_guint8(tvb, suboptoff);
1444 
1445         /** Type 0 is FQDN **/
1446         if (type == 0) {
1447             dhcpv6_domain(pkt_s_tree, vti, pinfo, hf_packetcable_cccV6_prov_srv_fqdn, tvb, suboptoff+1, subopt_len-1);
1448 
1449             /** Type 1 is IPv6 **/
1450         } else if (type == 1) {
1451             if ((subopt_len % 16) == 0) {
1452                 for (i = 0; i < subopt_len/16; i++) {
1453                     proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_prov_srv_ipv6, tvb, suboptoff+1, 4, ENC_NA);
1454                     suboptoff += 16;
1455                 }
1456             }
1457         } else {
1458             expert_add_info_format(pinfo, vti, &ei_dhcpv6_invalid_type, "Invalid type: %u (%u byte%s)",
1459                                    type, subopt_len, plurality(subopt_len, "", "s"));
1460         }
1461         suboptoff += subopt_len;
1462         break;
1463     case PKT_CCCV6_IETF_AS_KRB:
1464         if (subopt_len == 12) {
1465             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_as_krb_nominal_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
1466             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_as_krb_max_timeout, tvb, suboptoff+4, 4, ENC_BIG_ENDIAN);
1467             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_as_krb_max_retry_count, tvb, suboptoff+8, 4, ENC_BIG_ENDIAN);
1468         } else {
1469             proto_item_append_text(vti, "Bogus length: %d", subopt_len);
1470         }
1471         suboptoff += subopt_len;
1472         break;
1473     case PKT_CCCV6_IETF_AP_KRB:
1474         if (subopt_len == 12) {
1475             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_ap_krb_nominal_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
1476             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_ap_krb_max_timeout, tvb, suboptoff+4, 4, ENC_BIG_ENDIAN);
1477             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_ap_krb_max_retry_count, tvb, suboptoff+8, 4, ENC_BIG_ENDIAN);
1478         } else {
1479             proto_item_append_text(vti, "Bogus length: %d", subopt_len);
1480         }
1481         suboptoff += subopt_len;
1482         break;
1483     case PKT_CCCV6_KRB_REALM:
1484         if (subopt_len > 0) {
1485             dhcpv6_domain(pkt_s_tree, vti, pinfo, hf_packetcable_cccV6_krb_realm, tvb, suboptoff, subopt_len);
1486         }
1487         suboptoff += subopt_len;
1488         break;
1489     case PKT_CCCV6_TGT_FLAG:
1490         if (subopt_len == 1) {
1491             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_tgt_flag, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1492             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_tgt_flag_fetch, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1493         }
1494         else {
1495             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1496         }
1497         suboptoff += subopt_len;
1498         break;
1499     case PKT_CCCV6_PROV_TIMER:
1500         if (subopt_len == 1) {
1501             ti = proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_prov_timer, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1502             if (tvb_get_guint8(tvb, suboptoff) > 30)
1503                 expert_add_info(pinfo, ti, &ei_dhcpv6_invalid_time_value);
1504         }
1505         else {
1506             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1507         }
1508         suboptoff += subopt_len;
1509         break;
1510     case PKT_CCCV6_IETF_SEC_TKT:
1511         proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_tcm, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
1512         if (subopt_len == 2) {
1513             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_tcm_provisioning_server, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
1514             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_tcm_call_manager_server, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
1515         } else {
1516             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1517         }
1518         suboptoff += subopt_len;
1519         break;
1520     default:
1521         suboptoff += subopt_len;
1522         break;
1523     }
1524     /** Return the number of bytes processed **/
1525     return (suboptoff - optoff);
1526 }
1527 
1528 /* ToDo: review latest CL docs for updates */
1529 static void
dissect_cablelabs_specific_opts(proto_tree * v_tree,proto_item * v_item,packet_info * pinfo,tvbuff_t * tvb,int voff,int len)1530 dissect_cablelabs_specific_opts(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int voff, int len)
1531 {
1532     guint type,
1533           sub_value;
1534     proto_item *ti;
1535     proto_item *ti2;
1536     proto_tree *subtree;
1537     proto_tree *subtree2;
1538     int tlv5_cap_index,
1539         tlv5_counter,
1540         tlv5_cap_len;
1541     int off = voff,
1542         sub_off, /** The offset for the sub-option */
1543         i,
1544         tlv_len, /* holds the number of elements in the tlv */
1545         field_len, /* holds the length of one occurrence of a field */
1546         opt_len, /* holds the length of the suboption */
1547         field_value;
1548     gchar *device_type = NULL;
1549 
1550     if (len > 4) {
1551         while (off - voff < len) {
1552 
1553             /* Type */
1554             type = tvb_get_ntohs(tvb, off);
1555             ti = proto_tree_add_item(v_tree, hf_cablelabs_opts, tvb, off, 2, ENC_BIG_ENDIAN);
1556             /* Length */
1557             tlv_len = tvb_get_ntohs(tvb, off+2);
1558 
1559             /* Values */
1560             sub_off = off + 4;
1561 
1562             switch (type) {
1563                 /* String types */
1564             case CL_OPTION_DEVICE_TYPE:
1565                 opt_len = tlv_len;
1566                 field_len = tlv_len;
1567 
1568                 device_type = tvb_get_string_enc(pinfo->pool, tvb, sub_off, field_len, ENC_ASCII);
1569 
1570                 if ((device_type == NULL) || (strlen(device_type) == 0)) {
1571                     proto_item_append_text(ti, "Packet does not contain Device Type.");
1572                 } else {
1573                     proto_item_append_text(ti, "\"%s\"", device_type);
1574                 }
1575                 break;
1576             case CL_OPTION_DEVICE_SERIAL_NUMBER:
1577             case CL_OPTION_HARDWARE_VERSION_NUMBER:
1578             case CL_OPTION_SOFTWARE_VERSION_NUMBER:
1579             case CL_OPTION_BOOT_ROM_VERSION:
1580             case CL_OPTION_MODEL_NUMBER:
1581             case CL_OPTION_VENDOR_NAME:
1582             case CL_OPTION_CONFIG_FILE_NAME:
1583             case CL_OPTION_EMBEDDED_COMPONENT_LIST:
1584                 opt_len = tlv_len;
1585                 field_len = tlv_len;
1586                 proto_item_append_text(ti, "\"%s\"",
1587                                        tvb_format_stringzpad(pinfo->pool, tvb, sub_off, field_len));
1588                 break;
1589             case CL_OPTION_VENDOR_OUI:
1590                 /* CableLabs specs treat 17.8 inconsistently
1591                  * as either binary (3b) or string (6b) */
1592                 opt_len = tlv_len;
1593                 if (tlv_len == 3) {
1594                     proto_item_append_text(ti, "%s",
1595                         tvb_bytes_to_str_punct(pinfo->pool, tvb, sub_off, 3, ':'));
1596                 } else if (tlv_len == 6) {
1597                     proto_item_append_text(ti, "\"%s\"", tvb_format_stringzpad(pinfo->pool, tvb, sub_off, tlv_len));
1598                 } else {
1599                     expert_add_info_format(pinfo, ti, &ei_dhcpv6_bogus_length, "Suboption %d: suboption length isn't 3 or 6", type);
1600                 }
1601                 break;
1602             case CL_OPTION_ORO:
1603                 field_len = 2;
1604                 opt_len = tlv_len;
1605                 if (opt_len > 0) {
1606                     for (i = 0; i < tlv_len; i += field_len) {
1607                         sub_value = tvb_get_ntohs(tvb, sub_off);
1608                         proto_item_append_text(ti, " %d", sub_value);
1609                         sub_off += field_len;
1610                     }
1611                 }
1612                 break;
1613             /* List of IPv6 Address */
1614             case CL_OPTION_TFTP_SERVERS:
1615             case CL_OPTION_SYSLOG_SERVERS:
1616             case CL_OPTION_RFC868_SERVERS:
1617             case CL_OPTION_CCAP_CORES:
1618                 field_len = 16;
1619                 opt_len = tlv_len;
1620                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1621 
1622                 if ((tlv_len % field_len) == 0) {
1623                     for (i = 0; i < tlv_len/field_len; i++) {
1624                         ti = proto_tree_add_item(subtree, hf_cablelabs_ipv6_server, tvb, sub_off, 16, ENC_NA);
1625                         proto_item_prepend_text(ti, " %d ", i + 1);
1626                         sub_off += field_len;
1627                     }
1628                 }
1629                 break;
1630             case CL_OPTION_DEVICE_ID:
1631                 opt_len = tlv_len;
1632                 field_len = tlv_len;
1633                 if (tlv_len != 6) {
1634                     expert_add_info_format(pinfo, ti, &ei_dhcpv6_bogus_length, "Bogus length: %d", tlv_len);
1635                 }
1636                 else {
1637                     proto_item_append_text(ti, "%s",
1638                                            tvb_bytes_to_str(pinfo->pool, tvb, sub_off, field_len));
1639                 }
1640                 break;
1641             case CL_OPTION_TLV5:
1642                 /* ToDo: review latest CL docs for updates */
1643                 opt_len = tlv_len;
1644 
1645 
1646                 tlv5_counter = 0;
1647                 tlv5_cap_index = sub_off;
1648 
1649                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_tlv5_type);
1650 
1651                 while (tlv5_counter < tlv_len) {
1652                     /*Device type is not mandatory for CM (see par 10.2.5.2.3 "Obtain IPv6 Management Address and Other Configuration Parameters" in  CM-SP-MULPIv3.1-114-180130*/
1653                     if (device_type == NULL || !g_ascii_strncasecmp(device_type, "ecm", 3)) {
1654                         ti2 = proto_tree_add_item(subtree, hf_modem_capabilities_encoding_type, tvb, tlv5_cap_index, 1, ENC_BIG_ENDIAN);
1655                     } else if (!g_ascii_strncasecmp(device_type, "edva", 3)) {
1656                         ti2 = proto_tree_add_item(subtree, hf_eue_capabilities_encoding_type, tvb, tlv5_cap_index, 1, ENC_BIG_ENDIAN);
1657                     } else {
1658                         break;
1659                     }
1660 
1661                     tlv5_cap_index++;
1662                     tlv5_counter++;
1663 
1664                     /* Why make another subtree (subtree2) below?
1665                        The addition of a subtree is not needed for the display.
1666                        However, when parsing the PDML, each Type 'contains' it's Length and Value.
1667                     */
1668                     subtree2 = proto_item_add_subtree(ti2, ett_dhcpv6_tlv5_type);
1669 
1670                     proto_tree_add_item(subtree2, hf_capabilities_encoding_length, tvb, tlv5_cap_index, 1, ENC_BIG_ENDIAN);
1671                     tlv5_cap_len = (guint8) tvb_get_guint8(tvb, tlv5_cap_index);
1672 
1673                     tlv5_cap_index++;
1674                     tlv5_counter += tlv5_cap_len;
1675 
1676                     /* In cases where the TLV length is greater than 2, the value fields should be displayed
1677                        according to the encoding of the values as described in the CL-SP-CANN-DHCP-Reg specification.
1678                        Below, these values are simply displayed as hex.
1679                     */
1680                     if (tlv5_cap_len > 2) {
1681                             proto_tree_add_item(subtree2, hf_capabilities_encoding_bytes, tvb, tlv5_cap_index, tlv5_cap_len, ENC_NA);
1682                     } else {
1683                             proto_tree_add_item(subtree2, hf_capabilities_encoding_number, tvb, tlv5_cap_index, tlv5_cap_len, ENC_BIG_ENDIAN);
1684                     }
1685 
1686                     tlv5_cap_index += tlv5_cap_len;
1687                     tlv5_counter++;
1688                 }
1689                 break;
1690             case CL_OPTION_TIME_OFFSET:
1691                 opt_len = tlv_len;
1692                 proto_item_append_text(ti, "%d", tvb_get_ntohl(tvb, sub_off));
1693                 break;
1694             case CL_OPTION_IP_PREF:
1695                 opt_len = tlv_len;
1696                 field_value = tvb_get_guint8(tvb, sub_off);
1697                 if (field_value == 1) {
1698                     proto_item_append_text(ti, "%s", "IPv4");
1699                 } else if (field_value == 2) {
1700                     proto_item_append_text(ti, "%s", "IPv6");
1701                 } else if (field_value == 6) {
1702                     proto_item_append_text(ti, "%s", "Dual Stack");
1703                 } else {
1704                     proto_item_append_text(ti, "%s%d", "Invalid IP Preference value ", field_value);
1705                 }
1706                 break;
1707             case CL_OPTION_DOCS_CMTS_CAP:
1708                 opt_len = tlv_len;
1709                 field_len = 0;
1710                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1711 
1712                 /* tlv_len contains the total length of all the TLVs for this
1713                    option */
1714                 if (tlv_len > 0) {
1715                     for (i = 0; field_len < opt_len; i++) {
1716                         int tagLen = 0;
1717                         int tag = 0;
1718                         tag = tvb_get_guint8(tvb, sub_off);
1719                         sub_off++;
1720                         tagLen = tvb_get_guint8(tvb, sub_off);
1721                         sub_off++;
1722                         if ((tag == CL_OPTION_DOCS_CMTS_TLV_VERS_NUM) && (tagLen == 2)) {
1723                             proto_tree_add_item(subtree, hf_cablelabs_docsis_version_number, tvb, sub_off,
1724                                 2, ENC_BIG_ENDIAN);
1725                             sub_off += 2;
1726                         }
1727                         else
1728                             sub_off += tagLen;
1729 
1730                         field_len += tagLen + 2;
1731                     }
1732                 }
1733                 else
1734                     proto_item_append_text(ti, " (empty)");
1735                 break;
1736             case CL_CM_MAC_ADDR:
1737                 opt_len = tlv_len;
1738                 if (tlv_len != 6) {
1739                     expert_add_info_format(pinfo, ti, &ei_dhcpv6_bogus_length, "Bogus length: %d", tlv_len);
1740                 }
1741                 else {
1742                     /*proto_item_append_text(ti, "CM MAC Address Option = %s", */
1743                     proto_item_append_text(ti, "%s", tvb_bytes_to_str_punct(pinfo->pool, tvb, sub_off, opt_len, ':'));
1744                     /* tvb_bytes_to_str(pinfo->pool, tvb, sub_off, opt_len)); */
1745                 }
1746                 break;
1747             case CL_EROUTER_CONTAINER_OPTION:
1748                 opt_len = tlv_len;
1749                 proto_item_append_text(ti, " %s (len=%d)",
1750                                        tvb_bytes_to_str(pinfo->pool, tvb, sub_off, opt_len), tlv_len);
1751                 break;
1752             case CL_OPTION_CCC:
1753                 opt_len = tlv_len;
1754                 field_len = 0;
1755                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1756                 proto_item_append_text(ti, " (%d bytes)", opt_len);
1757                 while (field_len < opt_len) {
1758                     sub_value = dissect_packetcable_ccc_option(subtree, ti, pinfo, tvb,
1759                                                                sub_off, (opt_len - field_len));
1760                     sub_off += sub_value;
1761                     field_len += sub_value;
1762                 }
1763                 break;
1764             case CL_OPTION_CCCV6:
1765                 opt_len = tlv_len;
1766                 field_len = 0;
1767                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1768                 proto_item_append_text(ti, " (%d bytes)", opt_len);
1769                 while (field_len < opt_len) {
1770                     sub_value = dissect_packetcable_cccV6_option(subtree, ti, pinfo, tvb,
1771                         sub_off, (opt_len - field_len));
1772                     sub_off += sub_value;
1773                     field_len += sub_value;
1774                 }
1775                 break;
1776             case CL_OPTION_CORRELATION_ID:
1777                 opt_len = tlv_len;
1778                  if (tlv_len != 4) {
1779                     proto_item_append_text(ti, "Bogus value length=%d",
1780                                            tlv_len);
1781                 }
1782                 else {
1783                     proto_item_append_text(ti, "%u", tvb_get_ntohl(tvb, sub_off));
1784                 }
1785                 break;
1786             default:
1787                 opt_len = tlv_len;
1788                 break;
1789             }
1790             off += (opt_len + 4);
1791 
1792         }
1793     }
1794     else {
1795         expert_add_info_format(pinfo, v_item, &ei_dhcpv6_bogus_length, "Bogus length: %d", len);
1796     }
1797 }
1798 
1799 static void
cablelabs_fmt_docsis_version(gchar * result,guint32 revision)1800 cablelabs_fmt_docsis_version( gchar *result, guint32 revision )
1801 {
1802    g_snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", (guint8)(( revision & 0xFF00 ) >> 8), (guint8)(revision & 0xFF) );
1803 }
1804 
1805 
1806 /* Returns the number of bytes consumed by this option. */
1807 static int
dhcpv6_option(tvbuff_t * tvb,packet_info * pinfo,proto_tree * bp_tree,int off,int eoff,gboolean * at_end,int protocol,hopcount_info hpi,guint8 msgtype)1808 dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree,
1809               int off, int eoff, gboolean *at_end, int protocol, hopcount_info hpi, guint8 msgtype)
1810 {
1811     guint16     opttype, hwtype, subopt_type;
1812     int         temp_optlen, optlen, subopt_len; /* 16-bit values that need 16-bit rollover protection */
1813     proto_item *ti = NULL, *option_item;
1814     proto_tree *subtree;
1815     proto_tree *subtree_2;
1816     int         i;
1817     guint16     duidtype;
1818     guint32     enterprise_no;
1819     guint       algorithm;
1820 
1821     /* option type and length must be present */
1822     if ((eoff - off) < 4) {
1823         *at_end = TRUE;
1824         return 0;
1825     }
1826 
1827     opttype = tvb_get_ntohs(tvb, off);
1828     optlen  = tvb_get_ntohs(tvb, off + 2);
1829 
1830     /* all option data must be present */
1831     if ((eoff - off) < (4 + optlen)) {
1832         *at_end = TRUE;
1833         return 0;
1834     }
1835 
1836     /* Replace "Text item" option header with a filterable field which in turn eliminates the need
1837      * for the "Value:" raw data field. */
1838     option_item = proto_tree_add_string_format(bp_tree, hf_option_type_str, tvb, off, 4 + optlen,
1839                     val_to_str_ext(opttype, &opttype_vals_ext, "DHCP option %u"),
1840                     "%s", val_to_str_ext(opttype, &opttype_vals_ext, "DHCP option %u"));
1841 
1842     subtree = proto_item_add_subtree(option_item, ett_dhcpv6_option);
1843 
1844     proto_tree_add_item(subtree, hf_option_type_num, tvb, off, 2, ENC_BIG_ENDIAN);
1845     proto_tree_add_item(subtree, hf_option_length, tvb, off + 2, 2, ENC_BIG_ENDIAN);
1846     off += 4;
1847 
1848     switch (opttype) {
1849     case OPTION_CLIENTID:
1850         col_append_fstr(pinfo->cinfo, COL_INFO, "CID: %s ", tvb_bytes_to_str(pinfo->pool, tvb, off, optlen));
1851         /* Fall through */
1852     case OPTION_SERVERID:
1853     case OPTION_RELAYID:
1854         if (optlen < 2) {
1855             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1856             break;
1857         }
1858         proto_tree_add_item(subtree, hf_duid_bytes, tvb, off, optlen, ENC_NA);
1859         duidtype = tvb_get_ntohs(tvb, off);
1860         proto_tree_add_item(subtree, hf_duid_type, tvb, off, 2, ENC_BIG_ENDIAN);
1861 
1862         switch (duidtype) {
1863         case DUID_LLT:
1864         {
1865             nstime_t llt_time;
1866 
1867             if (optlen < 8) {
1868                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1869                 break;
1870             }
1871             proto_tree_add_item(subtree, hf_duidllt_hwtype, tvb, off + 2, 2, ENC_BIG_ENDIAN);
1872 
1873             /* Packet specifies seconds since Jan 1 2000, so add 946684800U (30 years) to get back to epoch */
1874             llt_time.secs = tvb_get_ntohl(tvb, off + 4) + 946684800U;
1875             llt_time.nsecs = 0;
1876 
1877             proto_tree_add_time(subtree, hf_duidllt_time, tvb, off + 4, 4, &llt_time);
1878             if (optlen > 8) {
1879                 hwtype = tvb_get_ntohs(tvb, off + 2);
1880                 proto_tree_add_string(subtree, hf_duidllt_link_layer_addr, tvb, off + 8,
1881                                     optlen - 8, tvb_arphrdaddr_to_str(tvb, off+8, optlen-8, hwtype));
1882             }
1883         }
1884         break;
1885         case DUID_EN:
1886             if (optlen < 6) {
1887                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1888                 break;
1889             }
1890             proto_tree_add_item(subtree, hf_duiden_enterprise, tvb, off + 2, 4, ENC_BIG_ENDIAN);
1891             if (optlen > 6) {
1892                 proto_tree_add_item(subtree, hf_duiden_identifier, tvb, off + 6, optlen - 6, ENC_NA);
1893             }
1894             break;
1895         case DUID_LL:
1896             if (optlen < 4) {
1897                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1898                 break;
1899             }
1900             proto_tree_add_item(subtree, hf_duidll_hwtype, tvb, off + 2, 2, ENC_BIG_ENDIAN);
1901             if (optlen > 4) {
1902                 hwtype = tvb_get_ntohs(tvb, off + 2);
1903                 proto_tree_add_string(subtree, hf_duidll_link_layer_addr, tvb, off + 4,
1904                                     optlen - 4, tvb_arphrdaddr_to_str(tvb, off+4, optlen-4, hwtype));
1905             }
1906             break;
1907         case DUID_UUID:
1908             if (optlen != 18) {
1909                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1910                 break;
1911             }
1912             proto_tree_add_item(subtree, hf_duiduuid_bytes, tvb, off + 2, 16, ENC_NA);
1913             break;
1914         }
1915         break;
1916     case OPTION_USER_CLASS:
1917     {
1918         temp_optlen = 0;
1919         while (optlen > temp_optlen) {
1920             subopt_len = tvb_get_ntohs(tvb,  off + temp_optlen);
1921             if (subopt_len > optlen - temp_optlen) {
1922                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "User Class: suboption too long");
1923                 break;
1924             }
1925             subtree_2 = proto_tree_add_subtree(subtree, tvb, off+temp_optlen, subopt_len, ett_dhcpv6_userclass_option, &ti, "User Class suboption");
1926             proto_tree_add_item(subtree_2, hf_option_userclass_length, tvb, off + temp_optlen, 2, ENC_BIG_ENDIAN);
1927             proto_tree_add_item(subtree_2, hf_option_userclass_opaque_data, tvb, off + temp_optlen + 2, subopt_len - 2, ENC_NA);
1928 
1929             temp_optlen += subopt_len;
1930         }
1931         break;
1932     }
1933     case OPTION_NTP_SERVER:
1934         if (optlen < 4) {
1935             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NTP Server: malformed option");
1936             break;
1937         }
1938         temp_optlen = 0;
1939         while (optlen > temp_optlen) {
1940             subopt_type = tvb_get_ntohs(tvb, off + temp_optlen);
1941             subopt_len = tvb_get_ntohs(tvb,  off + 2 + temp_optlen);
1942             if (subopt_len > optlen - temp_optlen) {
1943                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NTP Server: suboption too long");
1944                 break;
1945             }
1946             subtree_2 = proto_tree_add_subtree(subtree, tvb, off+temp_optlen, 4 + subopt_len, ett_dhcpv6_netserver_option, &ti,
1947                                      val_to_str(subopt_type, ntp_server_opttype_vals, "NTP Server suboption %u"));
1948             proto_tree_add_item(subtree_2, hf_option_ntpserver_type,   tvb, off + temp_optlen,     2, ENC_BIG_ENDIAN);
1949             proto_tree_add_item(subtree_2, hf_option_ntpserver_length, tvb, off + temp_optlen + 2, 2, ENC_BIG_ENDIAN);
1950             temp_optlen += 4;
1951             switch (subopt_type) {
1952             case NTP_SUBOPTION_SRV_ADDR:
1953                 proto_tree_add_item(subtree_2, hf_option_ntpserver_addr,    tvb, off + temp_optlen, 16, ENC_NA);
1954                 break;
1955             case NTP_SUBOPTION_MC_ADDR:
1956                 proto_tree_add_item(subtree_2, hf_option_ntpserver_mc_addr, tvb, off + temp_optlen, 16, ENC_NA);
1957                 break;
1958             case NTP_SUBOPTION_SRV_FQDN:
1959                 /* RFC 5906: section 4.3: "Internationalized domain names are not allowed ..." */
1960                 dhcpv6_domain(subtree_2, ti, pinfo, hf_option_ntpserver_fqdn, tvb, off + temp_optlen, subopt_len);
1961                 break;
1962             }
1963 
1964             temp_optlen += subopt_len;
1965         }
1966         break;
1967     case OPTION_S46_RULE:
1968     {
1969         guint8 ipv4_pref_len, ipv6_pref_len;
1970         int ipv6_pref_len_bytes;
1971 
1972         if (optlen < 8) {
1973             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_RULE: malformed option");
1974             break;
1975         }
1976 
1977         /*  0 1 2 3 4 5 6 7
1978          * +-+-+-+-+-+-+-+-+
1979          * |Reserved     |F|
1980          * +-+-+-+-+-+-+-+-+
1981          */
1982         proto_tree_add_bitmask(subtree, tvb, off, hf_option_s46_rule_flags, ett_dhcpv6_s46_rule_flags, dhcpv6_s46_rule_flags_fields, ENC_BIG_ENDIAN);
1983         proto_tree_add_item(subtree, hf_option_s46_rule_ea_len, tvb, off + 1, 1, ENC_BIG_ENDIAN);
1984         proto_tree_add_item(subtree, hf_option_s46_rule_ipv4_pref_len, tvb, off + 2, 1, ENC_BIG_ENDIAN);
1985         ipv4_pref_len = tvb_get_guint8(tvb, off + 2);
1986 
1987         if (ipv4_pref_len > 32) {
1988             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_RULE: malformed option");
1989             break;
1990         }
1991 
1992         proto_tree_add_item(subtree, hf_option_s46_rule_ipv4_prefix, tvb, off + 3, 4, ENC_NA);
1993         proto_tree_add_item(subtree, hf_option_s46_rule_ipv6_pref_len, tvb, off + 7, 1, ENC_BIG_ENDIAN);
1994         ipv6_pref_len = tvb_get_guint8(tvb, off + 7);
1995 
1996         if (ipv6_pref_len > 128) {
1997             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_RULE: malformed option");
1998             break;
1999         }
2000 
2001         ipv6_pref_len_bytes =
2002             dissect_dhcpv6_s46_ipv6_prefix(tvb, hf_option_s46_rule_ipv6_prefix, off + 8, ipv6_pref_len, subtree);
2003 
2004         temp_optlen = 8 + ipv6_pref_len_bytes;
2005         while ((optlen - temp_optlen) > 0) {
2006             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2007                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2008             if (*at_end) {
2009                 /* Bad option - just skip to the end */
2010                 temp_optlen = optlen;
2011             }
2012         }
2013     }
2014     break;
2015     case OPTION_S46_BR:
2016         if (optlen != 16) {
2017             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_BR: malformed option");
2018             break;
2019         }
2020 
2021         proto_tree_add_item(subtree, hf_option_s46_br_address, tvb, off, 16, ENC_NA);
2022         break;
2023     case OPTION_S46_DMR:
2024     {
2025         guint8 dmr_pref_len;
2026 
2027         if (optlen < 1 || optlen > 17) {
2028             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_DMR: malformed option");
2029             break;
2030         }
2031 
2032         proto_tree_add_item(subtree, hf_option_s46_dmr_pref_len, tvb, off, 1, ENC_BIG_ENDIAN);
2033         dmr_pref_len = tvb_get_guint8(tvb, off);
2034 
2035         if (dmr_pref_len > 128) {
2036             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_DMR: malformed option");
2037             break;
2038         }
2039 
2040         dissect_dhcpv6_s46_ipv6_prefix(tvb, hf_option_s46_dmr_prefix, off + 1, dmr_pref_len, subtree);
2041     }
2042     break;
2043     case OPTION_S46_V4V6BIND:
2044     {
2045         guint8 ipv6_pref_len;
2046         int ipv6_pref_len_bytes;
2047 
2048         if (optlen < 5) {
2049             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_V4V6BIND: malformed option");
2050             break;
2051         }
2052 
2053         proto_tree_add_item(subtree, hf_option_s46_v4v6bind_ipv4_address, tvb, off, 4, ENC_NA);
2054         proto_tree_add_item(subtree, hf_option_s46_v4v6bind_ipv6_pref_len, tvb, off + 4, 1, ENC_BIG_ENDIAN);
2055         ipv6_pref_len = tvb_get_guint8(tvb, off + 4);
2056 
2057         if (ipv6_pref_len > 128) {
2058             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_V4V6BIND: malformed option");
2059             break;
2060         }
2061 
2062         ipv6_pref_len_bytes =
2063             dissect_dhcpv6_s46_ipv6_prefix(tvb, hf_option_s46_v4v6bind_ipv6_prefix, off + 5, ipv6_pref_len, subtree);
2064 
2065         temp_optlen = 5 + ipv6_pref_len_bytes;
2066         while ((optlen - temp_optlen) > 0) {
2067             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2068                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2069             if (*at_end) {
2070                 /* Bad option - just skip to the end */
2071                 temp_optlen = optlen;
2072             }
2073         }
2074     }
2075     break;
2076     case OPTION_S46_PORTPARAMS:
2077     {
2078         guint16 psid;
2079         guint8 offset, psid_len;
2080 
2081         if (optlen != 4) {
2082             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_PORTPARAMS: malformed option");
2083             break;
2084         }
2085 
2086         proto_tree_add_item(subtree, hf_option_s46_portparam_offset, tvb, off, 1, ENC_BIG_ENDIAN);
2087         offset = tvb_get_guint8(tvb, off);
2088 
2089         if (offset > 15) {
2090             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_PORTPARAMS: malformed option");
2091             break;
2092         }
2093 
2094         proto_tree_add_item(subtree, hf_option_s46_portparam_psid_len, tvb, off + 1, 1, ENC_BIG_ENDIAN);
2095         psid_len = tvb_get_guint8(tvb, off + 1);
2096 
2097         if (psid_len > 16) {
2098             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "S46_PORTPARAMS: malformed option");
2099             break;
2100         }
2101 
2102         psid = tvb_get_ntohs(tvb, off + 2);
2103         proto_tree_add_uint(subtree, hf_option_s46_portparam_psid, tvb, off + 2, 2, psid >> (16 - psid_len));
2104     }
2105     break;
2106     case OPTION_S46_CONT_MAPE:
2107     case OPTION_S46_CONT_MAPT:
2108     case OPTION_S46_CONT_LW:
2109         temp_optlen = 0;
2110         while ((optlen - temp_optlen) > 0) {
2111             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2112                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2113             if (*at_end) {
2114                 /* Bad option - just skip to the end */
2115                 temp_optlen = optlen;
2116             }
2117         }
2118         break;
2119     case OPTION_IA_NA:
2120     case OPTION_IA_PD:
2121         if (optlen < 12) {
2122             if (opttype == OPTION_IA_NA)
2123                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_NA: malformed option");
2124             else
2125                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_PD: malformed option");
2126             break;
2127         }
2128         proto_tree_add_string(subtree, hf_iaid, tvb, off,
2129                                     4, tvb_arphrdaddr_to_str(tvb, off, 4, opttype));  /* XXX: IAID is opaque ? review ... */
2130         if (tvb_get_ntohl(tvb, off+4) == DHCPV6_LEASEDURATION_INFINITY) {
2131             proto_tree_add_uint_format_value(subtree, hf_iaid_t1, tvb, off+4,
2132                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
2133         } else {
2134             proto_tree_add_item(subtree, hf_iaid_t1, tvb, off+4,
2135                                     4, ENC_BIG_ENDIAN);
2136         }
2137 
2138         if (tvb_get_ntohl(tvb, off+8) == DHCPV6_LEASEDURATION_INFINITY) {
2139             proto_tree_add_uint_format_value(subtree, hf_iaid_t2, tvb, off+8,
2140                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
2141         } else {
2142             proto_tree_add_item(subtree, hf_iaid_t2, tvb, off+8,
2143                                     4, ENC_BIG_ENDIAN);
2144         }
2145 
2146         temp_optlen = 12;
2147         while ((optlen - temp_optlen) > 0) {
2148             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2149                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2150             if (*at_end) {
2151                 /* Bad option - just skip to the end */
2152                 temp_optlen = optlen;
2153             }
2154         }
2155         break;
2156     case OPTION_IA_TA:
2157         if (optlen < 4) {
2158             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_TA: malformed option");
2159             break;
2160         }
2161         proto_tree_add_string(subtree, hf_iata, tvb, off,
2162                                     4, tvb_arphrdaddr_to_str(tvb, off, 4, opttype));  /* XXX: IAID is opaque ? review ... */
2163         temp_optlen = 4;
2164         while ((optlen - temp_optlen) > 0) {
2165             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2166                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2167             if (*at_end) {
2168                 /* Bad option - just skip to the end */
2169                 temp_optlen = optlen;
2170             }
2171         }
2172         break;
2173     case OPTION_IAADDR:
2174     {
2175         guint32 preferred_lifetime, valid_lifetime;
2176 
2177         if (optlen < 24) {
2178             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_TA: malformed option");
2179             break;
2180         }
2181 
2182         proto_tree_add_item(subtree, hf_iaaddr_ip, tvb, off, 16, ENC_NA);
2183         col_append_fstr(pinfo->cinfo, COL_INFO, "IAA: %s ", tvb_ip6_to_str(pinfo->pool, tvb, off));
2184 
2185         preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
2186         valid_lifetime = tvb_get_ntohl(tvb, off + 20);
2187 
2188         if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
2189             proto_tree_add_uint_format_value(subtree, hf_iaaddr_pref_lifetime, tvb, off+16,
2190                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
2191         } else {
2192             proto_tree_add_item(subtree, hf_iaaddr_pref_lifetime, tvb, off+16,
2193                                     4, ENC_BIG_ENDIAN);
2194         }
2195         if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
2196             proto_tree_add_uint_format(subtree, hf_iaaddr_valid_lifetime, tvb, off+20,
2197                                     4, DHCPV6_LEASEDURATION_INFINITY, "Preferred lifetime: infinity");
2198         } else {
2199             proto_tree_add_item(subtree, hf_iaaddr_valid_lifetime, tvb, off+20,
2200                                     4, ENC_BIG_ENDIAN);
2201         }
2202 
2203         temp_optlen = 24;
2204         while ((optlen - temp_optlen) > 0) {
2205             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2206                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2207             if (*at_end) {
2208                 /* Bad option - just skip to the end */
2209                 temp_optlen = optlen;
2210             }
2211         }
2212     }
2213     break;
2214     case OPTION_ORO:
2215     case OPTION_ERO:
2216         for (i = 0; i < optlen; i += 2) {
2217             proto_tree_add_item(subtree, hf_requested_option_code, tvb, off+i,
2218                                     2, ENC_BIG_ENDIAN);
2219         }
2220         break;
2221     case OPTION_PREFERENCE:
2222         if (optlen != 1) {
2223             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "PREFERENCE: malformed option");
2224             break;
2225         }
2226         proto_tree_add_item(subtree, hf_option_preference, tvb, off, 1, ENC_BIG_ENDIAN);
2227         break;
2228     case OPTION_ELAPSED_TIME:
2229         if (optlen != 2) {
2230             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "ELAPSED-TIME: malformed option");
2231             break;
2232         }
2233 
2234         temp_optlen = tvb_get_ntohs(tvb, off);
2235         proto_tree_add_uint(subtree, hf_elapsed_time, tvb, off, 2, temp_optlen*10);
2236         break;
2237     case OPTION_RELAY_MSG:
2238         if (optlen == 0) {
2239             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RELAY-MSG: malformed option");
2240         } else {
2241             /* here, we should dissect a full DHCP message */
2242             dissect_dhcpv6(tvb, pinfo, subtree, off, off + optlen, hpi);
2243         }
2244         break;
2245     case OPTION_AUTH:
2246         if (optlen < 11) {
2247             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "AUTH: malformed option");
2248             break;
2249         }
2250 
2251         proto_tree_add_item(subtree, hf_auth_protocol, tvb, off, 1, ENC_BIG_ENDIAN);
2252         proto_tree_add_item_ret_uint(subtree, hf_auth_algorithm, tvb, off+1, 1, ENC_BIG_ENDIAN, &algorithm);
2253         proto_tree_add_item(subtree, hf_auth_rdm, tvb, off+2, 1, ENC_BIG_ENDIAN);
2254         proto_tree_add_item(subtree, hf_auth_replay_detection, tvb, off+3, 8, ENC_NA);
2255         if (optlen > 11+20 && algorithm == 1) {  // RFC 3315, HMAC-MD5 (16) + Key ID (4) => 20 bytes
2256             if (optlen-11-20 < 256) {
2257                 proto_tree_add_item(subtree, hf_auth_realm, tvb, off+11, optlen-11-20, ENC_ASCII|ENC_NA);
2258             } else {
2259                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DHCP realm: probably malformed option");
2260             }
2261             proto_tree_add_item(subtree, hf_auth_key_id, tvb, off+optlen-16-4, 4, ENC_BIG_ENDIAN);
2262             proto_tree_add_item(subtree, hf_auth_md5_data, tvb, off+optlen-16, 16, ENC_NA);
2263         } else {
2264             proto_tree_add_item(subtree, hf_auth_info, tvb, off+11, optlen-11, ENC_NA);
2265         }
2266         break;
2267     case OPTION_UNICAST:
2268         if (optlen != 16) {
2269             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "UNICAST: malformed option");
2270             break;
2271         }
2272         proto_tree_add_item(subtree, hf_opt_unicast, tvb, off, 16, ENC_NA);
2273         break;
2274     case OPTION_STATUS_CODE:
2275         proto_tree_add_item(subtree, hf_opt_status_code, tvb, off, 2, ENC_BIG_ENDIAN);
2276         if (optlen > 2)
2277             proto_tree_add_item(subtree, hf_opt_status_msg, tvb, off+2, optlen - 2, ENC_ASCII|ENC_NA);
2278         break;
2279     case OPTION_VENDOR_CLASS:
2280         if (optlen < 4) {
2281             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "VENDOR_CLASS: malformed option");
2282             break;
2283         }
2284         proto_tree_add_item(subtree, hf_vendorclass_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
2285         if (optlen > 4)
2286             proto_tree_add_item(subtree, hf_vendorclass_data, tvb, off+6, optlen-6, ENC_ASCII|ENC_NA);
2287         break;
2288     case OPTION_VENDOR_OPTS:
2289         if (optlen < 4) {
2290             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "VENDOR_OPTS: malformed option");
2291             break;
2292         }
2293 
2294         enterprise_no = tvb_get_ntohl(tvb, off);
2295         ti = proto_tree_add_item(subtree, hf_vendoropts_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
2296 
2297         if (enterprise_no == 4491) {
2298             dissect_cablelabs_specific_opts(subtree, ti, pinfo, tvb, off+4, optlen-4);
2299         } else {
2300             int optoffset = 0;
2301 
2302             while ((optlen - 4 - optoffset) > 0) {
2303                 int olen = tvb_get_ntohs(tvb, off + optoffset + 6);
2304                 subtree_2 = proto_tree_add_subtree(subtree, tvb, off + optoffset + 4,
2305                                          4 + olen, ett_dhcpv6_option_vsoption, NULL, "option");
2306                 proto_tree_add_item(subtree_2, hf_vendoropts_enterprise_option_code, tvb, off + optoffset + 4, 2, ENC_BIG_ENDIAN);
2307                 proto_tree_add_item(subtree_2, hf_vendoropts_enterprise_option_length, tvb, off + optoffset + 6, 2, ENC_BIG_ENDIAN);
2308                 proto_tree_add_item(subtree_2, hf_vendoropts_enterprise_option_data, tvb, off + optoffset + 8, olen, ENC_NA);
2309                 optoffset += (4 + olen);
2310             }
2311         }
2312         break;
2313     case OPTION_INTERFACE_ID:
2314     {
2315         if (optlen == 0) {
2316             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "INTERFACE_ID: malformed option");
2317             break;
2318         }
2319 
2320         if (cablelabs_interface_id) {
2321             gint namelen = tvb_strnlen(tvb, off, optlen)+1;
2322             if (namelen == 0) {
2323                 proto_tree_add_item(subtree, hf_cablelabs_interface_id, tvb, off, optlen, ENC_ASCII|ENC_NA);
2324             } else {
2325                 proto_tree_add_item(subtree, hf_cablelabs_interface_id, tvb, off, namelen-1, ENC_ASCII|ENC_NA);
2326 
2327                 temp_optlen = optlen - namelen;
2328                 off += namelen;
2329                 if (temp_optlen >= 6)
2330                     proto_tree_add_string(subtree, hf_cablelabs_interface_id_link_address, tvb, off, temp_optlen, tvb_arphrdaddr_to_str(tvb, off, 6, ARPHRD_ETHER));
2331             }
2332         } else {
2333             proto_tree_add_item(subtree, hf_interface_id, tvb, off, optlen, ENC_NA);
2334         }
2335     }
2336     break;
2337     case OPTION_RECONF_MSG:
2338         if (optlen != 1) {
2339             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RECONF_MSG: malformed option");
2340             break;
2341         }
2342 
2343         proto_tree_add_item(subtree, hf_reconf_msg, tvb, off, 1, ENC_BIG_ENDIAN);
2344         break;
2345     case OPTION_RECONF_ACCEPT:
2346         if (optlen)
2347             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RECONF_ACCEPT: malformed option");
2348         break;
2349     case OPTION_SIP_SERVER_D:
2350         if (optlen > 0) {
2351             subtree_2 = proto_tree_add_subtree(subtree, tvb, off, optlen, ett_dhcpv6_sip_server_domain_search_list_option, &ti, "SIP Servers Domain Search List");
2352             dhcpv6_domain(subtree_2, ti, pinfo, hf_sip_server_domain_search_fqdn, tvb, off, optlen);
2353         }
2354         break;
2355     case OPTION_SIP_SERVER_A:
2356         if (optlen % 16) {
2357             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "SIP servers address: malformed option");
2358             break;
2359         }
2360 
2361         for (i = 0; i < optlen; i += 16)
2362             proto_tree_add_item(subtree, hf_sip_server_a, tvb, off + i, 16, ENC_NA);
2363         break;
2364     case OPTION_DNS_SERVERS:
2365         if (optlen % 16) {
2366             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DNS servers address: malformed option");
2367             break;
2368         }
2369 
2370         for (i = 0; i < optlen; i += 16) {
2371             ti = proto_tree_add_item(subtree, hf_dns_servers, tvb, off + i, 16, ENC_NA);
2372             proto_item_prepend_text(ti, " %d ", i/16 + 1);
2373         }
2374         break;
2375 
2376     case OPTION_DOMAIN_LIST:
2377         if (optlen > 0) {
2378             subtree_2 = proto_tree_add_subtree(subtree, tvb, off, optlen, ett_dhcpv6_dns_domain_search_list_option, &ti,
2379                             "Domain name suffix search list");
2380             dhcpv6_domain(subtree_2, ti, pinfo, hf_domain_search_list_entry, tvb, off, optlen);
2381         }
2382         break;
2383 
2384     /* NIS...: RFC 3898 */
2385     case OPTION_NIS_SERVERS:
2386         if (optlen % 16) {
2387             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NIS servers address: malformed option");
2388             break;
2389         }
2390         for (i = 0; i < optlen; i += 16)
2391             proto_tree_add_item(subtree, hf_nis_servers, tvb, off + i, 16, ENC_NA);
2392         break;
2393     case OPTION_NISP_SERVERS:
2394         if (optlen % 16) {
2395             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NISP servers address: malformed option");
2396             break;
2397         }
2398         for (i = 0; i < optlen; i += 16)
2399             proto_tree_add_item(subtree, hf_nisp_servers, tvb, off + i, 16, ENC_NA);
2400         break;
2401     case OPTION_NIS_DOMAIN_NAME:
2402         if (optlen > 0) {
2403             subtree_2 = proto_tree_add_subtree(subtree, tvb, off, optlen, ett_dhcpv6_nis_domain_name_option, &ti, "nis-domain-name");
2404             dhcpv6_domain(subtree_2, ti, pinfo, hf_nis_fqdn, tvb, off, optlen);
2405         }
2406         break;
2407     case OPTION_NISP_DOMAIN_NAME:
2408         if (optlen > 0) {
2409             subtree_2 = proto_tree_add_subtree(subtree, tvb, off, optlen, ett_dhcpv6_nisp_domain_name_option, &ti, "nisp-domain-name");
2410             dhcpv6_domain(subtree_2, ti, pinfo, hf_nisp_fqdn, tvb, off, optlen);
2411         }
2412         break;
2413 
2414     case OPTION_SNTP_SERVERS:
2415         /* Deprecated as of RFC 5908 */
2416         if (optlen % 16) {
2417             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "SNTP servers address: malformed option");
2418             break;
2419         }
2420         for (i = 0; i < optlen; i += 16){
2421             ti = proto_tree_add_item(subtree, hf_sntp_servers, tvb, off + i, 16, ENC_NA);
2422             proto_item_prepend_text(ti, " %d ", i/16 + 1);
2423         }
2424         break;
2425     case OPTION_LIFETIME:
2426         if (optlen != 4) {
2427             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LIFETIME: malformed option");
2428             break;
2429         }
2430         proto_tree_add_item(subtree, hf_opt_lifetime, tvb, off, 4, ENC_BIG_ENDIAN);
2431         break;
2432 
2433     /* BCMCS...: RFC 4280 */
2434     case OPTION_BCMCS_SERVER_D:
2435         if (optlen > 0) {
2436             subtree_2 = proto_tree_add_subtree(subtree, tvb, off, optlen, ett_dhcpv6_bcmcs_servers_domain_search_list_option, &ti, "BCMCS Servers Domain Search List");
2437             dhcpv6_domain(subtree_2, ti, pinfo, hf_bcmcs_servers_fqdn, tvb, off, optlen);
2438         }
2439         break;
2440     case OPTION_BCMCS_SERVER_A:
2441         if (optlen % 16) {
2442             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "BCMCS servers address: malformed option");
2443             break;
2444         }
2445         for (i = 0; i < optlen; i += 16)
2446             proto_tree_add_item(subtree, hf_bcmcs_servers_a, tvb, off + i, 16, ENC_NA);
2447         break;
2448 
2449     case OPTION_REMOTE_ID:
2450         if (optlen < 4) {
2451             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "REMOTE_ID: malformed option");
2452             break;
2453         }
2454         proto_tree_add_item(subtree, hf_remoteid_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
2455         off += 4;
2456         proto_tree_add_item(subtree, hf_remoteid_enterprise_id, tvb, off, optlen - 4, ENC_NA);
2457         break;
2458     case OPTION_SUBSCRIBER_ID:
2459         if (optlen == 0) {
2460             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "SUBSCRIBER_ID: malformed option");
2461             break;
2462         }
2463         proto_tree_add_item(subtree, hf_subscriber_id, tvb, off, optlen, ENC_ASCII|ENC_NA);
2464         break;
2465     case OPTION_CLIENT_FQDN:
2466         if (optlen < 1) {
2467             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "FQDN: malformed option");
2468         } else {
2469             guint8      flags;
2470             proto_item *fi = NULL;
2471             proto_tree *flags_tree = NULL;
2472             char       *flags_str= NULL, *suffix;
2473             gboolean    is_client;
2474             proto_item *exi;
2475             proto_tree *ex_subtree;
2476 
2477             /*
2478              * A client MUST only include the OPTION_CLIENT_FQDN in SOLICIT, REQUEST, RENEW, or REBIND messages.
2479              * [RFC 4704 Section 5.]
2480              * Servers MUST only include a OPTION_CLIENT_FQDN in ADVERTISE and REPLY messages.
2481              * [RFC 4704 Section 6.]
2482              */
2483             if (msgtype == SOLICIT || msgtype == REQUEST || msgtype == RENEW || msgtype == REBIND)
2484                 is_client = TRUE;
2485             else if (msgtype == ADVERTISE || msgtype == REPLY)
2486                 is_client = FALSE;
2487             else {
2488                 exi = proto_tree_add_uint_format(subtree, hf_clientfqdn_bad_msgtype, tvb, off-4, 1,
2489                         msgtype,
2490                         "Only the following message types are permitted to use OPTION_CLIENT_FQDN:\n"
2491                         "SOLICIT, REQUEST, RENEW, REBIND, ADVERTISE, and REPLY");
2492                 ex_subtree = proto_item_add_subtree(exi, ett_clientfqdn_expert);
2493                 proto_tree_add_expert(ex_subtree, pinfo, &ei_dhcpv6_clientfqdn_bad_msgtype, tvb, off-4, 1);
2494                 break;
2495             }
2496             /*
2497              * +-----+-+-+-+
2498              * | MBZ |N|O|S|
2499              * +-----+-+-+-+
2500              *
2501              * [RFC4704 Section 4.1]
2502              * "The 'S' bit indicates whether the server SHOULD or SHOULD NOT perform the AAAA RR (FQDN-to-address)
2503              * DNS updates. A client sets the bit to 0 to indicate that the server SHOULD NOT perform the updates
2504              * and 1 to indicate that the server SHOULD perform the updates. The state of the bit in the reply from
2505              * the server indicates the action to be taken by the server; if it is 1 the server has taken
2506              * responsibility for AAAA RR updates for the FQDN.
2507              *
2508              * The 'O' bit indicates whether the server has overridden the client's preference for the 'S' bit.
2509              * A client MUST set this bit to 0. A server MUST set this bit to 1 if the "S" bit in its reply to the
2510              * client does not match the 'S' bit received from the client.
2511              *
2512              * The 'N' bit indicates whether the server SHOULD NOT perform any DNS updates. A client sets this bit to
2513              * 0 to request that the server SHOULD perform updates (the PTR RR and possibly the AAAA RR based on the
2514              * 'S' bit) 1 to request that the server SHOULD NOT perform any DNS updates. A server sets the 'N' bit to
2515              * indicate whether the server SHALL (0) or SHALL NOT (1) perform DNS updates. If the 'N' bit is 1, the
2516              * 'S' bit MUST be 0."
2517              */
2518             flags = tvb_get_guint8(tvb, off);
2519             suffix = "]";
2520 
2521             if (is_client) {
2522                 /*CLIENT*/
2523                 if ((flags & 0x5)==0) flags_str = "[CLIENT wants to update its AAAA RRs and SERVER to update its PTR RRs";
2524                 if ((flags & 0x5)==1) flags_str = "[CLIENT wants SERVER to update both its AAAA and PTR RRs";
2525                 if ((flags & 0x5)==4) flags_str = "[CLIENT prefers that the server not perform *any* DNS updates";
2526                 if ((flags & 0x5)==5) flags_str = "[ERROR: CLIENT prefers that the server not perform *any* DNS updates\n"
2527                                                   "        In which case the 'S' bit MUST be 0";
2528                 /* The client MUST set this bit to 0 (in that it is meaningless). */
2529             }
2530             else {
2531                 /*SERVER*/
2532                 if ((flags & 0x5)==0) flags_str = "[CLIENT SHALL update AAAA RRs; SERVER SHALL update PTR RRs";
2533                 if ((flags & 0x5)==1) flags_str = "[SERVER SHALL update both AAAA and PTR RRs";
2534                 if ((flags & 0x5)==4) flags_str = "[CLIENT SHALL update AAAA RRs; SERVER SHALL NOT perform any DNS updates";
2535                 if ((flags & 0x5)==5) flags_str = "[ERROR: SERVER SHALL NOT perform *any* DNS updates in which case "
2536                                                   "        the 'S' bit MUST be 0";
2537                 if ((flags & 0x2)==2
2538                 && ((flags & 0x5)==0 || (flags & 0x5)==1))
2539                     suffix = "]\n[Server has overridden the client's S bit]";
2540             }
2541             fi = proto_tree_add_uint_format(subtree, hf_clientfqdn_flags, tvb, off, 1, flags,
2542                     "Flags: 0x%02x  %s%s", flags, flags_str, suffix);
2543             flags_tree = proto_item_add_subtree(fi, ett_clientfqdn_flags);
2544 
2545         if (is_client) {
2546                 proto_tree_add_item(flags_tree, hf_clientfqdn_client_n, tvb, off, 1, ENC_BIG_ENDIAN);
2547                 proto_tree_add_item(flags_tree, hf_clientfqdn_client_s, tvb, off, 1, ENC_BIG_ENDIAN);
2548             }
2549             else {
2550                 proto_tree_add_item(flags_tree, hf_clientfqdn_server_n, tvb, off, 1, ENC_BIG_ENDIAN);
2551                 proto_tree_add_item(flags_tree, hf_clientfqdn_server_o, tvb, off, 1, ENC_BIG_ENDIAN);
2552                 proto_tree_add_item(flags_tree, hf_clientfqdn_server_s, tvb, off, 1, ENC_BIG_ENDIAN);
2553             }
2554             if ((flags & 0x5)==5)
2555                 proto_tree_add_expert(subtree, pinfo, &ei_dhcpv6_s_bit_should_be_zero, tvb, off, 1);
2556 
2557             dhcpv6_domain(subtree, option_item, pinfo, hf_client_fqdn, tvb, off+1, optlen-1);
2558         }
2559         break;
2560     case OPTION_PANA_AGENT:
2561         if (optlen % 16) {
2562             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "PANA agent address: malformed option");
2563             break;
2564         }
2565         for (i = 0; i < optlen; i += 16)
2566             proto_tree_add_item(subtree, hf_pana_agent, tvb, off + i, 16, ENC_NA);
2567         break;
2568     case OPTION_TIME_ZONE:
2569         if (optlen > 0)
2570             proto_tree_add_item(subtree, hf_opt_timezone, tvb, off, optlen, ENC_ASCII|ENC_NA);
2571         break;
2572     case OPTION_TZDB:
2573         if (optlen > 0)
2574             proto_tree_add_item(subtree, hf_opt_tzdb, tvb, off, optlen, ENC_ASCII|ENC_NA);
2575         break;
2576 
2577     case OPTION_MUDURL:
2578         if (optlen > 0)
2579             proto_tree_add_item(subtree, hf_opt_mudurl, tvb, off, optlen, ENC_ASCII|ENC_NA);
2580         break;
2581 
2582     case OPTION_LQ_QUERY:
2583     {
2584         guint8 query_type;
2585         if (optlen < 17) {
2586             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LQ-QUERY: malformed option");
2587             break;
2588         }
2589         query_type = tvb_get_guint8(tvb, off);
2590         ti = proto_tree_add_item(subtree, hf_lq_query, tvb, off, 1, ENC_BIG_ENDIAN);
2591         if ((protocol == proto_dhcpv6)           &&
2592             ((query_type == LQ_QUERY_RELAYID)      ||
2593              (query_type == LQ_QUERY_LINK_ADDRESS) ||
2594              (query_type == LQ_QUERY_REMOTEID))) {
2595             expert_add_info(pinfo, ti, &ei_dhcpv6_bulk_leasequery_bad_query_type);
2596         }
2597 
2598         proto_tree_add_item(subtree, hf_lq_query_link_address, tvb, off+1, 16, ENC_NA);
2599         temp_optlen = 17;
2600         while ((optlen - temp_optlen) > 0) {
2601             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2602                                          off + temp_optlen,
2603                                          off + optlen, at_end, protocol, hpi, msgtype);
2604             if (*at_end) {
2605                 /* Bad option - just skip to the end */
2606                 temp_optlen = optlen;
2607             }
2608         }
2609     }
2610     break;
2611     case OPTION_CLIENT_DATA:
2612         temp_optlen = 0;
2613         while ((optlen - temp_optlen) > 0) {
2614             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2615                                          off + temp_optlen,
2616                                          off + optlen, at_end, protocol, hpi, msgtype);
2617             if (*at_end) {
2618                 /* Bad option - just skip to the end */
2619                 temp_optlen = optlen;
2620             }
2621         }
2622         break;
2623     case OPTION_CLT_TIME:
2624         if (optlen != 4) {
2625             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "CLT_TIME: malformed option");
2626             break;
2627         }
2628 
2629         proto_tree_add_item(subtree, hf_clt_time, tvb, off, 4, ENC_BIG_ENDIAN);
2630         break;
2631     case OPTION_LQ_RELAY_DATA:
2632         if (optlen < 16) {
2633             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LQ_RELAY_DATA: malformed option");
2634             break;
2635         }
2636 
2637         proto_tree_add_item(subtree, hf_lq_relay_data_peer_addr, tvb, off, 16, ENC_NA);
2638         proto_tree_add_item(subtree, hf_lq_relay_data_msg, tvb, off+16, optlen - 16, ENC_ASCII|ENC_NA);
2639         break;
2640     case OPTION_LQ_CLIENT_LINK:
2641         if (optlen % 16) {
2642             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LQ client links address: malformed option");
2643             break;
2644         }
2645         for (i = 0; i < optlen; i += 16)
2646             proto_tree_add_item(subtree, hf_lq_client_link, tvb, off + i, 16, ENC_NA);
2647         break;
2648     case OPTION_CAPWAP_AC_V6:
2649         if (optlen % 16) {
2650             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "CAPWAP Access Controllers address: malformed option");
2651             break;
2652         }
2653         for (i = 0; i < optlen; i += 16)
2654             proto_tree_add_item(subtree, hf_capwap_ac_v6, tvb, off + i, 16, ENC_NA);
2655         break;
2656 
2657     case OPTION_AFTR_NAME:
2658         dhcpv6_domain(subtree, option_item, pinfo, hf_aftr_name, tvb, off, optlen);
2659         break;
2660     case OPTION_IAPREFIX:
2661         if (optlen < 25) {
2662             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IAPREFIX: malformed option");
2663             break;
2664         }
2665 
2666         if (tvb_get_ntohl(tvb, off) == DHCPV6_LEASEDURATION_INFINITY) {
2667             proto_tree_add_uint_format_value(subtree, hf_iaprefix_pref_lifetime, tvb, off,
2668                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
2669         } else {
2670             proto_tree_add_item(subtree, hf_iaprefix_pref_lifetime, tvb, off,
2671                                     4, ENC_BIG_ENDIAN);
2672         }
2673         if (tvb_get_ntohl(tvb, off + 4) == DHCPV6_LEASEDURATION_INFINITY) {
2674             proto_tree_add_uint_format_value(subtree, hf_iaprefix_valid_lifetime, tvb, off+4,
2675                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
2676         } else {
2677             proto_tree_add_item(subtree, hf_iaprefix_valid_lifetime, tvb, off+4,
2678                                     4, ENC_BIG_ENDIAN);
2679         }
2680         proto_tree_add_item(subtree, hf_iaprefix_pref_len, tvb, off+8, 1, ENC_BIG_ENDIAN);
2681         proto_tree_add_item(subtree, hf_iaprefix_pref_addr, tvb, off+9, 16, ENC_NA);
2682         temp_optlen = 25;
2683         while ((optlen - temp_optlen) > 0) {
2684             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
2685                                          off+temp_optlen, off + optlen, at_end, protocol, hpi, msgtype);
2686             if (*at_end) {
2687                 /* Bad option - just skip to the end */
2688                 temp_optlen = optlen;
2689             }
2690         }
2691         break;
2692     case OPTION_MIP6_HA:
2693         if (optlen != 16) {
2694             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "MIP6_HA: malformed option");
2695             break;
2696         }
2697         proto_tree_add_item(subtree, hf_mip6_ha, tvb, off, 16, ENC_NA);
2698         break;
2699     case OPTION_MIP6_HOA:
2700         if (optlen != 16) {
2701             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "MIP6_HOA: malformed option");
2702             break;
2703         }
2704 
2705         proto_tree_add_item(subtree, hf_mip6_hoa, tvb, off, 16, ENC_NA);
2706         break;
2707     case OPTION_NAI:
2708         if (optlen < 4) {
2709             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NAI: malformed option");
2710             break;
2711         }
2712         proto_tree_add_item(subtree, hf_nai, tvb, off, optlen - 2, ENC_ASCII|ENC_NA);
2713         break;
2714     case OPTION_PD_EXCLUDE:
2715         if ((optlen < 2) || (optlen > 17)) {
2716             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "PD_EXCLUDE: malformed option");
2717             break;
2718         }
2719         proto_tree_add_item(subtree, hf_pd_exclude_pref_len, tvb, off, 1, ENC_BIG_ENDIAN);
2720         proto_tree_add_item(subtree, hf_pd_exclude_subnet_id , tvb, off+1, optlen-1, ENC_NA);
2721         break;
2722     case OPTION_CAPTIVE_PORTAL:{
2723         proto_item *ti_cp;
2724         ti_cp = proto_tree_add_item(subtree, hf_option_captive_portal, tvb, off, optlen, ENC_ASCII|ENC_NA);
2725         proto_item_set_url(ti_cp);
2726         break;
2727         }
2728     case OPTION_S46_PRIORITY:
2729         temp_optlen = optlen;
2730         while (temp_optlen >= 2) {
2731             proto_tree_add_item(subtree, hf_option_s46_option_code, tvb, off, 2, ENC_BIG_ENDIAN);
2732             temp_optlen -= 2;
2733             off += 2;
2734         }
2735         break;
2736     case OPTION_F_BINDING_STATUS:
2737         if (optlen != 1) {
2738             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2739             break;
2740         }
2741         proto_tree_add_item(subtree, hf_option_failover_binding_status, tvb, off, 1, ENC_BIG_ENDIAN);
2742         break;
2743     case OPTION_F_CONNECT_FLAGS:
2744         if (optlen != 2) {
2745             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2746             break;
2747         }
2748         proto_tree_add_bitmask(subtree, tvb, off, hf_option_failover_connect_flags, ett_dhcpv6_failover_connect_flags, dhcpv6_failover_connect_flags_fields, ENC_BIG_ENDIAN);
2749         break;
2750     case OPTION_F_DNS_HOST_NAME:
2751         {
2752         const gchar *dns_name;
2753         gint dns_name_len;
2754 
2755         get_dns_name(tvb, off, optlen, off, &dns_name, &dns_name_len);
2756         proto_tree_add_string(subtree, hf_option_failover_dns_hostname, tvb, off, optlen, format_text(pinfo->pool, dns_name, dns_name_len));
2757         break;
2758         }
2759     case OPTION_F_DNS_ZONE_NAME:
2760         {
2761         const gchar *dns_name;
2762         gint dns_name_len;
2763 
2764         get_dns_name(tvb, off, optlen, off, &dns_name, &dns_name_len);
2765         proto_tree_add_string(subtree, hf_option_failover_dns_zonename, tvb, off, optlen, format_text(pinfo->pool, dns_name, dns_name_len));
2766         break;
2767         }
2768     case OPTION_F_DNS_FLAGS:
2769         if (optlen != 2) {
2770             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2771             break;
2772         }
2773         proto_tree_add_bitmask(subtree, tvb, off, hf_option_failover_dns_flags, ett_dhcpv6_failover_dns_flags, dhcpv6_failover_dns_flags_fields, ENC_BIG_ENDIAN);
2774         break;
2775     case OPTION_F_EXPIRATION_TIME:
2776         if (optlen != 4) {
2777             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2778             break;
2779         }
2780         proto_tree_add_item(subtree, hf_option_failover_expiration_time, tvb, off, 4, ENC_BIG_ENDIAN);
2781         break;
2782     case OPTION_F_MAX_UNACKED_BNDUPD:
2783         if (optlen != 4) {
2784             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2785             break;
2786         }
2787         proto_tree_add_item(subtree, hf_option_failover_max_unacked_bndupd, tvb, off, 4, ENC_BIG_ENDIAN);
2788         break;
2789     case OPTION_F_MCLT:
2790         if (optlen != 4) {
2791             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2792             break;
2793         }
2794         proto_tree_add_item(subtree, hf_option_failover_mclt, tvb, off, 4, ENC_BIG_ENDIAN);
2795         break;
2796     case OPTION_F_PARTNER_LIFETIME:
2797         if (optlen != 4) {
2798             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2799             break;
2800         }
2801         proto_tree_add_item(subtree, hf_option_failover_partner_lifetime, tvb, off, 4, ENC_BIG_ENDIAN);
2802         break;
2803     case OPTION_F_PARTNER_LIFETIME_SENT:
2804         if (optlen != 4) {
2805             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2806             break;
2807         }
2808         proto_tree_add_item(subtree, hf_option_failover_partner_lifetime_sent, tvb, off, 4, ENC_BIG_ENDIAN);
2809         break;
2810     case OPTION_F_PARTNER_DOWN_TIME:
2811         if (optlen != 4) {
2812             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2813             break;
2814         }
2815         proto_tree_add_item(subtree, hf_option_failover_partner_downtime, tvb, off, 4, ENC_BIG_ENDIAN);
2816         break;
2817     case OPTION_F_PARTNER_RAW_CLT_TIME:
2818         if (optlen != 4) {
2819             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2820             break;
2821         }
2822         proto_tree_add_item(subtree, hf_option_failover_partner_raw_clt_time, tvb, off, 4, ENC_BIG_ENDIAN);
2823         break;
2824     case OPTION_F_PROTOCOL_VERSION:
2825         if (optlen != 4) {
2826             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2827             break;
2828         }
2829         proto_tree_add_item(subtree, hf_option_failover_major_version, tvb, off, 2, ENC_BIG_ENDIAN);
2830         proto_tree_add_item(subtree, hf_option_failover_minor_version, tvb, off+2, 2, ENC_BIG_ENDIAN);
2831         break;
2832     case OPTION_F_KEEPALIVE_TIME:
2833         if (optlen != 4) {
2834             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2835             break;
2836         }
2837         proto_tree_add_item(subtree, hf_option_failover_keepalive_time, tvb, off, 4, ENC_BIG_ENDIAN);
2838         break;
2839     case OPTION_F_RECONFIGURE_DATA:
2840         if (optlen < 4) {
2841             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2842             break;
2843         }
2844         proto_tree_add_item(subtree, hf_option_failover_reconfigure_time, tvb, off, 4, ENC_BIG_ENDIAN);
2845         proto_tree_add_item(subtree, hf_option_failover_reconfigure_key, tvb, off+4, optlen-4, ENC_NA);
2846         break;
2847     case OPTION_F_RELATIONSHIP_NAME:
2848         proto_tree_add_item(subtree, hf_option_failover_relationship_name, tvb, off, optlen, ENC_UTF_8|ENC_NA);
2849         break;
2850     case OPTION_F_SERVER_FLAGS:
2851         if (optlen != 1) {
2852             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2853             break;
2854         }
2855         proto_tree_add_bitmask(subtree, tvb, off, hf_option_failover_server_flags, ett_dhcpv6_failover_server_flags, dhcpv6_failover_server_flags_fields, ENC_BIG_ENDIAN);
2856         break;
2857     case OPTION_F_SERVER_STATE:
2858         if (optlen != 1) {
2859             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2860             break;
2861         }
2862         proto_tree_add_item(subtree, hf_option_failover_server_state, tvb, off, 1, ENC_BIG_ENDIAN);
2863         break;
2864     case OPTION_F_START_TIME_OF_STATE:
2865         if (optlen != 4) {
2866             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2867             break;
2868         }
2869         proto_tree_add_item(subtree, hf_option_failover_start_time_of_state, tvb, off, 4, ENC_BIG_ENDIAN);
2870         break;
2871     case OPTION_F_STATE_EXPIRATION_TIME:
2872         if (optlen != 4) {
2873             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Failover: malformed option");
2874             break;
2875         }
2876         proto_tree_add_item(subtree, hf_option_failover_state_expiration_time, tvb, off, 4, ENC_BIG_ENDIAN);
2877         break;
2878     case OPTION_RELAY_PORT:
2879         if (optlen != 2) {
2880             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "Relay Port: malformed option");
2881             break;
2882         }
2883         proto_tree_add_item(subtree, hf_option_relay_port, tvb, off, 2, ENC_BIG_ENDIAN);
2884         break;
2885     }
2886 
2887     return 4 + optlen;
2888 }
2889 
2890 
2891 /* May be called recursively */
2892 static void
dissect_dhcpv6(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int off,int eoff,hopcount_info hpi)2893 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2894                int off, int eoff, hopcount_info hpi)
2895 {
2896     proto_tree        *bp_tree = NULL;
2897     proto_item        *ti;
2898     gboolean           at_end;
2899     guint8             msgtype;
2900     msgtype = tvb_get_guint8(tvb, off);
2901 
2902     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_ext(msgtype, &msgtype_vals_ext, "Message Type %u"));
2903 
2904     if (tree) {
2905         ti = proto_tree_add_item(tree, proto_dhcpv6, tvb, off, eoff - off, ENC_NA);
2906         bp_tree = proto_item_add_subtree(ti, ett_dhcpv6);
2907     }
2908 
2909 
2910     if ((msgtype == RELAY_FORW) || (msgtype == RELAY_REPLY)) {
2911         const guint8 previous_hopcount = hpi.hopcount;
2912         proto_item *previous_pi = hpi.pi;
2913         if (tree) {
2914             proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype,  tvb, off,       1, ENC_BIG_ENDIAN);
2915             hpi.pi = proto_tree_add_item(bp_tree, hf_dhcpv6_hopcount, tvb, off + 1,   1, ENC_BIG_ENDIAN);
2916             proto_tree_add_item(bp_tree, hf_dhcpv6_linkaddr, tvb, off + 2,  16, ENC_NA);
2917             proto_tree_add_item(bp_tree, hf_dhcpv6_peeraddr, tvb, off + 18, 16, ENC_NA);
2918 
2919         }
2920         /* Check the hopcount not exceed the HOP_COUNT_LIMIT */
2921         hpi.hopcount = tvb_get_guint8(tvb, off + 1);
2922         if (hpi.hopcount > HOP_COUNT_LIMIT) {
2923           expert_add_info_format(pinfo, hpi.pi, &ei_dhcpv6_error_hopcount, "Hopcount (%d) exceeds the maximum limit HOP_COUNT_LIMIT (%d)", hpi.hopcount, HOP_COUNT_LIMIT);
2924         }
2925         /* Check hopcount is correctly incremented by 1 */
2926         if (hpi.relay_message_previously_detected && hpi.hopcount != previous_hopcount - 1) {
2927           expert_add_info_format(pinfo, previous_pi, &ei_dhcpv6_error_hopcount, "hopcount is not correctly incremented by 1 (expected : %d, actual : %d)", hpi.hopcount + 1, previous_hopcount);
2928         }
2929         hpi.relay_message_previously_detected = TRUE;
2930         col_append_fstr(pinfo->cinfo, COL_INFO, "L: %s ", tvb_ip6_to_str(pinfo->pool, tvb, off + 2));
2931         off += 34;
2932     } else {
2933         /* Check the inner hopcount equals 0 */
2934         if (hpi.hopcount) {
2935             expert_add_info_format(pinfo, hpi.pi, &ei_dhcpv6_error_hopcount, "Hopcount of most inner message has to equal 0 instead of %d", hpi.hopcount);
2936         }
2937         if (tree) {
2938             proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, ENC_BIG_ENDIAN);
2939             proto_tree_add_item(bp_tree, hf_dhcpv6_xid, tvb, off + 1, 3, ENC_BIG_ENDIAN);
2940         }
2941         col_append_fstr(pinfo->cinfo, COL_INFO, "XID: 0x%06x ", tvb_get_ntoh24(tvb, off + 1));
2942         off += 4;
2943     }
2944 
2945     at_end = FALSE;
2946     while ((off < eoff) && !at_end)
2947         off += dhcpv6_option(tvb, pinfo, bp_tree, off, eoff, &at_end, proto_dhcpv6, hpi, msgtype);
2948 }
2949 
2950 static int
dissect_dhcpv6_stream(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2951 dissect_dhcpv6_stream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2952 {
2953     hopcount_info hpi;
2954     initialize_hopount_info(&hpi);
2955     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
2956     col_clear(pinfo->cinfo, COL_INFO);
2957     dissect_dhcpv6(tvb, pinfo, tree, 0, tvb_reported_length(tvb), hpi);
2958     return tvb_captured_length(tvb);
2959 }
2960 
2961 static guint
get_dhcpv6_bulk_leasequery_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)2962 get_dhcpv6_bulk_leasequery_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
2963                                    int offset, void *data _U_)
2964 {
2965     return (tvb_get_ntohs(tvb, offset)+2);
2966 }
2967 
2968 static int
dissect_dhcpv6_bulk_leasequery_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2969 dissect_dhcpv6_bulk_leasequery_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2970 {
2971     proto_item *ti;
2972     proto_tree *bulk_tree, *option_tree;
2973     gint        offset = 0, end;
2974     guint16     size, trans_id;
2975     guint8      msg_type;
2976     gboolean    at_end = FALSE;
2977     hopcount_info hpi;
2978     initialize_hopount_info(&hpi);
2979 
2980     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6 BulkLease");
2981     col_clear(pinfo->cinfo, COL_INFO);
2982 
2983     ti = proto_tree_add_item(tree, proto_dhcpv6_bulk_leasequery, tvb, 0, -1, ENC_NA );
2984     bulk_tree = proto_item_add_subtree(ti, ett_dhcpv6_bulk_leasequery);
2985 
2986     size = tvb_get_ntohs(tvb, offset);
2987     proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_size, tvb, offset, 2, ENC_BIG_ENDIAN);
2988     offset += 2;
2989 
2990     msg_type = tvb_get_guint8( tvb, offset );
2991     ti = proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_msgtype, tvb, offset, 1, ENC_BIG_ENDIAN);
2992     if ((msg_type != LEASEQUERY)       &&
2993         (msg_type != LEASEQUERY_REPLY) &&
2994         (msg_type != LEASEQUERY_DONE)  &&
2995         (msg_type != LEASEQUERY_DATA))
2996         expert_add_info_format(pinfo, ti, &ei_dhcpv6_bulk_leasequery_bad_msg_type,
2997             "Message Type %d not allowed by DHCPv6 Bulk Leasequery", msg_type);
2998 
2999     offset += 1;
3000     proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
3001     offset += 1;
3002 
3003     trans_id = tvb_get_ntohs(tvb, offset);
3004     proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_trans_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3005     offset += 2;
3006 
3007     col_add_fstr(pinfo->cinfo, COL_INFO, "%s, Transaction ID: %5u",
3008                       val_to_str_ext_const(msg_type, &msgtype_vals_ext, "Unknown"), trans_id);
3009 
3010     option_tree = proto_tree_add_subtree(bulk_tree, tvb, offset, -1, ett_dhcpv6_bulk_leasequery_options, NULL, "DHCPv6 Options");
3011     end = size + 2;
3012     while ((offset < end) && !at_end)
3013         offset += dhcpv6_option(tvb, pinfo, option_tree, offset,
3014                                 end, &at_end, proto_dhcpv6_bulk_leasequery, hpi, msg_type);
3015 
3016     return tvb_reported_length(tvb);
3017 }
3018 
3019 static int
dissect_dhcpv6_bulk_leasequery(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3020 dissect_dhcpv6_bulk_leasequery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3021 {
3022     tcp_dissect_pdus(tvb, pinfo, tree, dhcpv6_bulk_leasequery_desegment, 2,
3023                     get_dhcpv6_bulk_leasequery_pdu_len, dissect_dhcpv6_bulk_leasequery_pdu, data);
3024     return tvb_reported_length(tvb);
3025 }
3026 
dissect_dhcpv6_s46_ipv6_prefix(tvbuff_t * tvb,int hf,int offset,int prefix_length,proto_tree * tree)3027 static int dissect_dhcpv6_s46_ipv6_prefix(tvbuff_t *tvb, int hf, int offset, int prefix_length, proto_tree *tree)
3028 {
3029 
3030     int bytes_to_process;
3031     ws_in6_addr prefix;
3032 
3033     bytes_to_process = (((prefix_length + 7) & 0xf8) >> 3);
3034 
3035     memset(prefix.bytes, 0, sizeof prefix.bytes);
3036     if (bytes_to_process != 0) {
3037         tvb_memcpy(tvb, prefix.bytes, offset, bytes_to_process);
3038     }
3039     proto_tree_add_ipv6(tree, hf, tvb, offset, bytes_to_process, &prefix);
3040 
3041     return bytes_to_process;
3042 }
3043 
3044 void
proto_register_dhcpv6(void)3045 proto_register_dhcpv6(void)
3046 {
3047     module_t *bulkquery_module;
3048     module_t *dhcpv6_module;
3049 
3050     static hf_register_info hf[] = {
3051 
3052         /* DHCPv6 header */
3053         { &hf_dhcpv6_msgtype,
3054           { "Message type", "dhcpv6.msgtype", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &msgtype_vals_ext, 0x0, NULL, HFILL }},
3055         { &hf_dhcpv6_hopcount,
3056           { "Hopcount", "dhcpv6.hopcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
3057         { &hf_dhcpv6_xid,
3058           { "Transaction ID", "dhcpv6.xid", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL}},
3059         { &hf_dhcpv6_linkaddr,
3060           { "Link address", "dhcpv6.linkaddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
3061         { &hf_dhcpv6_peeraddr,
3062           { "Peer address", "dhcpv6.peeraddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
3063         /* Generic option stuff */
3064         { &hf_option_type_num,
3065           { "Option", "dhcpv6.option.type", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &opttype_vals_ext, 0x0, NULL, HFILL}},
3066         { &hf_option_length,
3067           { "Length", "dhcpv6.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
3068         { &hf_option_type_str,
3069           { "Option", "dhcpv6.option.type_str", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3070 
3071         /* OPTION_CLIENT_FQDN */
3072         { &hf_clientfqdn_bad_msgtype,
3073           { "Illegal Message Type", "dhcpv6.clientfqdn.bad_msgtype", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &msgtype_vals_ext, 0x0, NULL, HFILL }},
3074         { &hf_clientfqdn_flags,
3075           { "Flags", "dhcpv6.client_fqdn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3076         /* Client's preferences */
3077         { &hf_clientfqdn_client_s,
3078           { "S bit", "dhcpv6.clientfqdn.client.s", FT_BOOLEAN, 8, TFS(&fqdn_s), 0x1,
3079             "Whether or not the client prefers to perform AAAA RR (FQDN-to-address) updates", HFILL}},
3080         { &hf_clientfqdn_client_n,
3081           { "N bit", "dhcpv6.clientfqdn.client.n", FT_BOOLEAN, 8, TFS(&fqdn_n), 0x4,
3082             "Whether or not the client prefers to perform PTR RR (address-to-FQDN) updates", HFILL}},
3083         /* Server's decision to reject or accept the client's preferences */
3084         { &hf_clientfqdn_server_s,
3085           { "S bit", "dhcpv6.clientfqdn.server.s", FT_BOOLEAN, 8, TFS(&fqdn_s), 0x1,
3086             "Whether or not the server SHALL perform AAAA RR (FQDN-to-address) updates", HFILL}},
3087         { &hf_clientfqdn_server_o,
3088           { "O bit", "dhcpv6.clientfqdn.server.o", FT_BOOLEAN, 8, TFS(&fqdn_o), 0x2,
3089               "Whether or not the server has overridden the client's S-bit preference", HFILL}},
3090         { &hf_clientfqdn_server_n,
3091           { "N bit", "dhcpv6.clientfqdn.server.n", FT_BOOLEAN, 8, TFS(&fqdn_n), 0x4,
3092             "Whether or not the server SHALL perform PTR RR (address-to-FQDN) updates", HFILL}},
3093 
3094         /* Headers used in dhcpv6_domain(). */
3095         { &hf_empty_domain_name,
3096           { "Empty domain name - field length", "dhcpv6.domain_field_len", FT_UINT16, BASE_DEC, NULL, 0,
3097             "Indicates that the client requests the server to provide an FQDN name", HFILL}},
3098         { &hf_dhcpv6_non_dns_encoded_name,
3099           { "Non-DNS encoded name. Label length exceeds 63", "dhcpv6.bogus_label_length",
3100             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
3101         { &hf_dhcpv6_domain_field_len_exceeded,
3102           { "Remaining length in the domain name field exceeded", "dhcpv6.domain_field_len_exceeded", FT_UINT8, BASE_DEC,
3103             NULL, 0, NULL, HFILL }},
3104         { &hf_dhcpv6_decoded_portion,
3105           { "Portion successfully decoded", "dhcpv6.decoded_portion", FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL}},
3106         { &hf_dhcpv6_encoded_fqdn_len_gt_255,
3107           { "DNS-encoded labels of FQDN exceed 255 octets", "dhcpv6.encoded_fqdn_gt_255", FT_UINT16, BASE_DEC, NULL, 0,
3108             "Encoded length is greater than 255 [RFC 1035 3.1.]", HFILL}},
3109         { &hf_dhcpv6_root_only_domain_name,
3110           { "Root only domain name", "dhcpv6.root_only_domain_name", FT_STRING, BASE_NONE, NULL, 0,
3111             "The root domain cannot be resolved", HFILL}},
3112         { &hf_dhcpv6_tld,
3113           { "Top Level Domain name", "dhcpv6.tld", FT_STRING, STR_ASCII, NULL, 0,
3114             "Likely to fail because most TLDs do not have an IP address", HFILL}},
3115         { &hf_dhcpv6_partial_name_preceded_by_fqdn,
3116           { "Partial name preceded by FQDN", "dhcpv6.partial_name_preceded_by_fqdn", FT_STRING, STR_ASCII, NULL, 0,
3117             "Partial domain names must be the only name in the domain field", HFILL}},
3118 
3119         { &hf_remoteid_enterprise,
3120           { "Enterprise ID", "dhcpv6.remoteid.enterprise", FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0, "RemoteID Enterprise Number", HFILL }},
3121         { &hf_duid_bytes,
3122           { "DUID", "dhcpv6.duid.bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3123         { &hf_duid_type,
3124           { "DUID Type", "dhcpv6.duid.type", FT_UINT16, BASE_DEC, VALS(duidtype_vals), 0x0, NULL, HFILL}},
3125         { &hf_duidllt_time,
3126           { "DUID Time", "dhcpv6.duidllt.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}},
3127         { &hf_duidllt_link_layer_addr,
3128           { "Link-layer address", "dhcpv6.duidllt.link_layer_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3129         { &hf_duidllt_hwtype,
3130           { "Hardware type", "dhcpv6.duidllt.hwtype", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0, "DUID LLT Hardware Type", HFILL }},
3131         { &hf_duidll_hwtype,
3132           { "Hardware type", "dhcpv6.duidll.hwtype", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0, "DUID LL Hardware Type", HFILL }},
3133         { &hf_duiden_enterprise,
3134           { "Enterprise ID", "dhcpv6.duiden.enterprise", FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0, "DUID EN Enterprise Number", HFILL }},
3135         { &hf_duiden_identifier,
3136           { "Identifier", "dhcpv6.duiden.identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3137         { &hf_duidll_link_layer_addr,
3138           { "Link-layer address", "dhcpv6.duidll.link_layer_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3139         { &hf_duiduuid_bytes,
3140           { "UUID", "dhcpv6.duiduuid.bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3141         { &hf_iaid,
3142           { "IAID", "dhcpv6.iaid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3143         { &hf_iaid_t1,
3144           { "T1", "dhcpv6.iaid.t1", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3145         { &hf_iaid_t2,
3146           { "T2", "dhcpv6.iaid.t2", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3147         { &hf_iata,
3148           { "IATA", "dhcpv6.iata", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3149         { &hf_iaaddr_ip,
3150           { "IPv6 address", "dhcpv6.iaaddr.ip", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3151         { &hf_iaaddr_pref_lifetime,
3152           { "Preferred lifetime", "dhcpv6.iaaddr.pref_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3153         { &hf_iaaddr_valid_lifetime,
3154           { "Valid lifetime", "dhcpv6.iaaddr.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3155         { &hf_requested_option_code,
3156           { "Requested Option code", "dhcpv6.requested_option_code", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &opttype_vals_ext, 0, NULL, HFILL }},
3157         { &hf_option_preference,
3158           { "Pref-value", "dhcpv6.option_preference", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
3159         { &hf_elapsed_time,
3160           { "Elapsed time", "dhcpv6.elapsed_time", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0, NULL, HFILL}},
3161         { &hf_auth_protocol,
3162           { "Protocol", "dhcpv6.auth.protocol", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
3163         { &hf_auth_algorithm,
3164           { "Algorithm", "dhcpv6.auth.algorithm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
3165         { &hf_auth_rdm,
3166           { "RDM", "dhcpv6.auth.rdm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
3167         { &hf_auth_replay_detection,
3168           { "Replay Detection", "dhcpv6.auth.replay_detection", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3169         { &hf_auth_info,
3170           { "Authentication Information", "dhcpv6.auth.info", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3171         { &hf_auth_realm,
3172           { "DHCP realm", "dhcpv6.auth.realm", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3173         { &hf_auth_key_id,
3174           {"Key ID", "dhcpv6.auth.key_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
3175         { &hf_auth_md5_data,
3176           {"HMAC-MD5 data", "dhcpv6.auth.md5_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3177         { &hf_opt_unicast,
3178           { "IPv6 address", "dhcpv6.unicast", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3179         { &hf_opt_status_code,
3180           { "Status Code", "dhcpv6.status_code", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &statuscode_vals_ext, 0, NULL, HFILL }},
3181         { &hf_opt_status_msg,
3182           { "Status Message", "dhcpv6.status_msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3183         { &hf_vendorclass_enterprise,
3184           { "Enterprise ID", "dhcpv6.vendorclass.enterprise", FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0, "Vendor Class Enterprise Number", HFILL }},
3185         { &hf_vendorclass_data,
3186           { "vendor-class-data", "dhcpv6.vendorclass.data", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
3187         { &hf_vendoropts_enterprise,
3188           { "Enterprise ID", "dhcpv6.vendoropts.enterprise", FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0, "Vendor opts Enterprise Number", HFILL }},
3189         { &hf_vendoropts_enterprise_option_code,
3190           { "Option code", "dhcpv6.vendoropts.enterprise.option_code", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3191         { &hf_vendoropts_enterprise_option_length,
3192           { "Option length", "dhcpv6.vendoropts.enterprise.option_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3193         { &hf_vendoropts_enterprise_option_data,
3194           { "Option data", "dhcpv6.vendoropts.enterprise.option_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3195         { &hf_interface_id,
3196           { "Interface-ID", "dhcpv6.interface_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
3197         { &hf_reconf_msg,
3198           { "Reconfigure message type", "dhcpv6.reconf_msg", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &msgtype_vals_ext, 0, NULL, HFILL }},
3199         { &hf_sip_server_domain_search_fqdn,
3200           { "SIP Server Domain Search FQDN", "dhcpv6.sip_server_domain_search_fqdn", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3201         { &hf_sip_server_a,
3202           { "SIP server address", "dhcpv6.sip_server_a", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3203         { &hf_dns_servers,
3204           { "DNS server address", "dhcpv6.dns_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3205         { &hf_domain_search_list_entry,
3206           { "List entry", "dhcpv6.search_list_entry", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3207         { &hf_nis_servers,
3208           { "NIS server address", "dhcpv6.nis_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3209         { &hf_nisp_servers,
3210           { "NISP server address", "dhcpv6.nisp_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3211         { &hf_nis_fqdn,
3212           { "NIS FQDN", "dhcpv6.nis_fqdn", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3213         { &hf_nisp_fqdn,
3214           { "NISP FQDN", "dhcpv6.nisp_fqdn", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3215         { &hf_sntp_servers,
3216           { "SNTP server address", "dhcpv6.sntp_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3217         { &hf_opt_lifetime,
3218           { "Lifetime", "dhcpv6.lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3219         { &hf_bcmcs_servers_fqdn,
3220           { "BCMCS server FQDN", "dhcpv6.bcmcs_server_fqdn", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3221         { &hf_bcmcs_servers_a,
3222           { "BCMCS server address", "dhcpv6.bcmcs_server_a", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3223         { &hf_remoteid_enterprise_id,
3224           { "Remote-ID", "dhcpv6.remoteid_enterprise_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3225         { &hf_subscriber_id,
3226           { "Subscriber-ID", "dhcpv6.subscriber_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3227         { &hf_client_fqdn,
3228           { "Client Domain Name", "dhcpv6.client_domain", FT_STRING, STR_ASCII, NULL, 0x0, NULL, HFILL } },
3229         { &hf_pana_agent,
3230           { "PANA agents address", "dhcpv6.pana_agent", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3231         { &hf_opt_timezone,
3232           { "Time-zone", "dhcpv6.timezone", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3233         { &hf_opt_tzdb,
3234           { "TZ-database", "dhcpv6.tzdb", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3235         { &hf_lq_query,
3236           { "Query-type", "dhcpv6.lq_query", FT_UINT8, BASE_DEC, VALS(lq_query_vals), 0, NULL, HFILL }},
3237         { &hf_lq_query_link_address,
3238           { "Link address", "dhcpv6.lq_query_link_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3239         { &hf_clt_time,
3240           { "Clt_time", "dhcpv6.clt_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3241         { &hf_lq_relay_data_peer_addr,
3242           { "Peer address", "dhcpv6.lq_relay_data_peer_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3243         { &hf_lq_relay_data_msg,
3244           { "DHCPv6 relay message", "dhcpv6.lq_relay_data_msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3245         { &hf_lq_client_link,
3246           { "LQ client links address", "dhcpv6.lq_client_link", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3247         { &hf_capwap_ac_v6,
3248           { "CAPWAP Access Controllers address", "dhcpv6.capwap_ac_v6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3249         { &hf_aftr_name,
3250           { "DS-Lite AFTR Name", "dhcpv6.aftr_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3251         { &hf_iaprefix_pref_lifetime,
3252           { "Preferred lifetime", "dhcpv6.iaprefix.pref_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3253         { &hf_iaprefix_valid_lifetime,
3254           { "Valid lifetime", "dhcpv6.iaprefix.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
3255         { &hf_iaprefix_pref_len,
3256           { "Prefix length", "dhcpv6.iaprefix.pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3257         { &hf_iaprefix_pref_addr,
3258           { "Prefix address", "dhcpv6.iaprefix.pref_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3259         { &hf_mip6_ha,
3260           { "Home Agent", "dhcpv6.mip6_home_agent", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3261         { &hf_mip6_hoa,
3262           { "Home Address", "dhcpv6.mip6_home_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3263         { &hf_nai,
3264           { "NAI", "dhcpv6.nai", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3265         { &hf_pd_exclude_pref_len,
3266           { "Prefix length", "dhcpv6.pd_exclude.pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3267         { &hf_pd_exclude_subnet_id,
3268           { "IPv6 subnet ID", "dhcpv6.pd_exclude.subnet_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
3269         { &hf_option_userclass_length,
3270           { "Length", "dhcpv6.userclass.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
3271         { &hf_option_userclass_opaque_data,
3272           { "Suboption", "dhcpv6.userclass.opaque_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL}},
3273         { &hf_option_ntpserver_type,
3274           { "Suboption", "dhcpv6.ntpserver.option.type", FT_UINT16, BASE_DEC, VALS(ntp_server_opttype_vals), 0x0, NULL, HFILL}},
3275         { &hf_option_ntpserver_length,
3276           { "Length", "dhcpv6.ntpserver.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
3277         { &hf_option_ntpserver_addr,
3278           { "NTP Server Address", "dhcpv6.ntpserver.addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3279         { &hf_option_ntpserver_mc_addr,
3280           { "NTP Multicast Address", "dhcpv6.ntpserver.mc_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3281         { &hf_option_captive_portal,
3282           { "Captive Portal", "dhcpv6.captive_portal", FT_STRING, BASE_NONE, NULL, 0x0, "The contact URI for the captive portal that the user should connect to", HFILL }},
3283         { &hf_option_s46_option_code,
3284           { "S46 Option code", "dhcpv6.option_code", FT_UINT16, BASE_HEX, VALS(s46_opt_code_vals), 0x0, NULL, HFILL }},
3285         { &hf_option_failover_binding_status,
3286           { "Failover Binding Status", "dhcpv6.failover.binding_status", FT_UINT8, BASE_DEC, VALS(failover_binding_status_vals), 0x0, NULL, HFILL }},
3287         { &hf_option_failover_connect_flags,
3288           { "Flags", "dhcpv6.failover.connect.flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
3289         { &hf_option_failover_connect_reserved_flag,
3290           { "Reserved", "dhcpv6.failover.connect.flags.reserved", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0xfffe, NULL, HFILL }},
3291         { &hf_option_failover_connect_f_flag,
3292           { "Fixed PD Length (F)", "dhcpv6.failover.connect.flags.f", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0001, NULL, HFILL }},
3293         { &hf_option_failover_dns_hostname,
3294           { "DNS Hostname", "dhcpv6.failover.dns_hostname", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3295         { &hf_option_failover_dns_zonename,
3296           { "DNS Zone Name", "dhcpv6.failover.dns_zonename", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3297         { &hf_option_failover_dns_flags,
3298           { "Flags", "dhcpv6.failover.dns.flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
3299         { &hf_option_failover_dns_reserved_flag,
3300           { "Reserved", "dhcpv6.failover.dns.flags.reserved", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0xfff0, NULL, HFILL }},
3301         { &hf_option_failover_dns_u_flag,
3302           { "Using Requested FQDN (U)", "dhcpv6.failover.dns.flags.u", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0008, NULL, HFILL }},
3303         { &hf_option_failover_dns_s_flag,
3304           { "Synthesized Name (S)", "dhcpv6.failover.dns.flags.s", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0004, NULL, HFILL }},
3305         { &hf_option_failover_dns_r_flag,
3306           { "Rev Uptodate (R)", "dhcpv6.failover.dns.flags.r", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0002, NULL, HFILL }},
3307         { &hf_option_failover_dns_f_flag,
3308           { "Fwd Uptodate (F)", "dhcpv6.failover.dns.flags.f", FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0001, NULL, HFILL }},
3309         { &hf_option_failover_expiration_time,
3310           { "Expiration Time", "dhcpv6.failover.expiration_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3311         { &hf_option_failover_max_unacked_bndupd,
3312           { "Max number of unacked BNDUPD messages", "dhcpv6.failover.max_unacked_bndupd", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3313         { &hf_option_failover_mclt,
3314           { "Maximum Client Lead Time (MCLT)", "dhcpv6.failover.mclt", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3315         { &hf_option_failover_partner_lifetime,
3316           { "Partner Lifetime", "dhcpv6.failover.partner_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3317         { &hf_option_failover_partner_lifetime_sent,
3318           { "Partner Lifetime Sent", "dhcpv6.failover.partner_lifetime_sent", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3319         { &hf_option_failover_partner_downtime,
3320           { "Partner Down Time", "dhcpv6.failover.partner_down_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3321         { &hf_option_failover_partner_raw_clt_time,
3322           { "Partner Raw Client Time", "dhcpv6.failover.partner_raw_clt_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3323         { &hf_option_failover_major_version,
3324           { "Protocol Major Version", "dhcpv6.failover.protocol.major_version", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3325         { &hf_option_failover_minor_version,
3326           { "Protocol Minor Version", "dhcpv6.failover.protocol.minor_version", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3327         { &hf_option_failover_keepalive_time,
3328           { "Keepalive Time", "dhcpv6.failover.keepalive_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3329         { &hf_option_failover_reconfigure_time,
3330           { "Reconfigure Time", "dhcpv6.failover.reconfigure_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3331         { &hf_option_failover_reconfigure_key,
3332           { "Reconfigure Key", "dhcpv6.failover.reconfigure_key", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
3333         { &hf_option_failover_relationship_name,
3334           { "Relationship Name", "dhcpv6.failover.relationship_name", FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }},
3335         { &hf_option_failover_server_flags,
3336           { "Flags", "dhcpv6.failover.server.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
3337         { &hf_option_failover_server_reserved_flag,
3338           { "Reserved", "dhcpv6.failover.server.flags.reserved", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0xf8, NULL, HFILL }},
3339         { &hf_option_failover_server_a_flag,
3340           { "Ack Startup (A)", "dhcpv6.failover.server.flags.a", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x04, NULL, HFILL }},
3341         { &hf_option_failover_server_s_flag,
3342           { "Startup (S)", "dhcpv6.failover.server.flags.s", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x02, NULL, HFILL }},
3343         { &hf_option_failover_server_c_flag,
3344           { "Communicated (C)", "dhcpv6.failover.server.flags.c", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
3345         { &hf_option_failover_server_state,
3346           { "Server State", "dhcpv6.failover.server_state", FT_UINT8, BASE_DEC, VALS(failover_server_state_vals), 0, NULL, HFILL }},
3347         { &hf_option_failover_start_time_of_state,
3348           { "Start Time of State", "dhcpv6.failover.start_time_of_state", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3349         { &hf_option_failover_state_expiration_time,
3350           { "State Expiration Time", "dhcpv6.failover.state_expiration_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3351         { &hf_option_relay_port,
3352           { "Downstream Source Port", "dhcpv6.relay_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3353         { &hf_option_ntpserver_fqdn,
3354           { "NTP Server FQDN", "dhcpv6.ntpserver.fqdn", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3355         { &hf_packetcable_ccc_suboption,
3356           { "Sub element", "dhcpv6.packetcable.ccc.suboption", FT_UINT16, BASE_DEC, VALS(pkt_ccc_opt_vals), 0, NULL, HFILL }},
3357         { &hf_packetcable_ccc_pri_dhcp,
3358           { "Primary DHCP", "dhcpv6.packetcable.ccc.pri_dhcp", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
3359         { &hf_packetcable_ccc_sec_dhcp,
3360           { "Secondary DHCP", "dhcpv6.packetcable.ccc.sec_dhcp", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
3361         { &hf_packetcable_cccV6_suboption,
3362           { "Sub element", "dhcpv6.packetcable.cccV6.suboption", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &pkt_cccV6_opt_vals_ext, 0, NULL, HFILL }},
3363         { &hf_modem_capabilities_encoding_type,
3364           { "Type", "dhcpv6.docsis.cccV6.tlv5.suboption", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &modem_capabilities_encoding_ext, 0, NULL, HFILL }},
3365         { &hf_eue_capabilities_encoding_type,
3366           { "Type", "dhcpv6.packetcable.cccV6.tlv5.suboption", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &eue_capabilities_encoding_ext, 0, NULL, HFILL }},
3367         { &hf_capabilities_encoding_length,
3368           { "Length", "dhcpv6.cccV6.tlv5.suboption.length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3369         { &hf_capabilities_encoding_bytes,
3370           { "Value", "dhcpv6.cccV6.tlv5.suboption.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3371         { &hf_capabilities_encoding_number,
3372           { "Value", "dhcpv6.cccV6.tlv5.suboption.value_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3373         { &hf_packetcable_cccV6_pri_dss,
3374           { "Primary SSID", "dhcpv6.packetcable.cccV6.pri_dss", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
3375         { &hf_packetcable_cccV6_sec_dss,
3376           { "Secondary SSID", "dhcpv6.packetcable.cccV6.sec_dss", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
3377         { &hf_packetcable_cccV6_prov_srv_type,
3378           { "Type", "dhcpv6.packetcable.cccV6.prov_srv.type", FT_UINT8, BASE_DEC, VALS(pkt_cccV6_prov_srv_type_vals), 0, NULL, HFILL }},
3379         { &hf_packetcable_cccV6_prov_srv_fqdn,
3380           { "FQDN", "dhcpv6.packetcable.cccV6.prov_srv.fqdn", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3381         { &hf_packetcable_cccV6_prov_srv_ipv6,
3382           { "IPv6 address", "dhcpv6.packetcable.cccV6.prov_srv.ipv6", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
3383         { &hf_packetcable_cccV6_as_krb_nominal_timeout,
3384           { "Nominal Timeout", "dhcpv6.packetcable.cccV6.as_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3385         { &hf_packetcable_cccV6_as_krb_max_timeout,
3386           { "Maximum Timeout", "dhcpv6.packetcable.cccV6.as_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3387         { &hf_packetcable_cccV6_as_krb_max_retry_count,
3388           { "Maximum Retry Count", "dhcpv6.packetcable.cccV6.as_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3389         { &hf_packetcable_cccV6_ap_krb_nominal_timeout,
3390           { "Nominal Timeout", "dhcpv6.packetcable.cccV6.ap_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3391         { &hf_packetcable_cccV6_ap_krb_max_timeout,
3392           { "Maximum Timeout", "dhcpv6.packetcable.cccV6.ap_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3393         { &hf_packetcable_cccV6_ap_krb_max_retry_count,
3394           { "Maximum Retry Count", "dhcpv6.packetcable.cccV6.ap_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
3395         { &hf_packetcable_cccV6_krb_realm,
3396           { "KRB Realm", "dhcpv6.packetcable.cccV6.krb_realm", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3397         { &hf_packetcable_cccV6_tgt_flag,
3398           { "TGT Flags", "dhcpv6.packetcable.cccV6.tgt_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
3399         { &hf_packetcable_cccV6_tgt_flag_fetch,
3400           { "Fetch TGT", "dhcpv6.packetcable.cccV6.tgt_flag.fetch", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
3401         { &hf_packetcable_cccV6_prov_timer,
3402           { "Provisioning timer", "dhcpv6.packetcable.cccV6.prov_timer", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3403         { &hf_packetcable_cccV6_sec_tcm,
3404           { "SEC TCM Flags", "dhcpv6.packetcable.cccV6.sec_tcm", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
3405         { &hf_packetcable_cccV6_sec_tcm_provisioning_server,
3406           { "Provisioning Server", "dhcpv6.packetcable.cccV6.sec_tcm.provisioning_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x01, NULL, HFILL }},
3407         { &hf_packetcable_cccV6_sec_tcm_call_manager_server,
3408           { "Call Manager Servers", "dhcpv6.packetcable.cccV6.tgt_flag.call_manager_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x02, NULL, HFILL }},
3409         { &hf_cablelabs_opts,
3410           { "Suboption", "dhcpv6.cablelabs.opt", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &cl_vendor_subopt_values_ext, 0, NULL, HFILL }},
3411         { &hf_cablelabs_ipv6_server,
3412           { "IPv6 address", "dhcpv6.cablelabs.ipv6_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
3413         { &hf_cablelabs_docsis_version_number,
3414           { "DOCSIS Version Number", "dhcpv6.cablelabs.docsis_version_number", FT_UINT16, BASE_CUSTOM, CF_FUNC(cablelabs_fmt_docsis_version), 0x0, NULL, HFILL}},
3415         { &hf_cablelabs_interface_id,
3416           { "Interface-ID", "dhcpv6.cablelabs.interface_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3417         { &hf_cablelabs_interface_id_link_address,
3418           { "Link Address", "dhcpv6.cablelabs.interface_id_link_address", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
3419         { &hf_option_s46_rule_flags,
3420           { "Flags", "dhcpv6.s46_rule.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
3421         { &hf_option_s46_rule_reserved_flag,
3422           { "Reserved", "dhcpv6.s46_rule.flags.reserved", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0xfe, NULL, HFILL }},
3423         { &hf_option_s46_rule_fmr_flag,
3424           { "Forwarding Mapping Rule", "dhcpv6.s46_rule.flags.fmr", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
3425         { &hf_option_s46_rule_ea_len,
3426           { "EA-bit length", "dhcpv6.s46_rule.ea_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3427         { &hf_option_s46_rule_ipv4_pref_len,
3428           { "IPv4 prefix length", "dhcpv6.s46_rule.ipv4_pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3429         { &hf_option_s46_rule_ipv4_prefix,
3430           { "IPv4 prefix", "dhcpv6.s46_rule.ipv4_prefix", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
3431         { &hf_option_s46_rule_ipv6_pref_len,
3432           { "IPv6 prefix length", "dhcpv6.s46_rule.ipv6_prefix_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3433         { &hf_option_s46_rule_ipv6_prefix,
3434           { "IPv6 prefix", "dhcpv6.s46_rule.ipv6_prefix", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
3435         { &hf_option_s46_br_address,
3436           { "BR address", "dhcpv6.s46_br.address", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
3437         { &hf_option_s46_dmr_pref_len,
3438           { "IPv6 prefix length", "dhcpv6.s46_dmr.dmr_pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3439         { &hf_option_s46_dmr_prefix,
3440           { "IPv6 prefix", "dhcpv6.s46_dmr.dmr_prefix", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
3441         { &hf_option_s46_v4v6bind_ipv4_address,
3442           { "IPv4 Address", "dhcpv6.s46_v4v6bind.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
3443         { &hf_option_s46_v4v6bind_ipv6_pref_len,
3444           { "IPv6 prefix length", "dhcpv6.s46_v4v6bind.ipv6_pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3445         { &hf_option_s46_v4v6bind_ipv6_prefix,
3446           { "IPv6 prefix", "dhcpv6.s46_v4v6bind.ipv6_prefix", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
3447         { &hf_option_s46_portparam_offset,
3448           { "Offset", "dhcpv6.s46_portparam.offset", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3449         { &hf_option_s46_portparam_psid_len,
3450           { "PSID length", "dhcpv6.s46_portparam.psid_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
3451         { &hf_option_s46_portparam_psid,
3452           { "PSID", "dhcpv6.s46_portparam.psid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
3453         { &hf_opt_mudurl,
3454           { "MUDURL", "dhcpv6.mudurl", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}
3455     };
3456 
3457     static gint *ett[] = {
3458         &ett_dhcpv6,
3459         &ett_dhcpv6_option,
3460         &ett_dhcpv6_option_vsoption,
3461         &ett_dhcpv6_vendor_option,
3462         &ett_dhcpv6_pkt_option,
3463         &ett_dhcpv6_userclass_option,
3464         &ett_dhcpv6_netserver_option,
3465         &ett_dhcpv6_tlv5_type,
3466         &ett_dhcpv6_sip_server_domain_search_list_option,
3467         &ett_dhcpv6_dns_domain_search_list_option,
3468         &ett_dhcpv6_nis_domain_name_option,
3469         &ett_dhcpv6_nisp_domain_name_option,
3470         &ett_dhcpv6_bcmcs_servers_domain_search_list_option,
3471         &ett_dhcpv6_s46_rule_flags,
3472         &ett_dhcpv6_failover_connect_flags,
3473         &ett_dhcpv6_failover_dns_flags,
3474         &ett_dhcpv6_failover_server_flags,
3475         &ett_clientfqdn_flags,
3476         &ett_clientfqdn_expert
3477     };
3478 
3479     static ei_register_info ei[] = {
3480         { &ei_dhcpv6_bogus_length, { "dhcpv6.bogus_length", PI_MALFORMED, PI_ERROR, "Bogus length", EXPFILL }},
3481         { &ei_dhcpv6_malformed_option, { "dhcpv6.malformed_option", PI_MALFORMED, PI_ERROR, "Malformed option", EXPFILL }},
3482         { &ei_dhcpv6_no_suboption_len, { "dhcpv6.no_suboption_len", PI_PROTOCOL, PI_WARN,
3483                                          "no room left in option for suboption length", EXPFILL }},
3484         { &ei_dhcpv6_invalid_time_value, { "dhcpv6.invalid_time_value", PI_PROTOCOL, PI_WARN, "Invalid time value", EXPFILL }},
3485         { &ei_dhcpv6_invalid_type, { "dhcpv6.invalid_type", PI_PROTOCOL, PI_WARN, "Invalid type", EXPFILL }},
3486         { &ei_dhcpv6_error_hopcount, { "dhcpv6.error_hopcount", PI_PROTOCOL, PI_WARN, "Detected error on hop-count", EXPFILL }},
3487         { &ei_dhcpv6_clientfqdn_bad_msgtype, { "dhcpv6.bad_msgtype", PI_PROTOCOL, PI_ERROR,
3488                                     "This message type is not permitted to use OPTION_CLIENT_FQDN", EXPFILL }},
3489         { &ei_dhcpv6_s_bit_should_be_zero, { "dhcpv6.s_bit_should_be_zero", PI_PROTOCOL, PI_ERROR,
3490                                     "ERROR: When the N-bit is set, the S-bit must be reset", EXPFILL }},
3491         /*
3492          * FQDN-related errors in dhcpv6_domain() */
3493         { &ei_dhcpv6_non_dns_encoded_name, { "dhcpv6.expert.name_not_dns_encoded", PI_PROTOCOL, PI_ERROR,
3494                                     "ERROR: This name is not a DNS record encoded", EXPFILL }},
3495         { &ei_dhcpv6_domain_field_len_exceeded, { "dhcpv6.expert.domain_field_length_exceeded", PI_MALFORMED, PI_ERROR,
3496                                     "ERROR: FQDN exceeds length of the domain name field", EXPFILL }},
3497         { &ei_dhcpv6_encoded_fqdn_len_gt_255, { "dhcpv6.expert.encoded_fqdn_gt_255", PI_MALFORMED, PI_ERROR,
3498                                     "ERROR: FQDN's *encoded* length exceeds 255 octets [RFC 1035 3.1.]", EXPFILL }},
3499         { &ei_dhcpv6_root_only_domain_name, { "dhcpv6.expert.root_only_domain_name", PI_PROTOCOL, PI_ERROR,
3500                                     "ERROR: A root-only domain name cannot be resolved.", EXPFILL }},
3501         { &ei_dhcpv6_tld_lookup, { "dhcpv6.expert.tld_lookup", PI_COMMENTS_GROUP, PI_WARN,
3502                                     "WARNING: TLDs are rarely resolvable ", EXPFILL }},
3503         { &ei_dhcpv6_partial_name_preceded_by_fqdn, { "dhcpv6.expert.partial_name_preceded_by_fqdn", PI_PROTOCOL, PI_ERROR,
3504                                     "ERROR: Partial name is preceded by an FQDN", EXPFILL }},
3505     };
3506 
3507     static hf_register_info bulk_leasequery_hf[] = {
3508         { &hf_dhcpv6_bulk_leasequery_size,
3509           { "Message size", "dhcpv6.bulk_leasequery.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3510         { &hf_dhcpv6_bulk_leasequery_msgtype,
3511           { "Message type", "dhcpv6.bulk_leasequery.msgtype", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &msgtype_vals_ext, 0x0, NULL, HFILL }},
3512         { &hf_dhcpv6_bulk_leasequery_reserved,
3513           { "Reserved", "dhcpv6.bulk_leasequery.reserved", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3514         { &hf_dhcpv6_bulk_leasequery_trans_id,
3515           { "Transaction ID", "dhcpv6.bulk_leasequery.trans_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3516     };
3517 
3518     static gint *ett_bulk_leasequery[] = {
3519         &ett_dhcpv6_bulk_leasequery,
3520         &ett_dhcpv6_bulk_leasequery_options
3521     };
3522 
3523     static ei_register_info ei_bulk_leasequery[] = {
3524         { &ei_dhcpv6_bulk_leasequery_bad_query_type, { "dhcpv6.bulk_leasequery.bad_query_type", PI_MALFORMED, PI_WARN, "LQ-QUERY: Query types only supported by Bulk Leasequery", EXPFILL }},
3525         { &ei_dhcpv6_bulk_leasequery_bad_msg_type, { "dhcpv6.bulk_leasequery.bad_msg_type", PI_MALFORMED, PI_WARN, "Message Type %d not allowed by DHCPv6 Bulk Leasequery", EXPFILL }},
3526     };
3527 
3528     expert_module_t *expert_dhcpv6;
3529     expert_module_t *expert_dhcpv6_bulk_leasequery;
3530 
3531     proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
3532     proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
3533     proto_register_subtree_array(ett, array_length(ett));
3534 
3535     expert_dhcpv6 = expert_register_protocol(proto_dhcpv6);
3536     expert_register_field_array(expert_dhcpv6, ei, array_length(ei));
3537 
3538     proto_dhcpv6_bulk_leasequery = proto_register_protocol("DHCPv6 Bulk Leasequery", "DHCPv6 Bulk Leasequery", "dhcpv6.bulk_leasequery");
3539     proto_register_field_array(proto_dhcpv6_bulk_leasequery, bulk_leasequery_hf, array_length(bulk_leasequery_hf));
3540     proto_register_subtree_array(ett_bulk_leasequery, array_length(ett_bulk_leasequery));
3541 
3542     expert_dhcpv6_bulk_leasequery = expert_register_protocol(proto_dhcpv6_bulk_leasequery);
3543     expert_register_field_array(expert_dhcpv6_bulk_leasequery, ei_bulk_leasequery, array_length(ei_bulk_leasequery));
3544 
3545     /* Allow other dissectors to find this one by name. */
3546     dhcpv6_handle = register_dissector("dhcpv6", dissect_dhcpv6_stream, proto_dhcpv6);
3547 
3548     dhcpv6_module = prefs_register_protocol(proto_dhcpv6, NULL);
3549     prefs_register_bool_preference(dhcpv6_module, "cablelabs_interface_id",
3550                                     "Dissect Option 18 (Interface-Id) as CableLab option",
3551                                     "Whether Option 18 is dissected as CableLab or RFC 3315",
3552                                     &cablelabs_interface_id);
3553 
3554     bulkquery_module = prefs_register_protocol(proto_dhcpv6_bulk_leasequery, NULL);
3555     prefs_register_bool_preference(bulkquery_module, "desegment",
3556                                     "Desegment all Bulk Leasequery messages spanning multiple TCP segments",
3557                                     "Whether the Bulk Leasequery dissector should desegment all messages spanning multiple TCP segments",
3558                                     &dhcpv6_bulk_leasequery_desegment);
3559 }
3560 
3561 void
proto_reg_handoff_dhcpv6(void)3562 proto_reg_handoff_dhcpv6(void)
3563 {
3564     dissector_handle_t dhcpv6_bulkquery_handle;
3565 
3566     dissector_add_uint_range_with_preference("udp.port", UDP_PORT_DHCPV6_RANGE, dhcpv6_handle);
3567 
3568     dhcpv6_bulkquery_handle = create_dissector_handle(dissect_dhcpv6_bulk_leasequery,
3569                                             proto_dhcpv6_bulk_leasequery);
3570     dissector_add_uint_with_preference("tcp.port", TCP_PORT_DHCPV6_UPSTREAM, dhcpv6_bulkquery_handle);
3571 }
3572 
3573 /*
3574  * Editor modelines
3575  *
3576  * Local Variables:
3577  * c-basic-offset: 4
3578  * tab-width: 8
3579  * indent-tabs-mode: nil
3580  * End:
3581  *
3582  * ex: set shiftwidth=4 tabstop=8 expandtab:
3583  * :indentSize=4:tabSize=8:noTabs=true:
3584  */
3585