From Michal Labedzki via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9333 :
[metze/wireshark/wip.git] / epan / dissectors / packet-dhcpv6.c
1 /* packet-dhpcv6.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  * $Id$
11  *
12  * The information used comes from:
13  * RFC3315.txt (DHCPv6)
14  * RFC3319.txt (SIP options)
15  * RFC3633.txt (Prefix options)
16  * RFC3646.txt (DNS servers/domains)
17  * RFC3898.txt (NIS options)
18  * RFC4075.txt (Simple Network Time Protocol Option)
19  * RFC4242.txt (Information Refresh Time Option)
20  * RFC4280.txt (Broadcast and Multicast Control Servers Options)
21  * RFC4649.txt (Remote ID option)
22  * RFC4704.txt (Client FQDN)
23  * RFC5007.txt (DHCPv6 Leasequery)
24  * RFC5417.txt (CAPWAP Access Controller DHCP Option)
25  * RFC5460.txt (DHCPv6 Bulk Leasequery)
26  * RFC5908.txt (Network Time Protocol (NTP) Server Option)
27  * RFC6334.txt (Dual-Stack Lite Option)
28  * RFC6603.txt (Prefix Exclude Option)
29  * draft-ietf-dhc-dhcpv6-opt-timeconfig-03.txt
30  * draft-ietf-dhc-dhcpv6-opt-lifetime-00.txt
31  * CL-SP-CANN-DHCP-Reg-I06-110210.doc
32  *
33  * Note that protocol constants are still subject to change, based on IANA
34  * assignment decisions.
35  *
36  * Wireshark - Network traffic analyzer
37  * By Gerald Combs <gerald@wireshark.org>
38  * Copyright 1998 Gerald Combs
39  *
40  * This program is free software; you can redistribute it and/or
41  * modify it under the terms of the GNU General Public License
42  * as published by the Free Software Foundation; either version 2
43  * of the License, or (at your option) any later version.
44  *
45  * This program is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48  * GNU General Public License for more details.
49  *
50  * You should have received a copy of the GNU General Public License
51  * along with this program; if not, write to the Free Software
52  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
53  */
54
55 #include "config.h"
56
57 #include <glib.h>
58 #include <epan/packet.h>
59 #include <epan/sminmpec.h>
60 #include <epan/strutil.h>
61 #include <epan/arptypes.h>
62 #include <epan/expert.h>
63 #include <epan/prefs.h>
64 #include <epan/wmem/wmem.h>
65 #include "packet-tcp.h"
66 #include "packet-arp.h"
67 #include "packet-dns.h"                         /* for get_dns_name() */
68
69 void proto_register_dhcpv6(void);
70 void proto_reg_handoff_dhcpv6(void);
71
72 static gboolean dhcpv6_bulk_leasequery_desegment  = TRUE;
73
74 static int proto_dhcpv6 = -1;
75 static int proto_dhcpv6_bulk_leasequery = -1;
76 static int hf_dhcpv6_msgtype = -1;
77 static int hf_dhcpv6_domain = -1;
78 static int hf_clientfqdn_reserved = -1;
79 static int hf_clientfqdn_n = -1;
80 static int hf_clientfqdn_o = -1;
81 static int hf_clientfqdn_s = -1;
82 static int hf_option_type = -1;
83 static int hf_option_length = -1;
84 static int hf_option_value = -1;
85 static int hf_remoteid_enterprise = -1;
86 static int hf_vendoropts_enterprise = -1;
87 static int hf_duid_bytes = -1;
88 static int hf_duid_type = -1;
89 static int hf_duidllt_time = -1;
90 static int hf_duidllt_link_layer_addr = -1;
91 static int hf_duidllt_hwtype = -1;
92 static int hf_duidll_hwtype = -1;
93 static int hf_duiden_enterprise = -1;
94 static int hf_duiden_identifier = -1;
95 static int hf_duidll_link_layer_addr = -1;
96 static int hf_iaid = -1;
97 static int hf_iaid_t1 = -1;
98 static int hf_iaid_t2 = -1;
99 static int hf_iata = -1;
100 static int hf_iaaddr_ip = -1;
101 static int hf_iaaddr_pref_lifetime = -1;
102 static int hf_iaaddr_valid_lifetime = -1;
103 static int hf_requested_option_code = -1;
104 static int hf_option_preference = -1;
105 static int hf_elapsed_time = -1;
106 static int hf_auth_protocol = -1;
107 static int hf_auth_algorithm = -1;
108 static int hf_auth_rdm = -1;
109 static int hf_auth_replay_detection = -1;
110 static int hf_auth_info = -1;
111 static int hf_opt_unicast = -1;
112 static int hf_opt_status_code = -1;
113 static int hf_opt_status_msg = -1;
114 static int hf_vendorclass_enterprise = -1;
115 static int hf_vendorclass_data = -1;
116 static int hf_vendoropts_enterprise_option_code = -1;
117 static int hf_vendoropts_enterprise_option_length = -1;
118 static int hf_vendoropts_enterprise_option_data = -1;
119 static int hf_interface_id = -1;
120 static int hf_interface_id_link_address = -1;
121 static int hf_reconf_msg = -1;
122 static int hf_sip_server_a = -1;
123 static int hf_dns_servers = -1;
124 static int hf_nis_servers = -1;
125 static int hf_nisp_servers = -1;
126 static int hf_sntp_servers = -1;
127 static int hf_opt_lifetime = -1;
128 static int hf_bcmcs_servers_a = -1;
129 static int hf_remoteid_enterprise_id = -1;
130 static int hf_subscriber_id = -1;
131 static int hf_pana_agent = -1;
132 static int hf_opt_timezone = -1;
133 static int hf_opt_tzdb = -1;
134 static int hf_lq_query = -1;
135 static int hf_lq_query_link_address = -1;
136 static int hf_clt_time = -1;
137 static int hf_lq_relay_data_peer_addr = -1;
138 static int hf_lq_relay_data_msg = -1;
139 static int hf_lq_client_link = -1;
140 static int hf_capwap_ac_v6 = -1;
141 static int hf_aftr_name = -1;
142 static int hf_iaprefix_pref_lifetime = -1;
143 static int hf_iaprefix_valid_lifetime = -1;
144 static int hf_iaprefix_pref_len = -1;
145 static int hf_iaprefix_pref_addr = -1;
146 static int hf_mip6_ha = -1;
147 static int hf_mip6_hoa = -1;
148 static int hf_nai = -1;
149 static int hf_pd_exclude_pref_len = -1;
150 static int hf_pd_exclude_subnet_id = -1;
151 static int hf_dhcpv6_hopcount = -1;
152 static int hf_dhcpv6_xid = -1;
153 static int hf_dhcpv6_peeraddr = -1;
154 static int hf_dhcpv6_linkaddr = -1;
155 static int hf_option_ntpserver_type = -1;
156 static int hf_option_ntpserver_length = -1;
157 static int hf_option_ntpserver_addr = -1;
158 static int hf_option_ntpserver_mc_addr = -1;
159 static int hf_packetcable_ccc_suboption = -1;
160 static int hf_packetcable_ccc_pri_dhcp = -1;
161 static int hf_packetcable_ccc_sec_dhcp = -1;
162 static int hf_packetcable_ccc_prov_srv_type = -1;
163 static int hf_packetcable_ccc_prov_srv_fqdn = -1;
164 static int hf_packetcable_ccc_prov_srv_ipv4 = -1;
165 static int hf_packetcable_ccc_as_krb_nominal_timeout = -1;
166 static int hf_packetcable_ccc_as_krb_max_timeout = -1;
167 static int hf_packetcable_ccc_as_krb_max_retry_count = -1;
168 static int hf_packetcable_ccc_ap_krb_nominal_timeout = -1;
169 static int hf_packetcable_ccc_ap_krb_max_timeout = -1;
170 static int hf_packetcable_ccc_ap_krb_max_retry_count = -1;
171 static int hf_packetcable_ccc_krb_realm = -1;
172 static int hf_packetcable_ccc_tgt_flag = -1;
173 static int hf_packetcable_ccc_tgt_flag_fetch = -1;
174 static int hf_packetcable_ccc_prov_timer = -1;
175 static int hf_packetcable_ccc_sec_tcm = -1;
176 static int hf_packetcable_ccc_sec_tcm_provisioning_server = -1;
177 static int hf_packetcable_ccc_sec_tcm_call_manager_server = -1;
178 static int hf_packetcable_cccV6_suboption = -1;
179 static int hf_packetcable_cccV6_pri_dss = -1;
180 static int hf_packetcable_cccV6_sec_dss = -1;
181 static int hf_packetcable_cccV6_prov_srv_type = -1;
182 static int hf_packetcable_cccV6_prov_srv_fqdn = -1;
183 static int hf_packetcable_cccV6_prov_srv_ipv6 = -1;
184 static int hf_packetcable_cccV6_as_krb_nominal_timeout = -1;
185 static int hf_packetcable_cccV6_as_krb_max_timeout = -1;
186 static int hf_packetcable_cccV6_as_krb_max_retry_count = -1;
187 static int hf_packetcable_cccV6_ap_krb_nominal_timeout = -1;
188 static int hf_packetcable_cccV6_ap_krb_max_timeout = -1;
189 static int hf_packetcable_cccV6_ap_krb_max_retry_count = -1;
190 static int hf_packetcable_cccV6_krb_realm = -1;
191 static int hf_packetcable_cccV6_tgt_flag = -1;
192 static int hf_packetcable_cccV6_tgt_flag_fetch = -1;
193 static int hf_packetcable_cccV6_prov_timer = -1;
194 static int hf_packetcable_cccV6_sec_tcm = -1;
195 static int hf_packetcable_cccV6_sec_tcm_provisioning_server = -1;
196 static int hf_packetcable_cccV6_sec_tcm_call_manager_server = -1;
197 static int hf_cablelabs_opts = -1;
198 static int hf_modem_capabilities_encoding_type = -1;
199 static int hf_eue_capabilities_encoding_type = -1;
200 static int hf_capabilities_encoding_length = -1;
201 static int hf_capabilities_encoding_bytes = -1;
202 static int hf_capabilities_encoding_number = -1;
203 static int hf_cablelabs_ipv6_server = -1;
204
205 static gint ett_dhcpv6 = -1;
206 static gint ett_dhcpv6_option = -1;
207 static gint ett_dhcpv6_option_vsoption = -1;
208 static gint ett_dhcpv6_vendor_option = -1;
209 static gint ett_dhcpv6_pkt_option = -1;
210 static gint ett_dhcpv6_netserver_option = -1;
211 static gint ett_dhcpv6_tlv5_type = -1;
212
213 static expert_field ei_dhcpv6_bogus_length = EI_INIT;
214 static expert_field ei_dhcpv6_malformed_option = EI_INIT;
215 static expert_field ei_dhcpv6_no_suboption_len = EI_INIT;
216 static expert_field ei_dhcpv6_invalid_byte = EI_INIT;
217 static expert_field ei_dhcpv6_invalid_time_value = EI_INIT;
218 static expert_field ei_dhcpv6_invalid_type = EI_INIT;
219 static expert_field ei_dhcpv6_malformed_dns = EI_INIT;
220
221
222 static int hf_dhcpv6_bulk_leasequery_size = -1;
223 static int hf_dhcpv6_bulk_leasequery_msgtype = -1;
224 static int hf_dhcpv6_bulk_leasequery_reserved = -1;
225 static int hf_dhcpv6_bulk_leasequery_trans_id = -1;
226
227 static gint ett_dhcpv6_bulk_leasequery = -1;
228 static gint ett_dhcpv6_bulk_leasequery_options = -1;
229
230 static expert_field ei_dhcpv6_bulk_leasequery_bad_query_type = EI_INIT;
231 static expert_field ei_dhcpv6_bulk_leasequery_no_lq_relay_data = EI_INIT;
232 static expert_field ei_dhcpv6_bulk_leasequery_bad_msg_type = EI_INIT;
233
234 #define UDP_PORT_DHCPV6_DOWNSTREAM      546
235 #define UDP_PORT_DHCPV6_UPSTREAM        547
236
237 #define DHCPV6_LEASEDURATION_INFINITY   0xffffffff
238
239 #define SOLICIT                  1
240 #define ADVERTISE                2
241 #define REQUEST                  3
242 #define CONFIRM                  4
243 #define RENEW                    5
244 #define REBIND                   6
245 #define REPLY                    7
246 #define RELEASE                  8
247 #define DECLINE                  9
248 #define RECONFIGURE             10
249 #define INFORMATION_REQUEST     11
250 #define RELAY_FORW              12
251 #define RELAY_REPLY             13
252 #define LEASEQUERY              14
253 #define LEASEQUERY_REPLY        15
254 #define LEASEQUERY_DONE         16
255 #define LEASEQUERY_DATA         17
256
257 #define OPTION_CLIENTID          1
258 #define OPTION_SERVERID          2
259 #define OPTION_IA_NA             3
260 #define OPTION_IA_TA             4
261 #define OPTION_IAADDR            5
262 #define OPTION_ORO               6
263 #define OPTION_PREFERENCE        7
264 #define OPTION_ELAPSED_TIME      8
265 #define OPTION_RELAY_MSG         9
266 /* #define      OPTION_SERVER_MSG       10 */
267 #define OPTION_AUTH             11
268 #define OPTION_UNICAST          12
269 #define OPTION_STATUS_CODE      13
270 #define OPTION_RAPID_COMMIT     14
271 #define OPTION_USER_CLASS       15
272 #define OPTION_VENDOR_CLASS     16
273 #define OPTION_VENDOR_OPTS      17
274 #define OPTION_INTERFACE_ID     18
275 #define OPTION_RECONF_MSG       19
276 #define OPTION_RECONF_ACCEPT    20
277 #define OPTION_SIP_SERVER_D     21
278 #define OPTION_SIP_SERVER_A     22
279 #define OPTION_DNS_SERVERS      23
280 #define OPTION_DOMAIN_LIST      24
281 #define OPTION_IA_PD            25
282 #define OPTION_IAPREFIX         26
283 #define OPTION_NIS_SERVERS      27
284 #define OPTION_NISP_SERVERS     28
285 #define OPTION_NIS_DOMAIN_NAME  29
286 #define OPTION_NISP_DOMAIN_NAME 30
287 #define OPTION_SNTP_SERVERS     31
288 #define OPTION_LIFETIME         32
289 #define OPTION_BCMCS_SERVER_D   33
290 #define OPTION_BCMCS_SERVER_A   34
291 #define OPTION_GEOCONF_CIVIC    36
292 #define OPTION_REMOTE_ID        37
293 #define OPTION_SUBSCRIBER_ID    38
294 #define OPTION_CLIENT_FQDN      39
295 #define OPTION_PANA_AGENT       40
296 #define OPTION_TIME_ZONE        41
297 #define OPTION_TZDB             42
298 #define OPTION_ERO              43
299 #define OPTION_LQ_QUERY         44
300 #define OPTION_CLIENT_DATA      45
301 #define OPTION_CLT_TIME         46
302 #define OPTION_LQ_RELAY_DATA    47
303 #define OPTION_LQ_CLIENT_LINK   48
304 #define OPTION_CAPWAP_AC_V6     52
305 #define OPTION_RELAYID          53
306 #define OPTION_NTP_SERVER       56
307 #define OPTION_AFTR_NAME        64
308 #define OPTION_PD_EXCLUDE       67
309
310 /* temporary value until defined by IETF */
311 #define OPTION_MIP6_HA          165
312 #define OPTION_MIP6_HOA         166
313 #define OPTION_NAI              167
314
315 #define DUID_LLT                1
316 #define DUID_EN                 2
317 #define DUID_LL                 3
318 #define DUID_LL_OLD             4
319
320 static const value_string msgtype_vals[] = {
321     { SOLICIT,                 "Solicit" },
322     { ADVERTISE,               "Advertise" },
323     { REQUEST,                 "Request" },
324     { CONFIRM,                 "Confirm" },
325     { RENEW,                   "Renew" },
326     { REBIND,                  "Rebind" },
327     { REPLY,                   "Reply" },
328     { RELEASE,                 "Release" },
329     { DECLINE,                 "Decline" },
330     { RECONFIGURE,             "Reconfigure" },
331     { INFORMATION_REQUEST,     "Information-request" },
332     { RELAY_FORW,              "Relay-forw" },
333     { RELAY_REPLY,             "Relay-reply" },
334     { LEASEQUERY,              "Leasequery" },
335     { LEASEQUERY_REPLY,        "Leasequery-reply" },
336     { LEASEQUERY_DONE,         "Leasequery-done" },
337     { LEASEQUERY_DATA,         "Leasequery-data" },
338     { 0, NULL }
339 };
340
341 static const value_string opttype_vals[] = {
342     { OPTION_CLIENTID,         "Client Identifier" },
343     { OPTION_SERVERID,         "Server Identifier" },
344     { OPTION_IA_NA,            "Identity Association for Non-temporary Address" },
345     { OPTION_IA_TA,            "Identity Association for Temporary Address" },
346     { OPTION_IAADDR,           "IA Address" },
347     { OPTION_ORO,              "Option Request" },
348     { OPTION_PREFERENCE,       "Preference" },
349     { OPTION_ELAPSED_TIME,     "Elapsed time" },
350     { OPTION_RELAY_MSG,        "Relay Message" },
351 /*  { OPTION_SERVER_MSG,       "Server message" }, */
352     { OPTION_AUTH,             "Authentication" },
353     { OPTION_UNICAST,          "Server unicast" },
354     { OPTION_STATUS_CODE,      "Status code" },
355     { OPTION_RAPID_COMMIT,     "Rapid Commit" },
356     { OPTION_USER_CLASS,       "User Class" },
357     { OPTION_VENDOR_CLASS,     "Vendor Class" },
358     { OPTION_VENDOR_OPTS,      "Vendor-specific Information" },
359     { OPTION_INTERFACE_ID,     "Interface-Id" },
360     { OPTION_RECONF_MSG,       "Reconfigure Message" },
361     { OPTION_RECONF_ACCEPT,    "Reconfigure Accept" },
362     { OPTION_SIP_SERVER_D,     "SIP Server Domain Name List" },
363     { OPTION_SIP_SERVER_A,     "SIP Servers IPv6 Address List" },
364     { OPTION_DNS_SERVERS,      "DNS recursive name server" },
365     { OPTION_DOMAIN_LIST,      "Domain Search List" },
366     { OPTION_IA_PD,            "Identity Association for Prefix Delegation" },
367     { OPTION_IAPREFIX,         "IA Prefix" },
368     { OPTION_NIS_SERVERS,      "Network Information Server" },
369     { OPTION_NISP_SERVERS,     "Network Information Server V2" },
370     { OPTION_NIS_DOMAIN_NAME,  "Network Information Server Domain Name" },
371     { OPTION_NISP_DOMAIN_NAME, "Network Information Server V2 Domain Name" },
372     { OPTION_SNTP_SERVERS,     "Simple Network Time Protocol Server" },
373     { OPTION_LIFETIME,         "Lifetime" },
374     { OPTION_BCMCS_SERVER_D,   "BCMCS Server Domain" },
375     { OPTION_BCMCS_SERVER_A,   "BCMCS Servers IPv6 Address List" },
376     { OPTION_GEOCONF_CIVIC,    "Geoconf Civic Address" },
377     { OPTION_REMOTE_ID,        "Remote Identifier" },
378     { OPTION_SUBSCRIBER_ID,    "Subscriber Identifier" },
379     { OPTION_CLIENT_FQDN,      "Fully Qualified Domain Name" },
380     { OPTION_PANA_AGENT,       "PANA Agents IPv6 Address List" },
381     { OPTION_TIME_ZONE,        "Time Zone" },
382     { OPTION_TZDB,             "Time Zone Database" },
383     { OPTION_ERO,              "Echo Request Option" },
384     { OPTION_LQ_QUERY,         "Leasequery Query" },
385     { OPTION_CLIENT_DATA,      "Leasequery Client Data" },
386     { OPTION_CLT_TIME,         "Client Last Transaction Time" },
387     { OPTION_LQ_RELAY_DATA,    "Leasequery Relay Data" },
388     { OPTION_LQ_CLIENT_LINK,   "Leasequery Client Link Address List" },
389     { OPTION_CAPWAP_AC_V6,     "CAPWAP Access Controllers" },
390     { OPTION_AFTR_NAME,        "Dual-Stack Lite AFTR Name" },
391     { OPTION_PD_EXCLUDE,       "Prefix Exclude" },
392     { OPTION_MIP6_HA,          "Mobile IPv6 Home Agent" },
393     { OPTION_MIP6_HOA,         "Mobile IPv6 Home Address" },
394     { OPTION_NAI,              "Network Access Identifier" },
395     { 0,        NULL }
396 };
397
398 static const value_string statuscode_vals[] =
399 {
400     {0, "Success" },
401     {1, "UnspecFail" },
402     {2, "NoAddrAvail" },
403     {3, "NoBinding" },
404     {4, "NotOnLink" },
405     {5, "UseMulticast" },
406     {6, "NoPrefixAvail" },
407     {7, "UnknownQueryType" },
408     {8, "MalformedQuery" },
409     {9, "NotConfigured" },
410     {10, "NotAllowed" },
411     {11, "QueryTerminated" },
412     {0, NULL }
413 };
414
415 static const value_string duidtype_vals[] =
416 {
417     { DUID_LLT,    "link-layer address plus time" },
418     { DUID_EN,     "assigned by vendor based on Enterprise number" },
419     { DUID_LL,     "link-layer address" },
420     { DUID_LL_OLD, "link-layer address (old)" },
421     { 0, NULL }
422 };
423
424 #define NTP_SUBOPTION_SRV_ADDR  1
425 #define NTP_SUBOPTION_MC_ADDR   2
426 #define NTP_SUBOPTION_SRV_FQDN  3
427
428 static const value_string ntp_server_opttype_vals[] =
429 {
430     { NTP_SUBOPTION_SRV_ADDR,    "NTP Server Address" },
431     { NTP_SUBOPTION_MC_ADDR,     "NTP Multicast Address" },
432     { NTP_SUBOPTION_SRV_FQDN,    "NTP Server FQDN" },
433
434     { 0, NULL }
435 };
436
437
438 static const true_false_string fqdn_n = {
439     "Server should not perform DNS updates",
440     "Server should perform DNS updates"
441 };
442
443 static const true_false_string fqdn_o = {
444     "Server has overridden client's S bit preference",
445     "Server has not overridden client's S bit preference"
446 };
447
448 static const true_false_string fqdn_s = {
449     "Server should perform forward DNS updates",
450     "Server should not perform forward DNS updates"
451 };
452
453 #define LQ_QUERY_ADDRESS        1
454 #define LQ_QUERY_CLIENTID       2
455 #define LQ_QUERY_RELAYID        3
456 #define LQ_QUERY_LINK_ADDRESS   4
457 #define LQ_QUERY_REMOTEID       5
458
459 static const value_string lq_query_vals[] = {
460     { LQ_QUERY_ADDRESS,      "by-address" },
461     { LQ_QUERY_CLIENTID,     "by-clientID" },
462     { LQ_QUERY_RELAYID,      "by-relayID" },
463     { LQ_QUERY_LINK_ADDRESS, "by-linkAddress" },
464     { LQ_QUERY_REMOTEID,     "by-remoteID" },
465     { 0, NULL },
466 };
467
468 /* CableLabs Common Vendor Specific Options */
469 #define CL_OPTION_ORO                     0x0001 /* 1 */
470 #define CL_OPTION_DEVICE_TYPE             0x0002 /* 2 */
471 #define CL_OPTION_EMBEDDED_COMPONENT_LIST 0x0003 /* 3 */
472 #define CL_OPTION_DEVICE_SERIAL_NUMBER    0x0004 /* 4 */
473 #define CL_OPTION_HARDWARE_VERSION_NUMBER 0x0005 /* 5 */
474 #define CL_OPTION_SOFTWARE_VERSION_NUMBER 0x0006 /* 6 */
475 #define CL_OPTION_BOOT_ROM_VERSION        0x0007 /* 7 */
476 #define CL_OPTION_VENDOR_OUI              0x0008 /* 8 */
477 #define CL_OPTION_MODEL_NUMBER            0x0009 /* 9 */
478 #define CL_OPTION_VENDOR_NAME             0x000a /* 10 */
479 /* 11-32 is currently reserved */
480 #define CL_OPTION_TFTP_SERVERS            0x0020 /* 32 */
481 #define CL_OPTION_CONFIG_FILE_NAME        0x0021 /* 33 */
482 #define CL_OPTION_SYSLOG_SERVERS          0x0022 /* 34 */
483 #define CL_OPTION_TLV5                    0x0023 /* 35 */
484 #define CL_OPTION_DEVICE_ID               0x0024 /* 36 */
485 #define CL_OPTION_RFC868_SERVERS          0x0025 /* 37 */
486 #define CL_OPTION_TIME_OFFSET             0x0026 /* 38 */
487 #define CL_OPTION_IP_PREF                 0x0027 /* 39 */
488
489 /** CableLabs DOCSIS Project Vendor Specific Options */
490 #define CL_OPTION_DOCS_CMTS_CAP 0x0401  /* 1025 */
491 #define CL_CM_MAC_ADDR 0x0402 /* 1026 */
492 #define CL_EROUTER_CONTAINER_OPTION 0x403 /* 1027 */
493
494 /** CableLabs PacketCable Project Vendor Specific Options **/
495 #define CL_OPTION_CCC 0x087a  /* 2170 */
496 #define CL_OPTION_CCCV6 0x087b  /* 2171 */
497 #define CL_OPTION_CORRELATION_ID 0x087c /*2172 */
498
499 /** CableLabs TLVs for DOCS_CMTS_CAP Vendor Option **/
500 #define CL_OPTION_DOCS_CMTS_TLV_VERS_NUM 0x01 /* 1 */
501
502 static const value_string cl_vendor_subopt_values[] = {
503     /*    1 */ { CL_OPTION_ORO, "Option Request = " },
504     /*    2 */ { CL_OPTION_DEVICE_TYPE, "Device Type = " },
505     /*    3 */ { CL_OPTION_EMBEDDED_COMPONENT_LIST, "Embedded Components = " },
506     /*    4 */ { CL_OPTION_DEVICE_SERIAL_NUMBER, "Serial Number = " },
507     /*    5 */ { CL_OPTION_HARDWARE_VERSION_NUMBER, "Hardware Version = " },
508     /*    6 */ { CL_OPTION_SOFTWARE_VERSION_NUMBER, "Software Version = " },
509     /*    7 */ { CL_OPTION_BOOT_ROM_VERSION, "Boot ROM Version = " },
510     /*    8 */ { CL_OPTION_VENDOR_OUI, "Organization Unique Identifier = " },
511     /*    9 */ { CL_OPTION_MODEL_NUMBER, "Model Number = " },
512     /*   10 */ { CL_OPTION_VENDOR_NAME, "Vendor Name = " },
513     /*   32 */ { CL_OPTION_TFTP_SERVERS, "TFTP Server Addresses : " },
514     /*   33 */ { CL_OPTION_CONFIG_FILE_NAME, "Configuration File Name = " },
515     /*   34 */ { CL_OPTION_SYSLOG_SERVERS, "Syslog Servers : " },
516     /*   35 */ { CL_OPTION_TLV5, "TLV5 = " },
517     /*   36 */ { CL_OPTION_DEVICE_ID, "Device Identifier = " },
518     /*   37 */ { CL_OPTION_RFC868_SERVERS, "Time Protocol Servers : " },
519     /*   38 */ { CL_OPTION_TIME_OFFSET, "Time Offset = " },
520     /*   39 */ { CL_OPTION_IP_PREF, "IP preference : " },
521     /* 1025 */ { CL_OPTION_DOCS_CMTS_CAP, "CMTS Capabilities Option : " },
522     /* 1026 */ { CL_CM_MAC_ADDR, "CM MAC Address Option = " },
523     /* 1027 */ { CL_EROUTER_CONTAINER_OPTION, "eRouter Container Option : " },
524     /* 2170 */ { CL_OPTION_CCC, "CableLabs Client Configuration : " },
525     /* 2171 */ { CL_OPTION_CCCV6, "CableLabs Client Configuration IPv6 : " },
526     /* 2172 */ { CL_OPTION_CORRELATION_ID, "CableLabs Correlation ID = " },
527     { 0, NULL }
528 };
529
530 #define PKT_CCC_PRI_DHCP       0x0001
531 #define PKT_CCC_SEC_DHCP       0x0002
532 #define PKT_CCC_IETF_PROV_SRV  0x0003
533 #define PKT_CCC_IETF_AS_KRB    0x0004
534 #define PKT_CCC_IETF_AP_KRB    0x0005
535 #define PKT_CCC_KRB_REALM      0x0006
536 #define PKT_CCC_TGT_FLAG       0x0007
537 #define PKT_CCC_PROV_TIMER     0x0008
538 #define PKT_CCC_IETF_SEC_TKT   0x0009
539 /** 10 -255 Reserved for future extensions **/
540
541 #define PKT_CCCV6_PRI_DSS       0x0001
542 #define PKT_CCCV6_SEC_DSS       0x0002
543 #define PKT_CCCV6_IETF_PROV_SRV 0x0003
544 #define PKT_CCCV6_IETF_AS_KRB   0x0004
545 #define PKT_CCCV6_IETF_AP_KRB   0x0005
546 #define PKT_CCCV6_KRB_REALM     0x0006
547 #define PKT_CCCV6_TGT_FLAG      0x0007
548 #define PKT_CCCV6_PROV_TIMER    0x0008
549 #define PKT_CCCV6_IETF_SEC_TKT  0x0009
550 /** 10 -255 Reserved for future extensions **/
551
552 static const value_string pkt_ccc_opt_vals[] = {
553     { PKT_CCC_PRI_DHCP,      "TSP's Primary DHCP Server" },
554     { PKT_CCC_SEC_DHCP,      "TSP's Secondary DHCP Server" },
555     { PKT_CCC_IETF_PROV_SRV, "TSP's Provisioning Server" },
556     { PKT_CCC_IETF_AS_KRB,   "TSP's AS-REQ/AS-REP Backoff and Retry" },
557     { PKT_CCC_IETF_AP_KRB,   "TSP's AP-REQ/AP-REP Backoff and Retry" },
558     { PKT_CCC_KRB_REALM,     "TSP's Kerberos Realm Name" },
559     { PKT_CCC_TGT_FLAG,      "TSP's Ticket Granting Server Utilization" },
560     { PKT_CCC_PROV_TIMER,    "TSP's Provisioning Timer Value" },
561     { PKT_CCC_IETF_SEC_TKT,  "PacketCable Security Ticket Control" },
562     { 0, NULL },
563 };
564
565 static const value_string pkt_ccc_prov_srv_type_vals[] = {
566     { 0,      "FQDN" },
567     { 1,      "IPv4" },
568     { 0, NULL },
569 };
570
571 static const value_string pkt_cccV6_prov_srv_type_vals[] = {
572     { 0,      "FQDN" },
573     { 1,      "IPv6" },
574     { 0, NULL },
575 };
576
577 static const value_string pkt_cccV6_opt_vals[] = {
578     { PKT_CCCV6_PRI_DSS,        "TSP's Primary DHCPv6 Server Selector ID" },
579     { PKT_CCCV6_SEC_DSS,        "TSP's Secondary DHCPv6 Server Selector ID " },
580     { PKT_CCCV6_IETF_PROV_SRV,  "TSP's Provisioning Server" },
581     { PKT_CCCV6_IETF_AS_KRB,    "TSP's AS-REQ/AS-REP Backoff and Retry" },
582     { PKT_CCCV6_IETF_AP_KRB,    "TSP's AP-REQ/AP-REP Backoff and Retry" },
583     { PKT_CCCV6_KRB_REALM,      "TSP's Kerberos Realm Name" },
584     { PKT_CCCV6_TGT_FLAG,       "TSP's Ticket Granting Server Utilization" },
585     { PKT_CCCV6_PROV_TIMER,     "TSP's Provisioning Timer Value" },
586     { PKT_CCCV6_IETF_SEC_TKT,   "PacketCable Security Ticket Control" },
587     { 0, NULL }
588 };
589
590 #if 0
591 static const value_string sec_tcm_vals[] = {
592     { 1 << 0, "PacketCable Provisioning Server" },
593     { 1 << 1, "PacketCable Call Manager Servers" },
594     { 0, NULL },
595 };
596 #endif
597
598 static const value_string modem_capabilities_encoding [] = {
599     { 1,      "Concatenation Support" },
600     { 2,      "DOCSIS Version" },
601     { 3,      "Fragmentation Support" },
602     { 4,      "Payload Header Suppression Support" },
603     { 5,      "IGMP Support" },
604     { 6,      "Privacy Support" },
605     { 7,      "Downstream SAID Support" },
606     { 8,      "Upstream Service Flow Support" },
607     { 9,      "Optional Filtering Support" },
608     { 10,      "Transmit Pre-Equalizer Taps per Modulation Interval" },
609     { 11,      "Number of Transmit Equalizer Taps" },
610     { 12,      "DCC Support" },
611     { 13,      "IP Filters Support" },
612     { 14,      "LLC Filters Support" },
613     { 15,      "Expanded Unicast SID Space" },
614     { 16,      "Ranging Hold-Off Support" },
615     { 17,      "L2VPN Capability" },
616     { 18,      "L2VPN eSAFE Host Capability" },
617     { 19,      "Downstream Unencrypted Traffic (DUT) Filtering" },
618     { 20,      "Upstream Frequency Range Support" },
619     { 21,      "Upstream Symbol Rate Support" },
620     { 22,      "Selectable Active Code Mode 2 Support" },
621     { 23,      "Code Hopping Mode 2 Support" },
622     { 24,      "Multiple Transmit Channel Support" },
623     { 25,      "5.12 Msps UpstreamTransmit Channel Support" },
624     { 26,      "2.56 Msps Upstream Transmit Channel Support" },
625     { 27,      "Total SID Cluster Support" },
626     { 28,      "SID Clusters per Service Flow Support" },
627     { 29,      "Multiple Receive Channel Support" },
628     { 30,      "Total Downstream Service ID (DSID) Support" },
629     { 31,      "Resequencing Downstream Service ID (DSID) Support" },
630     { 32,      "Multicast Downstream Service ID (DSID) Support" },
631     { 33,      "Multicast DSID Forwarding" },
632     { 34,      "Frame Control Type Forwarding Capability" },
633     { 35,      "DPV Capability" },
634     { 36,      "Unsolicited Grant Service/Upstream Service Flow Support" },
635     { 37,      "MAP and UCD Receipt Support" },
636     { 38,      "Upstream Drop Classifier Support" },
637     { 39,      "IPv6 Support" },
638     { 40,      "Extended Upstream Transmit Power Capability" },
639     { 41,      "Optional 802.1ad, 802.1ah, MPLS Classification Support" },
640     { 42,      "D-ONU Capabilities Encoding" },
641     { 43,      "TBD" },
642     { 44,      "Energy Management Capabilities" },
643     { 0, NULL },
644 };
645
646 static const value_string eue_capabilities_encoding [] = {
647     { 1,       "PacketCable Version" },
648     { 2,       "Number Of Telephony Endpoints" },
649     { 3,       "TGT Support" },
650     { 4,       "HTTP Download File Access Method Support" },
651     { 5,       "MTA-24 Event SYSLOG Notification Support" },
652     { 6,       "NCS Service Flow Support" },
653     { 7,       "Primary Line Support" },
654     { 8,       "Vendor Specific TLV Type(s)" },
655     { 9,       "NVRAM Ticket/Ticket Information Storage Support" },
656     { 10,      "Provisioning Event Reporting Support" },
657     { 11,      "Supported CODEC(s)" },
658     { 12,      "Silence Suppression Support" },
659     { 13,      "Echo Cancellation Support" },
660     { 14,      "RSVP Support" },
661     { 15,      "UGS-AD Support" },
662     { 16,      "MTA's \"ifIndex\" starting number in \"ifTable\"" },
663     { 17,      "Provisioning Flow Logging Support" },
664     { 18,      "Supported Provisioning Flows" },
665     { 19,      "T38 Version Support" },
666     { 20,      "T38 Error Correction Support" },
667     { 21,      "RFC2833 DTMF Support" },
668     { 22,      "Voice Metrics Support" },
669     { 23,      "Device MIB Support" },
670     { 24,      "Multiple Grants Per Interval Support" },
671     { 25,      "V.152 Support" },
672     { 26,      "Certificate Bootstrapping Support" },
673     { 38,      "IP Address Provisioning Capability" },
674     { 0, NULL },
675 };
676
677 /* May be called recursively */
678 static void
679 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
680                gboolean downstream, int off, int eoff);
681
682 static gint
683 swap_field_length_with_char(tvbuff_t* tvb, wmem_strbuf_t* strbuf, gint offset, gint subopt_len, gchar replacement)
684 {
685     gint len_cnt = 0;
686     gint next_length = 0;
687
688     while (len_cnt < subopt_len) {
689         next_length = tvb_get_guint8(tvb, offset);
690         offset++;
691         len_cnt++;
692
693         wmem_strbuf_append(strbuf, tvb_get_string(wmem_packet_scope(), tvb, offset, next_length));
694         len_cnt += next_length;
695
696         /* Do not append replacement character to end of string. */
697         if (len_cnt+2 < subopt_len) {
698             wmem_strbuf_append_c(strbuf, replacement);
699         }
700         offset += next_length;
701     }
702     return len_cnt;
703 }
704
705 static int
706 dissect_packetcable_ccc_option(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int optoff,
707                                int optend)
708 {
709     /** THE ENCODING OF THIS SUBOPTION HAS CHANGED FROM DHCPv4
710         the code and length fields have grown from a single octet to
711         two octets each. **/
712     int suboptoff = optoff;
713     guint16 subopt, subopt_len;
714     guint8 type;
715     proto_item *vti, *ti;
716     proto_tree *pkt_s_tree;
717     guchar kr_name;       /** A character in the kerberos realm name option */
718     guint8 kr_value;      /* The integer value of the character currently being tested */
719     int kr_fail_flag = 0; /* Flag indicating an invalid character was found */
720     int kr_pos = 0;       /* The position of the first invalid character */
721     gint i = 0;
722
723     subopt = tvb_get_ntohs(tvb, optoff);
724     suboptoff += 2;
725
726     subopt_len = tvb_get_ntohs(tvb, suboptoff);
727     suboptoff += 2;
728
729     /* There must be at least five octets left to be a valid sub element */
730     if (optend <= 0) {
731         expert_add_info_format(pinfo, v_item, &ei_dhcpv6_no_suboption_len, "Sub element %d: no room left in option for suboption length", subopt);
732         return (optend);
733     }
734     /* g_print("dissect packetcable ccc option subopt_len=%d optend=%d\n\n", subopt_len, optend); */
735
736     vti = proto_tree_add_item(v_tree, hf_packetcable_ccc_suboption, tvb, optoff, 2, ENC_BIG_ENDIAN);
737     pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
738
739     switch (subopt) {
740     case PKT_CCC_PRI_DHCP:      /* IPv4 address values */
741         if (subopt_len == 4) {
742             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_pri_dhcp, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
743         }
744         else {
745             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
746         }
747
748         suboptoff += subopt_len;
749         break;
750     case PKT_CCC_SEC_DHCP:
751         if (subopt_len == 4) {
752             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_sec_dhcp, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
753         }
754         else {
755             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
756         }
757
758         suboptoff += subopt_len;
759         break;
760     case PKT_CCC_IETF_PROV_SRV :
761         proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_prov_srv_type, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
762         type = tvb_get_guint8(tvb, suboptoff);
763
764         /** Type 0 is FQDN **/
765         if (type == 0) {
766             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_prov_srv_fqdn, tvb, suboptoff+1, subopt_len-1, ENC_ASCII|ENC_NA);
767         }
768         /** Type 1 is IPv4 **/
769         else if (type == 1) {
770             if (subopt_len == 5) {
771                 proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_prov_srv_ipv4, tvb, suboptoff+1, 4, ENC_BIG_ENDIAN);
772             }
773             else {
774                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
775             }
776         }
777         else {
778             expert_add_info_format(pinfo, vti, &ei_dhcpv6_invalid_type, "Invalid type: %u (%u byte%s)",
779                 type, subopt_len, plurality(subopt_len, "", "s"));
780         }
781         suboptoff += subopt_len;
782         break;
783     case PKT_CCC_IETF_AS_KRB :
784         if (subopt_len == 12) {
785             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_as_krb_nominal_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
786             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_as_krb_max_timeout, tvb, suboptoff+4, 4, ENC_BIG_ENDIAN);
787             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_as_krb_max_retry_count, tvb, suboptoff+8, 4, ENC_BIG_ENDIAN);
788         }
789         else {
790             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
791         }
792         suboptoff += subopt_len;
793         break;
794     case PKT_CCC_IETF_AP_KRB :
795         if (subopt_len == 12) {
796             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_ap_krb_nominal_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
797             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_ap_krb_max_timeout, tvb, suboptoff+4, 4, ENC_BIG_ENDIAN);
798             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_ap_krb_max_retry_count, tvb, suboptoff+8, 4, ENC_BIG_ENDIAN);
799         }
800         else {
801             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
802         }
803         suboptoff += subopt_len;
804         break;
805     case PKT_CCC_KRB_REALM:
806         if (subopt_len > 0) {
807             /** The only allowable characters are
808                 A-Z (upper case only) 65-90
809                 '.', 46
810                 '/', 47
811                 '\', 92
812                 '=', 61
813                 '"', 34
814                 ',', 44
815                 and
816                 ':' 58
817                 so loop through and
818                 make sure it conforms to the expected syntax.
819             **/
820             for (i=0; i < subopt_len; i++) {
821                 kr_name = tvb_get_guint8(tvb, suboptoff + i);
822                 kr_value = (int)kr_name;
823                 if ((kr_value >= 65 && kr_value <= 90) ||
824                     kr_value == 34 ||
825                     kr_value == 44 ||
826                     kr_value == 46 ||
827                     kr_value == 47 ||
828                     kr_value == 58 ||
829                     kr_value == 61 ||
830                     kr_value == 92)   {
831                 }
832                 else if (!kr_fail_flag) {
833                     kr_pos = i;
834                     kr_fail_flag = 1;
835                 }
836             }
837
838             ti = proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_krb_realm, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA);
839             if (kr_fail_flag)
840                 expert_add_info_format(pinfo, ti, &ei_dhcpv6_invalid_byte, "Invalid at byte=%d", kr_pos);
841         }
842         suboptoff += subopt_len;
843         break;
844     case PKT_CCC_TGT_FLAG:
845         if (subopt_len == 1) {
846             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_tgt_flag, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
847             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_tgt_flag_fetch, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
848         }
849         else {
850             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
851         }
852         suboptoff += subopt_len;
853         break;
854     case PKT_CCC_PROV_TIMER:
855         if (subopt_len == 1) {
856             ti = proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_prov_timer, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
857             if (tvb_get_guint8(tvb, suboptoff ) > 30)
858                 expert_add_info(pinfo, ti, &ei_dhcpv6_invalid_time_value);
859         }
860         else {
861             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
862         }
863         suboptoff += subopt_len;
864         break;
865     case PKT_CCC_IETF_SEC_TKT :
866         proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_sec_tcm, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
867         if (subopt_len == 2) {
868             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_sec_tcm_provisioning_server, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
869             proto_tree_add_item(pkt_s_tree, hf_packetcable_ccc_sec_tcm_call_manager_server, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
870         } else {
871             expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
872         }
873         suboptoff += subopt_len;
874         break;
875     default:
876         suboptoff += subopt_len;
877         break;
878
879     }
880
881     /** Return the number of bytes processed **/
882     return (suboptoff - optoff);
883 }
884
885 static int
886 dissect_packetcable_cccV6_option(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int optoff,
887     int optend)
888 {
889     int suboptoff = optoff;
890     guint16 subopt, subopt_len;
891     guint8 type;
892     proto_item *vti, *ti;
893     proto_tree *pkt_s_tree;
894     /* guchar kr_name; */        /* A character in the kerberos realm name option */
895     guint8 kr_value;        /* The integer value of the character currently being tested */
896     int kr_fail_flag = 0;   /* Flag indicating an invalid character was found */
897     int kr_pos = 0;         /* The position of the first invalid character */
898     int i = 0;
899
900     subopt = tvb_get_ntohs(tvb, optoff);
901     suboptoff += 2;
902
903     subopt_len = tvb_get_ntohs(tvb, suboptoff);
904     suboptoff += 2;
905
906     /* There must be at least five octets left to be a valid sub element */
907     if (optend <= 0) {
908         expert_add_info_format(pinfo, v_item, &ei_dhcpv6_no_suboption_len, "Sub element %d: no room left in option for suboption length", subopt);
909         return (optend);
910     }
911
912     vti = proto_tree_add_item(v_tree, hf_packetcable_cccV6_suboption, tvb, optoff, 2, ENC_BIG_ENDIAN);
913     pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
914
915     switch (subopt) {
916         case PKT_CCCV6_PRI_DSS:
917             if (subopt_len < 35) {
918                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_pri_dss, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA);
919             } else {
920                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
921             }
922             suboptoff += subopt_len;
923             break;
924         case PKT_CCCV6_SEC_DSS:
925             if (subopt_len < 35) {
926                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_dss, tvb, suboptoff, subopt_len, ENC_ASCII|ENC_NA);
927             } else {
928                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
929             }
930             suboptoff += subopt_len;
931             break;
932         case PKT_CCCV6_IETF_PROV_SRV:
933             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_prov_srv_type, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
934             type = tvb_get_guint8(tvb, suboptoff);
935
936             /** Type 0 is FQDN **/
937             if (type == 0) {
938
939                 gint len_cnt;
940                 wmem_strbuf_t* strbuf = NULL;
941                 strbuf = wmem_strbuf_new(wmem_packet_scope(), "");
942
943                 len_cnt = swap_field_length_with_char(tvb, strbuf, suboptoff+1, subopt_len, '.');
944
945                 if (len_cnt < 1) {
946                     proto_tree_add_string(pkt_s_tree, hf_packetcable_cccV6_prov_srv_fqdn, tvb, suboptoff+2, 28,
947                                           "Packet does not contain FQDN");
948                 } else {
949                     proto_tree_add_string(pkt_s_tree, hf_packetcable_cccV6_prov_srv_fqdn, tvb,
950                                           suboptoff+2, subopt_len-3, wmem_strbuf_get_str(strbuf));
951                 }
952
953             /** Type 1 is IPv6 **/
954             } else if (type == 1) {
955                 if ((subopt_len % 16) == 0) {
956                     for (i = 0; i < subopt_len/16; i++) {
957                         proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_prov_srv_ipv6, tvb, suboptoff+1, 4, ENC_NA);
958                         suboptoff += 16;
959                     }
960                 }
961             } else {
962                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_invalid_type, "Invalid type: %u (%u byte%s)",
963                     type, subopt_len, plurality(subopt_len, "", "s"));
964             }
965             suboptoff += subopt_len;
966             break;
967         case PKT_CCCV6_IETF_AS_KRB:
968             if (subopt_len == 12) {
969                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_as_krb_nominal_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
970                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_as_krb_max_timeout, tvb, suboptoff+4, 4, ENC_BIG_ENDIAN);
971                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_as_krb_max_retry_count, tvb, suboptoff+8, 4, ENC_BIG_ENDIAN);
972             } else {
973                 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
974             }
975             suboptoff += subopt_len;
976             break;
977         case PKT_CCCV6_IETF_AP_KRB:
978             if (subopt_len == 12) {
979                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_ap_krb_nominal_timeout, tvb, suboptoff, 4, ENC_BIG_ENDIAN);
980                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_ap_krb_max_timeout, tvb, suboptoff+4, 4, ENC_BIG_ENDIAN);
981                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_ap_krb_max_retry_count, tvb, suboptoff+8, 4, ENC_BIG_ENDIAN);
982             } else {
983                 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
984             }
985             suboptoff += subopt_len;
986             break;
987         case PKT_CCCV6_KRB_REALM:
988             if (subopt_len > 0) {
989                 gint cnt;
990                 gint len_cnt;
991                 proto_item* pi_tmp = NULL;
992                 wmem_strbuf_t* strbuf = NULL;
993                 strbuf = wmem_strbuf_new(wmem_packet_scope(), "");
994
995                 len_cnt = swap_field_length_with_char(tvb, strbuf, suboptoff, subopt_len, '.');
996
997                 if (len_cnt < 1) {
998                     proto_tree_add_string(pkt_s_tree, hf_packetcable_cccV6_prov_srv_fqdn, tvb, suboptoff+2, 34,
999                                           "Packet does not contain KRB Realm");
1000                 } else {
1001                     pi_tmp = proto_tree_add_string(pkt_s_tree, hf_packetcable_cccV6_krb_realm, tvb,
1002                                                    suboptoff+1, subopt_len-2, wmem_strbuf_get_str(strbuf));
1003                 }
1004
1005                 /* Validate KRB Realm name encoding (sort of) and syntax per RFCs 3495, 1510, and 1035 */
1006                 for (cnt=0; cnt < len_cnt-2; cnt++) {
1007                     kr_value = (int) wmem_strbuf_get_str(strbuf)[cnt];
1008                     if ((kr_value >= 65 && kr_value <= 90)
1009                         || kr_value == 34
1010                         || kr_value == 44
1011                         || kr_value == 46
1012                         || kr_value == 47
1013                         || kr_value == 58
1014                         || kr_value == 61
1015                         || kr_value == 92) {
1016                     } else if (!kr_fail_flag) {
1017                         kr_pos = cnt;
1018                         kr_fail_flag = 1;
1019                     }
1020                 }
1021                 if (kr_fail_flag)
1022                     expert_add_info_format(pinfo, pi_tmp, &ei_dhcpv6_invalid_byte, "Invalid at byte=%d", kr_pos);
1023             }
1024             suboptoff += subopt_len;
1025             break;
1026         case PKT_CCCV6_TGT_FLAG:
1027             if (subopt_len == 1) {
1028                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_tgt_flag, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1029                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_tgt_flag_fetch, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1030             }
1031             else {
1032                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1033             }
1034             suboptoff += subopt_len;
1035             break;
1036         case PKT_CCCV6_PROV_TIMER:
1037             if (subopt_len == 1) {
1038                 ti = proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_prov_timer, tvb, suboptoff, 1, ENC_BIG_ENDIAN);
1039                 if (tvb_get_guint8(tvb, suboptoff ) > 30)
1040                     expert_add_info(pinfo, ti, &ei_dhcpv6_invalid_time_value);
1041             }
1042             else {
1043                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1044             }
1045             suboptoff += subopt_len;
1046             break;
1047         case PKT_CCCV6_IETF_SEC_TKT:
1048             proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_tcm, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
1049             if (subopt_len == 2) {
1050                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_tcm_provisioning_server, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
1051                 proto_tree_add_item(pkt_s_tree, hf_packetcable_cccV6_sec_tcm_call_manager_server, tvb, suboptoff, 2, ENC_BIG_ENDIAN);
1052             } else {
1053                 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
1054             }
1055             suboptoff += subopt_len;
1056             break;
1057         default:
1058             suboptoff += subopt_len;
1059             break;
1060     }
1061     /** Return the number of bytes processed **/
1062     return (suboptoff - optoff);
1063 }
1064
1065 static void
1066 dissect_cablelabs_specific_opts(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int voff, int len)
1067 {
1068     guint16 type,
1069             tlv_len, /* holds the number of elements in the tlv */
1070             opt_len, /* holds the length of the suboption */
1071             sub_value;
1072     proto_item *ti;
1073     proto_item *ti2;
1074     proto_tree *subtree;
1075     proto_tree *subtree2;
1076     gint tlv5_cap_index,
1077          tlv5_counter,
1078          tlv5_cap_len;
1079     int off = voff,
1080         sub_off, /** The offset for the sub-option */
1081         i,
1082         field_len, /* holds the length of one occurrence of a field */
1083         field_value;
1084     gchar* device_type = NULL;
1085
1086     if (len > 4) {
1087         while (off - voff < len) {
1088
1089             /* Type */
1090             type = tvb_get_ntohs(tvb, off);
1091             ti = proto_tree_add_item(v_tree, hf_cablelabs_opts, tvb, off, 2, ENC_BIG_ENDIAN);
1092             /* Length */
1093             tlv_len = tvb_get_ntohs(tvb, off+2);
1094
1095             /* Values */
1096             sub_off = off + 4;
1097
1098             switch(type) {
1099                 /* String types */
1100             case CL_OPTION_DEVICE_TYPE :
1101                 opt_len = tlv_len;
1102                 field_len = tlv_len;
1103
1104                 device_type = tvb_get_string(wmem_packet_scope(), tvb, sub_off, field_len);
1105
1106                 if (device_type == NULL || strlen(device_type) == 0) {
1107                     proto_item_append_text(ti, "Packet does not contain Device Type.");
1108                 } else {
1109                     proto_item_append_text(ti, "\"%s\"", device_type);
1110                 }
1111                 break;
1112             case CL_OPTION_DEVICE_SERIAL_NUMBER :
1113             case CL_OPTION_HARDWARE_VERSION_NUMBER :
1114             case CL_OPTION_SOFTWARE_VERSION_NUMBER :
1115             case CL_OPTION_BOOT_ROM_VERSION :
1116             case CL_OPTION_MODEL_NUMBER :
1117             case CL_OPTION_VENDOR_NAME :
1118             case CL_OPTION_CONFIG_FILE_NAME :
1119             case CL_OPTION_EMBEDDED_COMPONENT_LIST :
1120                 opt_len = tlv_len;
1121                 field_len = tlv_len;
1122                 proto_item_append_text(ti, "\"%s\"",
1123                                        tvb_format_stringzpad(tvb, sub_off, field_len));
1124                 break;
1125             case CL_OPTION_VENDOR_OUI :
1126                 /* CableLabs specs treat 17.8 inconsistently
1127                  * as either binary (3b) or string (6b) */
1128                 opt_len = tlv_len;
1129                 if (tlv_len == 3) {
1130                     proto_item_append_text(ti, "%s",
1131                         tvb_bytes_to_str_punct(tvb, sub_off, 3, ':'));
1132                 } else if (tlv_len == 6) {
1133                     proto_item_append_text(ti, "\"%s\"", tvb_format_stringzpad(tvb, sub_off, tlv_len));
1134                 } else {
1135                     expert_add_info_format(pinfo, ti, &ei_dhcpv6_bogus_length, "Suboption %d: suboption length isn't 3 or 6", type);
1136                 }
1137                 break;
1138             case CL_OPTION_ORO :
1139                 field_len = 2;
1140                 opt_len = tlv_len;
1141                 if (opt_len > 0) {
1142                     for (i = 0; i < tlv_len; i += field_len) {
1143                         sub_value = tvb_get_ntohs(tvb, sub_off);
1144                         proto_item_append_text(ti, " %d", sub_value);
1145                         sub_off += field_len;
1146                     }
1147                 }
1148                 break;
1149                 /* List of IPv6 Address */
1150             case CL_OPTION_TFTP_SERVERS :
1151             case CL_OPTION_SYSLOG_SERVERS :
1152             case CL_OPTION_RFC868_SERVERS :
1153                 field_len = 16;
1154                 opt_len = tlv_len;
1155                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1156
1157                 if ((tlv_len % field_len) == 0) {
1158                     for (i = 0; i < tlv_len/field_len; i++) {
1159                         ti = proto_tree_add_item(subtree, hf_cablelabs_ipv6_server, tvb, sub_off, 16, ENC_NA);
1160                         proto_item_prepend_text(ti, " %d ", i + 1);
1161                         sub_off += field_len;
1162                     }
1163                 }
1164                 break;
1165             case CL_OPTION_DEVICE_ID :
1166                 opt_len = tlv_len;
1167                 field_len = tlv_len;
1168                 if (tlv_len != 6) {
1169                     expert_add_info_format(pinfo, ti, &ei_dhcpv6_bogus_length, "Bogus length: %d", tlv_len);
1170                 }
1171                 else {
1172                     proto_item_append_text(ti, "%s",
1173                                            tvb_bytes_to_str(tvb, sub_off, field_len));
1174                 }
1175                 break;
1176             case CL_OPTION_TLV5 :
1177                 opt_len = tlv_len;
1178
1179                 if (device_type == NULL)
1180                     break;
1181
1182                 tlv5_counter = 0;
1183                 tlv5_cap_index = sub_off;
1184
1185                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_tlv5_type);
1186
1187                 while (tlv5_counter < tlv_len) {
1188
1189                     if (!g_ascii_strncasecmp(device_type, "ecm", 3)) {
1190                         ti2 = proto_tree_add_item(subtree, hf_modem_capabilities_encoding_type, tvb, tlv5_cap_index, 1, ENC_BIG_ENDIAN);
1191                     } else if (!g_ascii_strncasecmp(device_type, "edva", 3)) {
1192                         ti2 = proto_tree_add_item(subtree, hf_eue_capabilities_encoding_type, tvb, tlv5_cap_index, 1, ENC_BIG_ENDIAN);
1193                     } else {
1194                         break;
1195                     }
1196
1197                     tlv5_cap_index++;
1198                     tlv5_counter++;
1199
1200                     /* Why make another subtree (subtree2) below?
1201                        The addition of a subtree is not needed for the display.
1202                        However, when parsing the PDML, each Type 'contains' it's Length and Value.
1203                     */
1204                     subtree2 = proto_item_add_subtree(ti2, ett_dhcpv6_tlv5_type);
1205
1206                     proto_tree_add_item(subtree2, hf_capabilities_encoding_length, tvb, tlv5_cap_index, 1, ENC_BIG_ENDIAN);
1207                     tlv5_cap_len = (guint8) tvb_get_guint8(tvb, tlv5_cap_index);
1208
1209                     tlv5_cap_index++;
1210                     tlv5_counter += tlv5_cap_len;
1211
1212                     /* In cases where the TLV length is greater than 2, the value fields should be displayed
1213                        according to the encoding of the values as described in the CL-SP-CANN-DHCP-Reg specification.
1214                        Below, these values are simply displayed as hex.
1215                     */
1216                     if (tlv5_cap_len > 2) {
1217                             proto_tree_add_item(subtree2, hf_capabilities_encoding_bytes, tvb, tlv5_cap_index, tlv5_cap_len, ENC_NA);
1218                     } else {
1219                             proto_tree_add_item(subtree2, hf_capabilities_encoding_number, tvb, tlv5_cap_index, tlv5_cap_len, ENC_BIG_ENDIAN);
1220                     }
1221
1222                     tlv5_cap_index += tlv5_cap_len;
1223                     tlv5_counter++;
1224                 }
1225                 break;
1226             case CL_OPTION_TIME_OFFSET :
1227                 opt_len = tlv_len;
1228                 proto_item_append_text(ti, "%d", tvb_get_ntohl(tvb, sub_off));
1229                 break;
1230             case CL_OPTION_IP_PREF :
1231                 opt_len = tlv_len;
1232                 field_value = tvb_get_guint8(tvb, sub_off);
1233                 if (field_value == 1) {
1234                     proto_item_append_text(ti, "%s", "IPv4");
1235                 } else if (field_value == 2) {
1236                     proto_item_append_text(ti, "%s", "IPv6");
1237                 } else if (field_value == 6) {
1238                     proto_item_append_text(ti, "%s", "Dual Stack");
1239                 } else {
1240                     proto_item_append_text(ti, "%s%d", "Invalid IP Preference value ", field_value);
1241                 }
1242                 break;
1243             case CL_OPTION_DOCS_CMTS_CAP :
1244                 opt_len = tlv_len;
1245                 field_len = 0;
1246                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1247
1248                 /* tlv_len contains the total length of all the TLVs for this
1249                    option */
1250                 if (tlv_len > 0) {
1251                     for (i = 0; field_len < opt_len; i++) {
1252                         int tagLen = 0;
1253                         int tag = 0;
1254                         tag = tvb_get_guint8(tvb, sub_off);
1255                         sub_off++;
1256                         tagLen = tvb_get_guint8(tvb, sub_off);
1257                         sub_off++;
1258                         if (tag == CL_OPTION_DOCS_CMTS_TLV_VERS_NUM &&
1259                             tagLen == 2) {
1260                             int major = 0;
1261                             int minor = 0;
1262                             major = tvb_get_guint8(tvb, sub_off);
1263                             sub_off++;
1264                             minor = tvb_get_guint8(tvb, sub_off);
1265                             sub_off++;
1266                             proto_tree_add_text(subtree, tvb, sub_off-2,
1267                                 2, "DOCSIS Version Number %d.%d",
1268                                                 major, minor);
1269                         }
1270                         else
1271                             sub_off += tagLen;
1272
1273                         field_len += tagLen + 2;
1274                     }
1275                 }
1276                 else
1277                     proto_tree_add_text(subtree, tvb, sub_off, 0, "empty");
1278                 break;
1279             case CL_CM_MAC_ADDR :
1280                 opt_len = tlv_len;
1281                 if (tlv_len != 6) {
1282                     expert_add_info_format(pinfo, ti, &ei_dhcpv6_bogus_length, "Bogus length: %d", tlv_len);
1283                 }
1284                 else {
1285                     /*proto_item_append_text(ti, "CM MAC Address Option = %s", */
1286                     proto_item_append_text(ti, "%s", tvb_bytes_to_str_punct(tvb, sub_off, opt_len, ':'));
1287                     /* tvb_bytes_to_str(tvb, sub_off, opt_len)); */
1288                 }
1289                 break;
1290             case CL_EROUTER_CONTAINER_OPTION :
1291                 opt_len = tlv_len;
1292                 proto_item_append_text(ti, " %s (len=%d)",
1293                                        tvb_bytes_to_str(tvb, sub_off, opt_len), tlv_len);
1294                 break;
1295             case CL_OPTION_CCC :
1296                 opt_len = tlv_len;
1297                 field_len = 0;
1298                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1299                 proto_item_append_text(ti, " (%d bytes)", opt_len);
1300                 while (field_len < opt_len) {
1301                     sub_value = dissect_packetcable_ccc_option(subtree, ti, pinfo, tvb,
1302                                                                sub_off, (opt_len - field_len));
1303                     sub_off += sub_value;
1304                     field_len += sub_value;
1305                 }
1306                 break;
1307             case CL_OPTION_CCCV6 :
1308                 opt_len = tlv_len;
1309                 field_len = 0;
1310                 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
1311                 proto_item_append_text(ti, " (%d bytes)", opt_len);
1312                 while (field_len < opt_len) {
1313                     sub_value = dissect_packetcable_cccV6_option(subtree, ti, pinfo, tvb,
1314                         sub_off, (opt_len - field_len));
1315                     sub_off += sub_value;
1316                     field_len += sub_value;
1317                 }
1318                 break;
1319             case CL_OPTION_CORRELATION_ID :
1320                 opt_len = tlv_len;
1321                  if (tlv_len != 4) {
1322                     proto_item_append_text(ti, "Bogus value length=%d",
1323                                            tlv_len);
1324                 }
1325                 else {
1326                     proto_item_append_text(ti, "%u", tvb_get_ntohl(tvb, sub_off));
1327                 }
1328                 break;
1329             default:
1330                 opt_len = tlv_len;
1331                 break;
1332             }
1333             off += (opt_len + 4);
1334
1335         }
1336     }
1337     else {
1338         expert_add_info_format(pinfo, v_item, &ei_dhcpv6_bogus_length, "Bogus length: %d", len);
1339     }
1340 }
1341
1342 /* Adds domain */
1343 static void
1344 dhcpv6_domain(proto_tree * subtree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int offset, guint16 optlen)
1345 {
1346     int start_offset=offset;
1347     char domain[256];
1348     int pos;
1349     guint8 len;
1350
1351     pos=0;
1352     while(optlen){
1353         /* this is the start of the domain name */
1354         if(!pos){
1355             start_offset=offset;
1356         }
1357         domain[pos]=0;
1358
1359         /* read length of the next substring */
1360         len = tvb_get_guint8(tvb, offset);
1361         /* Microsoft dhcpv6 clients aren't currently RFC 4704 conformant: They send an
1362          * ASCII string instead of a DNS record encoded domain name. Catch that case
1363          * to allow us to continue after such a malformed record.
1364          */
1365         if ( optlen < len ) {
1366             expert_add_info(pinfo, v_item, &ei_dhcpv6_malformed_dns);
1367             return;
1368         }
1369         offset++;
1370         optlen--;
1371         /* if len==0 and pos>0 we have read an entire domain string */
1372         if(!len){
1373             if(!pos){
1374                 /* empty string, this must be an error? */
1375                 expert_add_info(pinfo, v_item, &ei_dhcpv6_malformed_option);
1376                 return;
1377             } else {
1378                 proto_tree_add_string(subtree, hf_dhcpv6_domain, tvb, start_offset, offset-start_offset, domain);
1379                 pos=0;
1380                 continue;
1381             }
1382         }
1383
1384         /* add the substring to domain */
1385         if(pos){
1386             domain[pos]='.';
1387             pos++;
1388         }
1389         if(pos+len>254){
1390             /* too long string, this must be an error? */
1391             expert_add_info(pinfo, v_item, &ei_dhcpv6_malformed_option);
1392             return;
1393         }
1394         tvb_memcpy(tvb, domain+pos, offset, len);
1395         pos+=len;
1396         offset+=len;
1397         optlen-=len;
1398     }
1399
1400     if(pos){
1401         domain[pos]=0;
1402         proto_tree_add_string(subtree, hf_dhcpv6_domain, tvb, start_offset, offset-start_offset, domain);
1403     }
1404 }
1405
1406 /* Returns the number of bytes consumed by this option. */
1407 static int
1408 dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree,
1409               gboolean downstream, int off, int eoff, gboolean *at_end, int protocol)
1410 {
1411     guint16     opttype, hwtype, subopt_type;
1412     int     temp_optlen = 0, optlen, subopt_len; /* 16-bit values that need 16-bit rollover protection */
1413     proto_item *ti = NULL, *option_item;
1414     proto_tree *subtree;
1415     proto_tree *subtree_2;
1416     int i;
1417     guint16 duidtype;
1418     guint32 enterprise_no;
1419
1420     /* option type and length must be present */
1421     if (eoff - off < 4) {
1422         *at_end = TRUE;
1423         return 0;
1424     }
1425
1426     opttype = tvb_get_ntohs(tvb, off);
1427     optlen = tvb_get_ntohs(tvb, off + 2);
1428
1429     /* all option data must be present */
1430     if (eoff - off < 4 + optlen) {
1431         *at_end = TRUE;
1432         return 0;
1433     }
1434
1435     option_item = proto_tree_add_text(bp_tree, tvb, off, 4 + optlen,
1436                              "%s", val_to_str(opttype, opttype_vals, "DHCP option %u"));
1437
1438     subtree = proto_item_add_subtree(option_item, ett_dhcpv6_option);
1439     proto_tree_add_item(subtree, hf_option_type, tvb, off, 2, ENC_BIG_ENDIAN);
1440     proto_tree_add_item(subtree, hf_option_length, tvb, off + 2, 2, ENC_BIG_ENDIAN);
1441     off += 4;
1442     /* Right now, none of the options can be filtered at, so provide a hex
1443        array for minimalistic filtering */
1444     if (optlen)
1445         proto_tree_add_item(subtree, hf_option_value, tvb, off, optlen, ENC_NA);
1446
1447     switch (opttype) {
1448     case OPTION_CLIENTID:
1449         col_append_fstr(pinfo->cinfo, COL_INFO, "CID: %s ", tvb_bytes_to_str(tvb, off, optlen));
1450         /* Fall through */
1451     case OPTION_SERVERID:
1452     case OPTION_RELAYID:
1453         if (optlen < 2) {
1454             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1455             break;
1456         }
1457         proto_tree_add_item(subtree, hf_duid_bytes, tvb, off, optlen, ENC_NA);
1458         duidtype = tvb_get_ntohs(tvb, off);
1459         proto_tree_add_item(subtree, hf_duid_type, tvb, off, 2, ENC_BIG_ENDIAN);
1460         switch (duidtype) {
1461         case DUID_LLT:
1462         {
1463             nstime_t llt_time;
1464
1465             if (optlen < 8) {
1466                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1467                 break;
1468             }
1469             proto_tree_add_item(subtree, hf_duidllt_hwtype, tvb, off + 2, 2, ENC_BIG_ENDIAN);
1470
1471             /* Packet specifies seconds since Jan 1 2000, so add 946684800U (30 years) to get back to epoch */
1472             llt_time.secs = tvb_get_ntohl(tvb, off + 4)+946684800U;
1473             llt_time.nsecs = 0;
1474
1475             proto_tree_add_time(subtree, hf_duidllt_time, tvb, off + 4, 4, &llt_time);
1476             if (optlen > 8) {
1477                 hwtype=tvb_get_ntohs(tvb, off + 2);
1478                 proto_tree_add_string(subtree, hf_duidllt_link_layer_addr, tvb, off + 8,
1479                                     optlen - 8, tvb_arphrdaddr_to_str(tvb, off+8, optlen-8, hwtype));
1480             }
1481         }
1482         break;
1483         case DUID_EN:
1484             if (optlen < 6) {
1485                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1486                 break;
1487             }
1488             proto_tree_add_item(subtree, hf_duiden_enterprise, tvb, off + 2, 4, ENC_BIG_ENDIAN);
1489             if (optlen > 6) {
1490                 proto_tree_add_item(subtree, hf_duiden_identifier, tvb, off + 6, optlen - 6, ENC_NA);
1491             }
1492             break;
1493         case DUID_LL:
1494         case DUID_LL_OLD:
1495             if (optlen < 4) {
1496                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1497                 break;
1498             }
1499             proto_tree_add_item(subtree, hf_duidll_hwtype, tvb, off + 2, 2, ENC_BIG_ENDIAN);
1500             if (optlen > 4) {
1501                 hwtype=tvb_get_ntohs(tvb, off + 2);
1502                 proto_tree_add_string(subtree, hf_duidll_link_layer_addr, tvb, off + 4,
1503                                     optlen - 4, tvb_arphrdaddr_to_str(tvb, off+4, optlen-4, hwtype));
1504             }
1505             break;
1506         }
1507         break;
1508     case OPTION_NTP_SERVER:
1509         if (optlen < 4) {
1510             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NTP Server: malformed option");
1511             break;
1512         }
1513         while (optlen > temp_optlen) {
1514             subopt_type = tvb_get_ntohs(tvb, off+temp_optlen);
1515             subopt_len = tvb_get_ntohs(tvb, off+2+temp_optlen);
1516             ti = proto_tree_add_text(subtree, tvb, off+temp_optlen, 4 + subopt_len,
1517                              "%s", val_to_str(opttype, ntp_server_opttype_vals, "NTP Server suboption %u"));
1518             subtree_2 = proto_item_add_subtree(option_item, ett_dhcpv6_netserver_option);
1519             proto_tree_add_item(subtree_2, hf_option_ntpserver_type, tvb, off + temp_optlen, 2, ENC_BIG_ENDIAN);
1520             proto_tree_add_item(subtree_2, hf_option_ntpserver_length, tvb, off + 2 + temp_optlen, 2, ENC_BIG_ENDIAN);
1521             temp_optlen += 4;
1522             switch(subopt_type) {
1523             case NTP_SUBOPTION_SRV_ADDR:
1524                 proto_tree_add_item(subtree_2, hf_option_ntpserver_addr, tvb, off + temp_optlen, 16, ENC_NA);
1525                 break;
1526             case NTP_SUBOPTION_MC_ADDR:
1527                 proto_tree_add_item(subtree_2, hf_option_ntpserver_mc_addr, tvb, off + temp_optlen, 16, ENC_NA);
1528                 break;
1529             case NTP_SUBOPTION_SRV_FQDN:
1530                 dhcpv6_domain(subtree_2, ti, pinfo, tvb, off + temp_optlen, subopt_len);
1531                 break;
1532             }
1533
1534             temp_optlen += subopt_len;
1535         }
1536         break;
1537     case OPTION_IA_NA:
1538     case OPTION_IA_PD:
1539         if (optlen < 12) {
1540             if (opttype == OPTION_IA_NA)
1541                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_NA: malformed option");
1542             else
1543                 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_PD: malformed option");
1544             break;
1545         }
1546         proto_tree_add_string(subtree, hf_iaid, tvb, off,
1547                                     4, tvb_arphrdaddr_to_str(tvb, off, 4, opttype));
1548         if (tvb_get_ntohl(tvb, off+4) == DHCPV6_LEASEDURATION_INFINITY) {
1549             proto_tree_add_uint_format_value(subtree, hf_iaid_t1, tvb, off+4,
1550                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
1551         } else {
1552             proto_tree_add_item(subtree, hf_iaid_t1, tvb, off+4,
1553                                     4, ENC_BIG_ENDIAN);
1554         }
1555
1556         if (tvb_get_ntohl(tvb, off+8) == DHCPV6_LEASEDURATION_INFINITY) {
1557             proto_tree_add_uint_format_value(subtree, hf_iaid_t2, tvb, off+8,
1558                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
1559         } else {
1560             proto_tree_add_item(subtree, hf_iaid_t2, tvb, off+8,
1561                                     4, ENC_BIG_ENDIAN);
1562         }
1563
1564         temp_optlen = 12;
1565         while ((optlen - temp_optlen) > 0) {
1566             temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1567                                          off+temp_optlen, off + optlen, at_end, protocol);
1568             if (*at_end) {
1569                 /* Bad option - just skip to the end */
1570                 temp_optlen = optlen;
1571             }
1572         }
1573         break;
1574     case OPTION_IA_TA:
1575         if (optlen < 4) {
1576             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_TA: malformed option");
1577             break;
1578         }
1579         proto_tree_add_string(subtree, hf_iata, tvb, off,
1580                                     4, tvb_arphrdaddr_to_str(tvb, off, 4, opttype));
1581         temp_optlen = 4;
1582         while ((optlen - temp_optlen) > 0) {
1583             temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1584                                          off+temp_optlen, off + optlen, at_end, protocol);
1585             if (*at_end) {
1586                 /* Bad option - just skip to the end */
1587                 temp_optlen = optlen;
1588             }
1589         }
1590         break;
1591     case OPTION_IAADDR:
1592     {
1593         guint32 preferred_lifetime, valid_lifetime;
1594
1595         if (optlen < 24) {
1596             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_TA: malformed option");
1597             break;
1598         }
1599
1600         proto_tree_add_item(subtree, hf_iaaddr_ip, tvb, off, 16, ENC_NA);
1601         col_append_fstr(pinfo->cinfo, COL_INFO, "IAA: %s ", tvb_ip6_to_str(tvb, off));
1602
1603         preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
1604         valid_lifetime = tvb_get_ntohl(tvb, off + 20);
1605
1606         if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1607             proto_tree_add_uint_format_value(subtree, hf_iaaddr_pref_lifetime, tvb, off+16,
1608                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
1609         } else {
1610             proto_tree_add_item(subtree, hf_iaaddr_pref_lifetime, tvb, off+16,
1611                                     4, ENC_BIG_ENDIAN);
1612         }
1613         if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1614             proto_tree_add_uint_format(subtree, hf_iaaddr_valid_lifetime, tvb, off+20,
1615                                     4, DHCPV6_LEASEDURATION_INFINITY, "Preferred lifetime: infinity");
1616         } else {
1617             proto_tree_add_item(subtree, hf_iaaddr_valid_lifetime, tvb, off+20,
1618                                     4, ENC_BIG_ENDIAN);
1619         }
1620
1621         temp_optlen = 24;
1622         while ((optlen - temp_optlen) > 0) {
1623             temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1624                                          off+temp_optlen, off + optlen, at_end, protocol);
1625             if (*at_end) {
1626                 /* Bad option - just skip to the end */
1627                 temp_optlen = optlen;
1628             }
1629         }
1630     }
1631     break;
1632     case OPTION_ORO:
1633     case OPTION_ERO:
1634         for (i = 0; i < optlen; i += 2) {
1635             proto_tree_add_item(subtree, hf_requested_option_code, tvb, off+i,
1636                                     2, ENC_BIG_ENDIAN);
1637         }
1638         break;
1639     case OPTION_PREFERENCE:
1640         if (optlen != 1) {
1641             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "PREFERENCE: malformed option");
1642             break;
1643         }
1644         proto_tree_add_item(subtree, hf_option_preference, tvb, off, 1, ENC_BIG_ENDIAN);
1645         break;
1646     case OPTION_ELAPSED_TIME:
1647         if (optlen != 2) {
1648             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "ELAPSED-TIME: malformed option");
1649             break;
1650         }
1651
1652         temp_optlen = tvb_get_ntohs(tvb, off);
1653         proto_tree_add_uint_format_value(subtree, hf_elapsed_time, tvb, off,
1654                                     2, temp_optlen*10, "%u ms", temp_optlen*10);
1655         break;
1656     case OPTION_RELAY_MSG:
1657         if (optlen == 0) {
1658             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RELAY-MSG: malformed option");
1659         } else {
1660             /* here, we should dissect a full DHCP message */
1661             dissect_dhcpv6(tvb, pinfo, subtree, downstream, off, off + optlen);
1662         }
1663         break;
1664     case OPTION_AUTH:
1665         if (optlen < 11) {
1666             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "AUTH: malformed option");
1667             break;
1668         }
1669
1670         proto_tree_add_item(subtree, hf_auth_protocol, tvb, off, 1, ENC_BIG_ENDIAN);
1671         proto_tree_add_item(subtree, hf_auth_algorithm, tvb, off+1, 1, ENC_BIG_ENDIAN);
1672         proto_tree_add_item(subtree, hf_auth_rdm, tvb, off+2, 1, ENC_BIG_ENDIAN);
1673         proto_tree_add_item(subtree, hf_auth_replay_detection, tvb, off+3, 8, ENC_NA);
1674         if (optlen != 11)
1675             proto_tree_add_item(subtree, hf_auth_info, tvb, off+11, optlen-11, ENC_NA);
1676         break;
1677     case OPTION_UNICAST:
1678         if (optlen != 16) {
1679             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "UNICAST: malformed option");
1680             break;
1681         }
1682         proto_tree_add_item(subtree, hf_opt_unicast, tvb, off, 16, ENC_NA);
1683         break;
1684     case OPTION_STATUS_CODE:
1685         proto_tree_add_item(subtree, hf_opt_status_code, tvb, off, 2, ENC_BIG_ENDIAN);
1686         if (optlen > 2)
1687             proto_tree_add_item(subtree, hf_opt_status_msg, tvb, off+2, optlen - 2, ENC_ASCII|ENC_NA);
1688         break;
1689     case OPTION_VENDOR_CLASS:
1690         if (optlen < 4) {
1691             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "VENDOR_CLASS: malformed option");
1692             break;
1693         }
1694         proto_tree_add_item(subtree, hf_vendorclass_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
1695         if (optlen > 4)
1696             proto_tree_add_item(subtree, hf_vendorclass_data, tvb, off+6, optlen-6, ENC_ASCII|ENC_NA);
1697         break;
1698     case OPTION_VENDOR_OPTS:
1699         if (optlen < 4) {
1700             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "VENDOR_OPTS: malformed option");
1701             break;
1702         }
1703
1704         enterprise_no = tvb_get_ntohl(tvb, off);
1705         ti = proto_tree_add_item(subtree, hf_vendoropts_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
1706
1707         if (optlen >= 4) {
1708             if (enterprise_no == 4491) {
1709                 dissect_cablelabs_specific_opts(subtree, ti, pinfo, tvb, off+4, optlen-4);
1710             } else {
1711                 int optoffset = 0;
1712
1713                 while((optlen - 4 - optoffset) > 0)  {
1714                     int olen = tvb_get_ntohs(tvb, off + optoffset + 6);
1715                     ti = proto_tree_add_text(subtree, tvb, off + optoffset + 4,
1716                                              4 + olen, "option");
1717                     subtree_2 = proto_item_add_subtree(ti, ett_dhcpv6_option_vsoption);
1718                     proto_tree_add_item(subtree_2, hf_vendoropts_enterprise_option_code, tvb, off + optoffset + 4, 2, ENC_BIG_ENDIAN);
1719                     proto_tree_add_item(subtree_2, hf_vendoropts_enterprise_option_length, tvb, off + optoffset + 6, 2, ENC_BIG_ENDIAN);
1720                     proto_tree_add_item(subtree_2, hf_vendoropts_enterprise_option_data, tvb, off + optoffset + 8, olen, ENC_NA);
1721                     optoffset += (4 + olen);
1722                 }
1723             }
1724         }
1725         break;
1726     case OPTION_INTERFACE_ID:
1727     {
1728         gint namelen;
1729
1730         if (optlen == 0) {
1731             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "INTERFACE_ID: malformed option");
1732             break;
1733         }
1734
1735         namelen = tvb_strnlen(tvb, off, optlen)+1;
1736         if (namelen == 0) {
1737             proto_tree_add_item(subtree, hf_interface_id, tvb, off, optlen, ENC_ASCII|ENC_NA);
1738         } else {
1739             proto_tree_add_item(subtree, hf_interface_id, tvb, off, namelen-1, ENC_ASCII|ENC_NA);
1740
1741             temp_optlen = optlen - namelen;
1742             off += namelen;
1743             if (temp_optlen >= 6)
1744                 proto_tree_add_string(subtree, hf_interface_id_link_address, tvb, off, temp_optlen, tvb_arphrdaddr_to_str(tvb, off, 6, ARPHRD_ETHER));
1745         }
1746     }
1747     break;
1748     case OPTION_RECONF_MSG:
1749         if (optlen != 1) {
1750             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RECONF_MSG: malformed option");
1751             break;
1752         }
1753
1754         proto_tree_add_item(subtree, hf_reconf_msg, tvb, off, 1, ENC_BIG_ENDIAN);
1755         break;
1756     case OPTION_RECONF_ACCEPT:
1757         if (optlen)
1758             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RECONF_ACCEPT: malformed option");
1759         break;
1760     case OPTION_SIP_SERVER_D:
1761         if (optlen > 0) {
1762             ti = proto_tree_add_text(subtree, tvb, off, optlen, "SIP Servers Domain Search List");
1763             dhcpv6_domain(subtree, ti, pinfo, tvb, off, optlen);
1764         }
1765         break;
1766     case OPTION_SIP_SERVER_A:
1767         if (optlen % 16) {
1768             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "SIP servers address: malformed option");
1769             break;
1770         }
1771
1772         for (i = 0; i < optlen; i += 16)
1773             proto_tree_add_item(subtree, hf_sip_server_a, tvb, off + i, 16, ENC_NA);
1774         break;
1775     case OPTION_DNS_SERVERS:
1776         if (optlen % 16) {
1777             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DNS servers address: malformed option");
1778             break;
1779         }
1780
1781         for (i = 0; i < optlen; i += 16) {
1782             ti = proto_tree_add_item(subtree, hf_dns_servers, tvb, off + i, 16, ENC_NA);
1783             proto_item_prepend_text(ti, " %d ", i/16 + 1);
1784         }
1785         break;
1786     case OPTION_DOMAIN_LIST:
1787         if (optlen > 0) {
1788             ti = proto_tree_add_text(subtree, tvb, off, optlen, "DNS Domain Search List");
1789             dhcpv6_domain(subtree, ti, pinfo, tvb, off, optlen);
1790         }
1791         break;
1792     case OPTION_NIS_SERVERS:
1793         if (optlen % 16) {
1794             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NIS servers address: malformed option");
1795             break;
1796         }
1797         for (i = 0; i < optlen; i += 16)
1798             proto_tree_add_item(subtree, hf_nis_servers, tvb, off + i, 16, ENC_NA);
1799         break;
1800     case OPTION_NISP_SERVERS:
1801         if (optlen % 16) {
1802             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NISP servers address: malformed option");
1803             break;
1804         }
1805         for (i = 0; i < optlen; i += 16)
1806             proto_tree_add_item(subtree, hf_nisp_servers, tvb, off + i, 16, ENC_NA);
1807         break;
1808     case OPTION_NIS_DOMAIN_NAME:
1809         if (optlen > 0) {
1810             ti = proto_tree_add_text(subtree, tvb, off, optlen, "nis-domain-name");
1811             dhcpv6_domain(subtree, ti, pinfo, tvb, off, optlen);
1812         }
1813         break;
1814     case OPTION_NISP_DOMAIN_NAME:
1815         if (optlen > 0) {
1816             ti = proto_tree_add_text(subtree, tvb, off, optlen, "nisp-domain-name");
1817             dhcpv6_domain(subtree, ti, pinfo, tvb, off, optlen);
1818         }
1819         break;
1820     case OPTION_SNTP_SERVERS:
1821         if (optlen % 16) {
1822             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "SNTP servers address: malformed option");
1823             break;
1824         }
1825         for (i = 0; i < optlen; i += 16)
1826             ti = proto_tree_add_item(subtree, hf_sntp_servers, tvb, off + i, 16, ENC_NA);
1827             proto_item_prepend_text(ti, " %d ", i/16 + 1);
1828         break;
1829     case OPTION_LIFETIME:
1830         if (optlen != 4) {
1831             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LIFETIME: malformed option");
1832             break;
1833         }
1834         proto_tree_add_item(subtree, hf_opt_lifetime, tvb, off, 4, ENC_BIG_ENDIAN);
1835         break;
1836     case OPTION_BCMCS_SERVER_D:
1837         if (optlen > 0) {
1838             ti = proto_tree_add_text(subtree, tvb, off, optlen, "BCMCS Servers Domain Search List");
1839             dhcpv6_domain(subtree, ti, pinfo, tvb, off, optlen);
1840         }
1841         break;
1842     case OPTION_BCMCS_SERVER_A:
1843         if (optlen % 16) {
1844             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "BCMCS servers address: malformed option");
1845             break;
1846         }
1847         for (i = 0; i < optlen; i += 16)
1848             proto_tree_add_item(subtree, hf_bcmcs_servers_a, tvb, off + i, 16, ENC_NA);
1849         break;
1850     case OPTION_REMOTE_ID:
1851         if (optlen < 4) {
1852             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "REMOTE_ID: malformed option");
1853             break;
1854         }
1855         proto_tree_add_item(subtree, hf_remoteid_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
1856         off += 4;
1857         proto_tree_add_item(subtree, hf_remoteid_enterprise_id, tvb, off, optlen - 4, ENC_ASCII|ENC_NA);
1858         break;
1859     case OPTION_SUBSCRIBER_ID:
1860         if (optlen == 0) {
1861             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "SUBSCRIBER_ID: malformed option");
1862             break;
1863         }
1864         proto_tree_add_item(subtree, hf_subscriber_id, tvb, off, optlen, ENC_ASCII|ENC_NA);
1865         break;
1866     case OPTION_CLIENT_FQDN:
1867         if (optlen < 1) {
1868             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "FQDN: malformed option");
1869         } else {
1870             /*
1871              * +-----+-+-+-+
1872              * | MBZ |N|O|S|
1873              * +-----+-+-+-+
1874              */
1875             proto_tree_add_item(subtree, hf_clientfqdn_reserved, tvb, off, 1, ENC_BIG_ENDIAN);
1876             proto_tree_add_item(subtree, hf_clientfqdn_n, tvb, off, 1, ENC_BIG_ENDIAN);
1877             proto_tree_add_item(subtree, hf_clientfqdn_o, tvb, off, 1, ENC_BIG_ENDIAN);
1878             proto_tree_add_item(subtree, hf_clientfqdn_s, tvb, off, 1, ENC_BIG_ENDIAN);
1879
1880             dhcpv6_domain(subtree, option_item, pinfo, tvb, off+1, optlen-1);
1881         }
1882         break;
1883     case OPTION_PANA_AGENT:
1884         if (optlen % 16) {
1885             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "PANA agent address: malformed option");
1886             break;
1887         }
1888         for (i = 0; i < optlen; i += 16)
1889             proto_tree_add_item(subtree, hf_pana_agent, tvb, off + i, 16, ENC_NA);
1890         break;
1891     case OPTION_TIME_ZONE:
1892         if (optlen > 0)
1893             proto_tree_add_item(subtree, hf_opt_timezone, tvb, off, optlen, ENC_ASCII|ENC_NA);
1894         break;
1895     case OPTION_TZDB:
1896         if (optlen > 0)
1897             proto_tree_add_item(subtree, hf_opt_tzdb, tvb, off, optlen, ENC_ASCII|ENC_NA);
1898         break;
1899     case OPTION_LQ_QUERY:
1900     {
1901         guint8 query_type;
1902         if (optlen < 17) {
1903             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LQ-QUERY: malformed option");
1904             break;
1905         }
1906         query_type = tvb_get_guint8(tvb, off);
1907         ti = proto_tree_add_item(subtree, hf_lq_query, tvb, off, 1, ENC_BIG_ENDIAN);
1908         if ((protocol == proto_dhcpv6) &&
1909             ((query_type == LQ_QUERY_RELAYID) ||
1910              (query_type == LQ_QUERY_LINK_ADDRESS) ||
1911              (query_type == LQ_QUERY_REMOTEID))) {
1912             expert_add_info(pinfo, ti, &ei_dhcpv6_bulk_leasequery_bad_query_type);
1913         }
1914
1915         proto_tree_add_item(subtree, hf_lq_query_link_address, tvb, off+1, 16, ENC_NA);
1916         temp_optlen = 17;
1917         while ((optlen - temp_optlen) > 0) {
1918             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
1919                                          downstream, off + temp_optlen,
1920                                          off + optlen, at_end, protocol);
1921             if (*at_end) {
1922                 /* Bad option - just skip to the end */
1923                 temp_optlen = optlen;
1924             }
1925         }
1926     }
1927     break;
1928     case OPTION_CLIENT_DATA:
1929         temp_optlen = 0;
1930         while ((optlen - temp_optlen) > 0) {
1931             temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
1932                                          downstream, off + temp_optlen,
1933                                          off + optlen, at_end, protocol);
1934             if (*at_end) {
1935                 /* Bad option - just skip to the end */
1936                 temp_optlen = optlen;
1937             }
1938         }
1939         break;
1940     case OPTION_CLT_TIME:
1941         if (optlen != 4) {
1942             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "CLT_TIME: malformed option");
1943             break;
1944         }
1945
1946         proto_tree_add_item(subtree, hf_clt_time, tvb, off, 4, ENC_BIG_ENDIAN);
1947         break;
1948     case OPTION_LQ_RELAY_DATA:
1949         if (optlen < 16) {
1950             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LQ_RELAY_DATA: malformed option");
1951             break;
1952         }
1953
1954         if (protocol == proto_dhcpv6_bulk_leasequery) {
1955             expert_add_info(pinfo, option_item, &ei_dhcpv6_bulk_leasequery_no_lq_relay_data);
1956         }
1957
1958         proto_tree_add_item(subtree, hf_lq_relay_data_peer_addr, tvb, off, 16, ENC_NA);
1959         proto_tree_add_item(subtree, hf_lq_relay_data_msg, tvb, off+16, optlen - 16, ENC_ASCII|ENC_NA);
1960         break;
1961     case OPTION_LQ_CLIENT_LINK:
1962         if (optlen % 16) {
1963             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "LQ client links address: malformed option");
1964             break;
1965         }
1966         for (i = 0; i < optlen; i += 16)
1967             proto_tree_add_item(subtree, hf_lq_client_link, tvb, off + i, 16, ENC_NA);
1968         break;
1969     case OPTION_CAPWAP_AC_V6:
1970         if (optlen % 16) {
1971             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "CAPWAP Access Controllers address: malformed option");
1972             break;
1973         }
1974         for (i = 0; i < optlen; i += 16)
1975             proto_tree_add_item(subtree, hf_capwap_ac_v6, tvb, off + i, 16, ENC_NA);
1976         break;
1977     case OPTION_AFTR_NAME:
1978     {
1979         const guchar *dns_name;
1980         get_dns_name(tvb, off, optlen, off, &dns_name);
1981         proto_tree_add_string(subtree, hf_aftr_name, tvb, off, optlen, dns_name);
1982         break;
1983     }
1984     case OPTION_IAPREFIX:
1985         if (optlen < 25) {
1986             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IAPREFIX: malformed option");
1987             break;
1988         }
1989
1990         if (tvb_get_ntohl(tvb, off) == DHCPV6_LEASEDURATION_INFINITY) {
1991             proto_tree_add_uint_format_value(subtree, hf_iaprefix_pref_lifetime, tvb, off,
1992                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
1993         } else {
1994             proto_tree_add_item(subtree, hf_iaprefix_pref_lifetime, tvb, off,
1995                                     4, ENC_BIG_ENDIAN);
1996         }
1997         if (tvb_get_ntohl(tvb, off + 4) == DHCPV6_LEASEDURATION_INFINITY) {
1998             proto_tree_add_uint_format_value(subtree, hf_iaprefix_valid_lifetime, tvb, off+4,
1999                                     4, DHCPV6_LEASEDURATION_INFINITY, "infinity");
2000         } else {
2001             proto_tree_add_item(subtree, hf_iaprefix_valid_lifetime, tvb, off+4,
2002                                     4, ENC_BIG_ENDIAN);
2003         }
2004         proto_tree_add_item(subtree, hf_iaprefix_pref_len, tvb, off+8, 1, ENC_BIG_ENDIAN);
2005         proto_tree_add_item(subtree, hf_iaprefix_pref_addr, tvb, off+9, 16, ENC_NA);
2006         temp_optlen = 25;
2007         while ((optlen - temp_optlen) > 0) {
2008             temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
2009                                          off+temp_optlen, off + optlen, at_end, protocol);
2010             if (*at_end) {
2011                 /* Bad option - just skip to the end */
2012                 temp_optlen = optlen;
2013             }
2014         }
2015         break;
2016     case OPTION_MIP6_HA:
2017         if (optlen != 16) {
2018             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "MIP6_HA: malformed option");
2019             break;
2020         }
2021         proto_tree_add_item(subtree, hf_mip6_ha, tvb, off, 16, ENC_NA);
2022         break;
2023     case OPTION_MIP6_HOA:
2024         if (optlen != 16) {
2025             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "MIP6_HOA: malformed option");
2026             break;
2027         }
2028
2029         proto_tree_add_item(subtree, hf_mip6_hoa, tvb, off, 16, ENC_NA);
2030         break;
2031     case OPTION_NAI:
2032         if (optlen < 4) {
2033             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "NAI: malformed option");
2034             break;
2035         }
2036         proto_tree_add_item(subtree, hf_nai, tvb, off, optlen - 2, ENC_ASCII|ENC_NA);
2037         break;
2038     case OPTION_PD_EXCLUDE:
2039         if ((optlen < 2) || (optlen > 17)) {
2040             expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "PD_EXCLUDE: malformed option");
2041             break;
2042         }
2043         proto_tree_add_item(subtree, hf_pd_exclude_pref_len, tvb, off, 1, ENC_BIG_ENDIAN);
2044         proto_tree_add_item(subtree, hf_pd_exclude_subnet_id , tvb, off+1, optlen-1, ENC_NA);
2045         break;
2046     }
2047
2048     return 4 + optlen;
2049 }
2050
2051
2052 static void
2053 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2054                gboolean downstream, int off, int eoff)
2055 {
2056     proto_tree *bp_tree = NULL;
2057     proto_item *ti;
2058     guint8 msgtype;
2059     gboolean at_end;
2060     struct e_in6_addr in6;
2061
2062     msgtype = tvb_get_guint8(tvb, off);
2063
2064     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msgtype, msgtype_vals, "Message Type %u"));
2065
2066     if (tree) {
2067         ti = proto_tree_add_item(tree, proto_dhcpv6, tvb, off, eoff - off, ENC_NA);
2068         bp_tree = proto_item_add_subtree(ti, ett_dhcpv6);
2069     }
2070
2071
2072     if (msgtype == RELAY_FORW || msgtype == RELAY_REPLY) {
2073         if (tree) {
2074             proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, ENC_BIG_ENDIAN);
2075             proto_tree_add_item(bp_tree, hf_dhcpv6_hopcount, tvb, off + 1, 1, ENC_BIG_ENDIAN);
2076             proto_tree_add_item(bp_tree, hf_dhcpv6_linkaddr, tvb, off + 2, 16, ENC_NA);
2077             tvb_get_ipv6(tvb, off + 2, &in6);
2078             col_append_fstr(pinfo->cinfo, COL_INFO, "L: %s ", ip6_to_str(&in6));
2079             proto_tree_add_item(bp_tree, hf_dhcpv6_peeraddr, tvb, off + 18, 16, ENC_NA);
2080         }
2081         off += 34;
2082     } else {
2083         if (tree) {
2084             proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, ENC_BIG_ENDIAN);
2085             proto_tree_add_item(bp_tree, hf_dhcpv6_xid, tvb, off + 1, 3, ENC_BIG_ENDIAN);
2086         }
2087         col_append_fstr(pinfo->cinfo, COL_INFO, "XID: 0x%x ", tvb_get_ntoh24(tvb, off + 1));
2088         off += 4;
2089     }
2090
2091     at_end = FALSE;
2092     while (off < eoff && !at_end)
2093         off += dhcpv6_option(tvb, pinfo, bp_tree, downstream, off, eoff, &at_end, proto_dhcpv6);
2094 }
2095
2096 static void
2097 dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2098 {
2099     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
2100     col_clear(pinfo->cinfo, COL_INFO);
2101     dissect_dhcpv6(tvb, pinfo, tree, TRUE, 0, tvb_reported_length(tvb));
2102 }
2103
2104 static void
2105 dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2106 {
2107     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
2108     col_clear(pinfo->cinfo, COL_INFO);
2109     dissect_dhcpv6(tvb, pinfo, tree, FALSE, 0, tvb_reported_length(tvb));
2110 }
2111
2112
2113 static guint
2114 get_dhcpv6_bulk_leasequery_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
2115 {
2116     return (tvb_get_ntohs(tvb, offset)+2);
2117 }
2118
2119 static void
2120 dissect_dhcpv6_bulk_leasequery_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2121 {
2122     proto_item *ti;
2123     proto_tree *bulk_tree, *option_tree;
2124     gint offset = 0, end;
2125     guint16 size, trans_id;
2126     guint8 msg_type;
2127     gboolean at_end = FALSE;
2128
2129     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6 BulkLease");
2130     col_clear(pinfo->cinfo, COL_INFO);
2131
2132     ti = proto_tree_add_item(tree, proto_dhcpv6_bulk_leasequery, tvb, 0, -1, ENC_NA );
2133     bulk_tree = proto_item_add_subtree(ti, ett_dhcpv6_bulk_leasequery);
2134
2135     size = tvb_get_ntohs(tvb, offset);
2136     proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_size, tvb, offset, 2, ENC_BIG_ENDIAN);
2137     offset += 2;
2138
2139     msg_type = tvb_get_guint8( tvb, offset );
2140     ti = proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_msgtype, tvb, offset, 1, ENC_BIG_ENDIAN);
2141     if ((msg_type != LEASEQUERY) &&
2142         (msg_type != LEASEQUERY_REPLY) &&
2143         (msg_type != LEASEQUERY_DONE) &&
2144         (msg_type != LEASEQUERY_DATA))
2145         expert_add_info_format(pinfo, ti, &ei_dhcpv6_bulk_leasequery_bad_msg_type,
2146             "Message Type %d not allowed by DHCPv6 Bulk Leasequery", msg_type);
2147
2148     offset++;
2149     proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2150     offset++;
2151
2152     trans_id = tvb_get_ntohs(tvb, offset);
2153     proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_trans_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2154     offset += 2;
2155
2156     col_add_fstr(pinfo->cinfo, COL_INFO, "%s, Transaction ID: %5u",
2157                       val_to_str_const(msg_type, msgtype_vals, "Unknown"), trans_id);
2158
2159     ti = proto_tree_add_text(bulk_tree, tvb, offset, -1, "DHCPv6 Options");
2160     option_tree = proto_item_add_subtree(ti, ett_dhcpv6_bulk_leasequery_options);
2161     end = size+2;
2162     while ((offset < end) && !at_end)
2163         offset += dhcpv6_option(tvb, pinfo, option_tree, FALSE, offset,
2164                                 end, &at_end, proto_dhcpv6_bulk_leasequery);
2165 }
2166
2167 static void
2168 dissect_dhcpv6_bulk_leasequery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2169 {
2170     tcp_dissect_pdus(tvb, pinfo, tree, dhcpv6_bulk_leasequery_desegment, 2,
2171                     get_dhcpv6_bulk_leasequery_pdu_len, dissect_dhcpv6_bulk_leasequery_pdu);
2172 }
2173
2174 void
2175 proto_register_dhcpv6(void)
2176 {
2177     module_t *bulkquery_module;
2178
2179     static hf_register_info hf[] = {
2180
2181         /* DHCPv6 header */
2182         { &hf_dhcpv6_msgtype,
2183           { "Message type", "dhcpv6.msgtype", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0x0, NULL, HFILL }},
2184         { &hf_dhcpv6_domain,
2185           { "Domain", "dhcpv6.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2186         { &hf_dhcpv6_hopcount,
2187           { "Hopcount", "dhcpv6.hopcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2188         { &hf_dhcpv6_xid,
2189           { "Transaction ID", "dhcpv6.xid", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL}},
2190         { &hf_dhcpv6_linkaddr,
2191           { "Link address", "dhcpv6.linkaddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
2192         { &hf_dhcpv6_peeraddr,
2193           { "Peer address", "dhcpv6.peeraddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
2194         /* Generic option stuff */
2195         { &hf_option_type,
2196           { "Option", "dhcpv6.option.type", FT_UINT16, BASE_DEC, VALS(opttype_vals), 0x0, NULL, HFILL}},
2197         { &hf_option_length,
2198           { "Length", "dhcpv6.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2199         { &hf_option_value,
2200           { "Value", "dhcpv6.option.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2201         /* Individual options */
2202         { &hf_clientfqdn_reserved,
2203           { "Reserved", "dhcpv6.clientfqdn.reserved", FT_UINT8, BASE_HEX, NULL, 0xF8, NULL, HFILL}},
2204         { &hf_clientfqdn_n,
2205           { "N bit", "dhcpv6.clientfqdn.n", FT_BOOLEAN, 8, TFS(&fqdn_n), 0x4, "Whether the server SHOULD NOT perform any DNS updates", HFILL}},
2206         { &hf_clientfqdn_o,
2207           { "O bit", "dhcpv6.clientfqdn.o", FT_BOOLEAN, 8, TFS(&fqdn_o), 0x2, "Whether the server has overridden the client's preference for the S bit.  Must be 0 when sent from client", HFILL}},
2208         { &hf_clientfqdn_s,
2209           { "S bit", "dhcpv6.clientfqdn.s", FT_BOOLEAN, 8, TFS(&fqdn_s), 0x1, "Whether the server SHOULD or SHOULD NOT perform the AAAA RR (FQDN-to-address) DNS updates", HFILL}},
2210         { &hf_remoteid_enterprise,
2211           { "Enterprise ID", "dhcpv6.remoteid.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING,  &sminmpec_values_ext, 0, "RemoteID Enterprise Number", HFILL }},
2212         { &hf_duid_bytes,
2213           { "DUID", "dhcpv6.duid.bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2214         { &hf_duid_type,
2215           { "DUID Type", "dhcpv6.duid.type", FT_UINT16, BASE_DEC, VALS(duidtype_vals), 0x0, NULL, HFILL}},
2216         { &hf_duidllt_time,
2217           { "DUID Time", "dhcpv6.duidllt.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}},
2218         { &hf_duidllt_link_layer_addr,
2219           { "Link-layer address", "dhcpv6.duidllt.link_layer_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2220         { &hf_duidllt_hwtype,
2221           { "Hardware type", "dhcpv6.duidllt.hwtype", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0, "DUID LLT Hardware Type", HFILL }},
2222         { &hf_duidll_hwtype,
2223           { "Hardware type", "dhcpv6.duidll.hwtype", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0, "DUID LL Hardware Type", HFILL }},
2224         { &hf_duiden_enterprise,
2225           { "Enterprise ID", "dhcpv6.duiden.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING,  &sminmpec_values_ext, 0, "DUID EN Enterprise Number", HFILL }},
2226         { &hf_duiden_identifier,
2227           { "Identifier", "dhcpv6.duiden.identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2228         { &hf_duidll_link_layer_addr,
2229           { "Link-layer address", "dhcpv6.duidll.link_layer_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2230         { &hf_iaid,
2231           { "IAID", "dhcpv6.iaid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2232         { &hf_iaid_t1,
2233           { "T1", "dhcpv6.iaid.t1", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2234         { &hf_iaid_t2,
2235           { "T2", "dhcpv6.iaid.t2", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2236         { &hf_iata,
2237           { "IATA", "dhcpv6.iata", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2238         { &hf_iaaddr_ip,
2239           { "IPv6 address", "dhcpv6.iaaddr.ip", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2240         { &hf_iaaddr_pref_lifetime,
2241           { "Preferred lifetime", "dhcpv6.iaaddr.pref_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2242         { &hf_iaaddr_valid_lifetime,
2243           { "Valid lifetime", "dhcpv6.iaaddr.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2244         { &hf_requested_option_code,
2245           { "Requested Option code", "dhcpv6.requested_option_code", FT_UINT16, BASE_DEC, VALS(opttype_vals), 0, NULL, HFILL }},
2246         { &hf_option_preference,
2247           { "Pref-value", "dhcpv6.option_preference", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2248         { &hf_elapsed_time,
2249           { "Elapsed time", "dhcpv6.elapsed_time", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL}},
2250         { &hf_auth_protocol,
2251           { "Protocol", "dhcpv6.auth.protocol", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2252         { &hf_auth_algorithm,
2253           { "Algorithm", "dhcpv6.auth.algorithm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2254         { &hf_auth_rdm,
2255           { "RDM", "dhcpv6.auth.rdm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2256         { &hf_auth_replay_detection,
2257           { "Replay Detection", "dhcpv6.auth.replay_detection", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2258         { &hf_auth_info,
2259           { "Authentication Information", "dhcpv6.auth.info", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2260         { &hf_opt_unicast,
2261           { "IPv6 address", "dhcpv6.unicast", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2262         { &hf_opt_status_code,
2263           { "Status Code", "dhcpv6.status_code", FT_UINT16, BASE_DEC, VALS(statuscode_vals), 0, NULL, HFILL }},
2264         { &hf_opt_status_msg,
2265           { "Status Message", "dhcpv6.status_msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2266         { &hf_vendorclass_enterprise,
2267           { "Enterprise ID", "dhcpv6.vendorclass.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING,  &sminmpec_values_ext, 0, "Vendor Class Enterprise Number", HFILL }},
2268         { &hf_vendorclass_data,
2269           { "vendor-class-data", "dhcpv6.vendorclass.data", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2270         { &hf_vendoropts_enterprise,
2271           { "Enterprise ID", "dhcpv6.vendoropts.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING,  &sminmpec_values_ext, 0, "Vendor opts Enterprise Number", HFILL }},
2272         { &hf_vendoropts_enterprise_option_code,
2273           { "Option code", "dhcpv6.vendoropts.enterprise.option_code", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2274         { &hf_vendoropts_enterprise_option_length,
2275           { "Option length", "dhcpv6.vendoropts.enterprise.option_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2276         { &hf_vendoropts_enterprise_option_data,
2277           { "Option data", "dhcpv6.vendoropts.enterprise.option_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2278         { &hf_interface_id,
2279           { "Interface-ID", "dhcpv6.interface_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2280         { &hf_interface_id_link_address,
2281           { "Link Address", "dhcpv6.interface_id_link_address", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2282         { &hf_reconf_msg,
2283           { "Reconfigure message type", "dhcpv6.reconf_msg", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0, NULL, HFILL }},
2284         { &hf_sip_server_a,
2285           { "SIP server address", "dhcpv6.sip_server_a", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2286         { &hf_dns_servers,
2287           { "DNS server address", "dhcpv6.dns_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2288         { &hf_nis_servers,
2289           { "NIS server address", "dhcpv6.nis_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2290         { &hf_nisp_servers,
2291           { "NISP server address", "dhcpv6.nisp_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2292         { &hf_sntp_servers,
2293           { "SNTP server address", "dhcpv6.sntp_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2294         { &hf_opt_lifetime,
2295           { "Lifetime", "dhcpv6.lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2296         { &hf_bcmcs_servers_a,
2297           { "BCMCS server address", "dhcpv6.bcmcs_server_a", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2298         { &hf_remoteid_enterprise_id,
2299           { "Remote-ID", "dhcpv6.remoteid_enterprise_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2300         { &hf_subscriber_id,
2301           { "Subscriber-ID", "dhcpv6.subscriber_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2302         { &hf_pana_agent,
2303           { "PANA agents address", "dhcpv6.pana_agent", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2304         { &hf_opt_timezone,
2305           { "Time-zone", "dhcpv6.timezone", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2306         { &hf_opt_tzdb,
2307           { "TZ-database", "dhcpv6.tzdb", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2308         { &hf_lq_query,
2309           { "Query-type", "dhcpv6.lq_query", FT_UINT8, BASE_DEC, VALS(lq_query_vals), 0, NULL, HFILL }},
2310         { &hf_lq_query_link_address,
2311           { "Link address", "dhcpv6.lq_query_link_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2312         { &hf_clt_time,
2313           { "Clt_time", "dhcpv6.clt_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2314         { &hf_lq_relay_data_peer_addr,
2315           { "Peer address", "dhcpv6.lq_relay_data_peer_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2316         { &hf_lq_relay_data_msg,
2317           { "DHCPv6 relay message", "dhcpv6.lq_relay_data_msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2318         { &hf_lq_client_link,
2319           { "LQ client links address", "dhcpv6.lq_client_link", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2320         { &hf_capwap_ac_v6,
2321           { "CAPWAP Access Controllers address", "dhcpv6.capwap_ac_v6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2322         { &hf_aftr_name,
2323           { "DS-Lite AFTR Name", "dhcpv6.aftr_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2324         { &hf_iaprefix_pref_lifetime,
2325           { "Preferred lifetime", "dhcpv6.iaprefix.pref_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2326         { &hf_iaprefix_valid_lifetime,
2327           { "Valid lifetime", "dhcpv6.iaprefix.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2328         { &hf_iaprefix_pref_len,
2329           { "Prefix length", "dhcpv6.iaprefix.pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2330         { &hf_iaprefix_pref_addr,
2331           { "Prefix address", "dhcpv6.iaprefix.pref_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2332         { &hf_mip6_ha,
2333           { "Home Agent", "dhcpv6.mip6_home_agent", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2334         { &hf_mip6_hoa,
2335           { "Home Address", "dhcpv6.mip6_home_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2336         { &hf_nai,
2337           { "NAI", "dhcpv6.nai", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2338         { &hf_pd_exclude_pref_len,
2339           { "Prefix length", "dhcpv6.pd_exclude.pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2340         { &hf_pd_exclude_subnet_id,
2341           { "IPv6 subnet ID", "dhcpv6.pd_exclude.subnet_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2342         { &hf_option_ntpserver_type,
2343           { "Suboption", "dhcpv6.ntpserver.option.type", FT_UINT16, BASE_DEC, VALS(ntp_server_opttype_vals), 0x0, NULL, HFILL}},
2344         { &hf_option_ntpserver_length,
2345           { "Length", "dhcpv6.ntpserver.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2346         { &hf_option_ntpserver_addr,
2347           { "NTP Server Address", "dhcpv6.ntpserver.addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2348         { &hf_option_ntpserver_mc_addr,
2349           { "NTP Multicast Address", "dhcpv6.ntpserver.mc_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2350         { &hf_packetcable_ccc_suboption,
2351           { "Sub element", "dhcpv6.packetcable.ccc.suboption", FT_UINT16, BASE_DEC, VALS(pkt_ccc_opt_vals), 0, NULL, HFILL }},
2352         { &hf_packetcable_ccc_pri_dhcp,
2353           { "Primary DHCP", "dhcpv6.packetcable.ccc.pri_dhcp", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2354         { &hf_packetcable_ccc_sec_dhcp,
2355           { "Secondary DHCP", "dhcpv6.packetcable.ccc.sec_dhcp", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2356         { &hf_packetcable_ccc_prov_srv_type,
2357           { "Type", "dhcpv6.packetcable.ccc.prov_srv.type", FT_UINT8, BASE_DEC, VALS(pkt_ccc_prov_srv_type_vals), 0, NULL, HFILL }},
2358         { &hf_packetcable_ccc_prov_srv_fqdn,
2359           { "FQDN", "dhcpv6.packetcable.ccc.prov_srv.fqdn", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2360         { &hf_packetcable_ccc_prov_srv_ipv4,
2361           { "IPv4 address", "dhcpv6.packetcable.ccc.prov_srv.ipv4", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2362         { &hf_packetcable_ccc_as_krb_nominal_timeout,
2363           { "Nominal Timeout", "dhcpv6.packetcable.ccc.as_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2364         { &hf_packetcable_ccc_as_krb_max_timeout,
2365           { "Maximum Timeout", "dhcpv6.packetcable.ccc.as_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2366         { &hf_packetcable_ccc_as_krb_max_retry_count,
2367           { "Maximum Retry Count", "dhcpv6.packetcable.ccc.as_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2368         { &hf_packetcable_ccc_ap_krb_nominal_timeout,
2369           { "Nominal Timeout", "dhcpv6.packetcable.ccc.ap_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2370         { &hf_packetcable_ccc_ap_krb_max_timeout,
2371           { "Maximum Timeout", "dhcpv6.packetcable.ccc.ap_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2372         { &hf_packetcable_ccc_ap_krb_max_retry_count,
2373           { "Maximum Retry Count", "dhcpv6.packetcable.ccc.ap_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2374         { &hf_packetcable_ccc_krb_realm,
2375           { "KRB Realm", "dhcpv6.packetcable.ccc.krb_realm", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2376         { &hf_packetcable_ccc_tgt_flag,
2377           { "TGT Flags", "dhcpv6.packetcable.ccc.tgt_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
2378         { &hf_packetcable_ccc_tgt_flag_fetch,
2379           { "Fetch TGT", "dhcpv6.packetcable.ccc.tgt_flag.fetch", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
2380         { &hf_packetcable_ccc_prov_timer,
2381           { "Provisioning timer", "dhcpv6.packetcable.ccc.prov_timer", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2382         { &hf_packetcable_ccc_sec_tcm,
2383           { "SEC TCM Flags", "dhcpv6.packetcable.ccc.sec_tcm", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
2384         { &hf_packetcable_ccc_sec_tcm_provisioning_server,
2385           { "Provisioning Server", "dhcpv6.packetcable.ccc.sec_tcm.provisioning_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x01, NULL, HFILL }},
2386         { &hf_packetcable_ccc_sec_tcm_call_manager_server,
2387           { "Call Manager Servers", "dhcpv6.packetcable.ccc.tgt_flag.call_manager_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x02, NULL, HFILL }},
2388         { &hf_packetcable_cccV6_suboption,
2389           { "Sub element", "dhcpv6.packetcable.cccV6.suboption", FT_UINT16, BASE_DEC, VALS(pkt_cccV6_opt_vals), 0, NULL, HFILL }},
2390         { &hf_modem_capabilities_encoding_type,
2391           { "Type", "dhcpv6.docsis.cccV6.tlv5.suboption", FT_UINT16, BASE_DEC, VALS(modem_capabilities_encoding), 0, NULL, HFILL }},
2392         { &hf_eue_capabilities_encoding_type,
2393           { "Type", "dhcpv6.packetcable.cccV6.tlv5.suboption", FT_UINT16, BASE_DEC, VALS(eue_capabilities_encoding), 0, NULL, HFILL }},
2394         { &hf_capabilities_encoding_length,
2395           { "Length", "dhcpv6.cccV6.tlv5.suboption.length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2396         { &hf_capabilities_encoding_bytes,
2397           { "Value", "dhcpv6.cccV6.tlv5.suboption.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2398         { &hf_capabilities_encoding_number,
2399           { "Value", "dhcpv6.cccV6.tlv5.suboption.value", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2400         { &hf_packetcable_cccV6_pri_dss,
2401           { "Primary SSID", "dhcpv6.packetcable.cccV6.pri_dss", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2402         { &hf_packetcable_cccV6_sec_dss,
2403           { "Secondary SSID", "dhcpv6.packetcable.cccV6.sec_dss", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2404         { &hf_packetcable_cccV6_prov_srv_type,
2405           { "Type", "dhcpv6.packetcable.cccV6.prov_srv.type", FT_UINT8, BASE_DEC, VALS(pkt_cccV6_prov_srv_type_vals), 0, NULL, HFILL }},
2406         { &hf_packetcable_cccV6_prov_srv_fqdn,
2407           { "FQDN", "dhcpv6.packetcable.cccV6.prov_srv.fqdn", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2408         { &hf_packetcable_cccV6_prov_srv_ipv6,
2409           { "IPv6 address", "dhcpv6.packetcable.cccV6.prov_srv.ipv6", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
2410         { &hf_packetcable_cccV6_as_krb_nominal_timeout,
2411           { "Nominal Timeout", "dhcpv6.packetcable.cccV6.as_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2412         { &hf_packetcable_cccV6_as_krb_max_timeout,
2413           { "Maximum Timeout", "dhcpv6.packetcable.cccV6.as_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2414         { &hf_packetcable_cccV6_as_krb_max_retry_count,
2415           { "Maximum Retry Count", "dhcpv6.packetcable.cccV6.as_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2416         { &hf_packetcable_cccV6_ap_krb_nominal_timeout,
2417           { "Nominal Timeout", "dhcpv6.packetcable.cccV6.ap_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2418         { &hf_packetcable_cccV6_ap_krb_max_timeout,
2419           { "Maximum Timeout", "dhcpv6.packetcable.cccV6.ap_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2420         { &hf_packetcable_cccV6_ap_krb_max_retry_count,
2421           { "Maximum Retry Count", "dhcpv6.packetcable.cccV6.ap_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2422         { &hf_packetcable_cccV6_krb_realm,
2423           { "KRB Realm", "dhcpv6.packetcable.cccV6.krb_realm", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2424         { &hf_packetcable_cccV6_tgt_flag,
2425           { "TGT Flags", "dhcpv6.packetcable.cccV6.tgt_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
2426         { &hf_packetcable_cccV6_tgt_flag_fetch,
2427           { "Fetch TGT", "dhcpv6.packetcable.cccV6.tgt_flag.fetch", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
2428         { &hf_packetcable_cccV6_prov_timer,
2429           { "Provisioning timer", "dhcpv6.packetcable.cccV6.prov_timer", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2430         { &hf_packetcable_cccV6_sec_tcm,
2431           { "SEC TCM Flags", "dhcpv6.packetcable.cccV6.sec_tcm", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
2432         { &hf_packetcable_cccV6_sec_tcm_provisioning_server,
2433           { "Provisioning Server", "dhcpv6.packetcable.cccV6.sec_tcm.provisioning_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x01, NULL, HFILL }},
2434         { &hf_packetcable_cccV6_sec_tcm_call_manager_server,
2435           { "Call Manager Servers", "dhcpv6.packetcable.cccV6.tgt_flag.call_manager_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x02, NULL, HFILL }},
2436         { &hf_cablelabs_opts,
2437           { "Suboption", "dhcpv6.cablelabs.opt", FT_UINT16, BASE_DEC, VALS(cl_vendor_subopt_values), 0, NULL, HFILL }},
2438         { &hf_cablelabs_ipv6_server,
2439           { "IPv6 address", "dhcpv6.cablelabs.ipv6_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2440     };
2441
2442     static gint *ett[] = {
2443         &ett_dhcpv6,
2444         &ett_dhcpv6_option,
2445         &ett_dhcpv6_option_vsoption,
2446         &ett_dhcpv6_vendor_option,
2447         &ett_dhcpv6_pkt_option,
2448         &ett_dhcpv6_netserver_option,
2449         &ett_dhcpv6_tlv5_type
2450     };
2451
2452     static ei_register_info ei[] = {
2453         { &ei_dhcpv6_bogus_length, { "dhcpv6.bogus_length", PI_MALFORMED, PI_ERROR, "Bogus length", EXPFILL }},
2454         { &ei_dhcpv6_malformed_option, { "dhcpv6.malformed_option", PI_MALFORMED, PI_ERROR, "Malformed option", EXPFILL }},
2455         { &ei_dhcpv6_no_suboption_len, { "dhcpv6.no_suboption_len", PI_PROTOCOL, PI_WARN, "no room left in option for suboption length", EXPFILL }},
2456         { &ei_dhcpv6_invalid_byte, { "dhcpv6.invalid_byte", PI_PROTOCOL, PI_WARN, "Invalid at byte", EXPFILL }},
2457         { &ei_dhcpv6_invalid_time_value, { "dhcpv6.invalid_time_value", PI_PROTOCOL, PI_WARN, "Invalid time value", EXPFILL }},
2458         { &ei_dhcpv6_invalid_type, { "dhcpv6.invalid_type", PI_PROTOCOL, PI_WARN, "Invalid type", EXPFILL }},
2459         { &ei_dhcpv6_malformed_dns, { "dhcpv6.malformed_dns", PI_PROTOCOL, PI_WARN, "Malformed DNS name record (MS Vista client?)", EXPFILL }},
2460     };
2461
2462     static hf_register_info bulk_leasequery_hf[] = {
2463         { &hf_dhcpv6_bulk_leasequery_size,
2464           { "Message size", "dhcpv6.bulk_leasequery.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2465         { &hf_dhcpv6_bulk_leasequery_msgtype,
2466           { "Message type", "dhcpv6.bulk_leasequery.msgtype", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0x0, NULL, HFILL }},
2467         { &hf_dhcpv6_bulk_leasequery_reserved,
2468           { "Reserved", "dhcpv6.bulk_leasequery.reserved", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2469         { &hf_dhcpv6_bulk_leasequery_trans_id,
2470           { "Transaction ID", "dhcpv6.bulk_leasequery.trans_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2471     };
2472
2473     static gint *ett_bulk_leasequery[] = {
2474         &ett_dhcpv6_bulk_leasequery,
2475         &ett_dhcpv6_bulk_leasequery_options
2476     };
2477
2478     static ei_register_info ei_bulk_leasequery[] = {
2479         { &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 }},
2480         { &ei_dhcpv6_bulk_leasequery_no_lq_relay_data, { "dhcpv6.bulk_leasequery.no_lq_relay_data", PI_MALFORMED, PI_WARN, "LQ_RELAY_DATA: Not allowed in Bulk Leasequery", EXPFILL }},
2481         { &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 }},
2482     };
2483
2484     expert_module_t* expert_dhcpv6;
2485     expert_module_t* expert_dhcpv6_bulk_leasequery;
2486
2487     proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
2488     proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
2489     proto_register_subtree_array(ett, array_length(ett));
2490
2491     expert_dhcpv6 = expert_register_protocol(proto_dhcpv6);
2492     expert_register_field_array(expert_dhcpv6, ei, array_length(ei));
2493
2494     proto_dhcpv6_bulk_leasequery = proto_register_protocol("DHCPv6 Bulk Leasequery", "DHCPv6 Bulk Leasequery", "dhcpv6.bulk_leasequery");
2495     proto_register_field_array(proto_dhcpv6_bulk_leasequery, bulk_leasequery_hf, array_length(bulk_leasequery_hf));
2496     proto_register_subtree_array(ett_bulk_leasequery, array_length(ett_bulk_leasequery));
2497
2498     expert_dhcpv6_bulk_leasequery = expert_register_protocol(proto_dhcpv6_bulk_leasequery);
2499     expert_register_field_array(expert_dhcpv6_bulk_leasequery, ei_bulk_leasequery, array_length(ei_bulk_leasequery));
2500
2501     /* Allow other dissectors to find this one by name.
2502        Just choose upstream version for now as they are identical. */
2503     register_dissector("dhcpv6", dissect_dhcpv6_upstream, proto_dhcpv6);
2504
2505     bulkquery_module = prefs_register_protocol(proto_dhcpv6_bulk_leasequery, NULL);
2506     prefs_register_bool_preference(bulkquery_module, "desegment",
2507                                     "Desegment all Bulk Leasequery messages spanning multiple TCP segments",
2508                                     "Whether the Bulk Leasequery dissector should desegment all messages spanning multiple TCP segments",
2509                                     &dhcpv6_bulk_leasequery_desegment);
2510
2511 }
2512
2513 void
2514 proto_reg_handoff_dhcpv6(void)
2515 {
2516     dissector_handle_t dhcpv6_handle, dhcpv6_bulkquery_handle;
2517
2518     dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_downstream,
2519                                             proto_dhcpv6);
2520     dissector_add_uint("udp.port", UDP_PORT_DHCPV6_DOWNSTREAM, dhcpv6_handle);
2521     dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_upstream,
2522                                             proto_dhcpv6);
2523     dissector_add_uint("udp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_handle);
2524     dhcpv6_bulkquery_handle = create_dissector_handle(dissect_dhcpv6_bulk_leasequery,
2525                                             proto_dhcpv6_bulk_leasequery);
2526     dissector_add_uint("tcp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_bulkquery_handle);
2527 }
2528
2529 /*
2530  * Editor modelines
2531  *
2532  * Local Variables:
2533  * c-basic-offset: 4
2534  * tab-width: 8
2535  * indent-tabs-mode: nil
2536  * End:
2537  *
2538  * ex: set shiftwidth=4 tabstop=8 expandtab:
2539  * :indentSize=4:tabSize=8:noTabs=true:
2540  */