HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-dhcpv6.c
blob0b3278a92b30f7943884dde6c1667bf4c4ce6da4
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>
10 * $Id$
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
33 * Note that protocol constants are still subject to change, based on IANA
34 * assignment decisions.
36 * Wireshark - Network traffic analyzer
37 * By Gerald Combs <gerald@wireshark.org>
38 * Copyright 1998 Gerald Combs
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.
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.
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.
55 #include "config.h"
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() */
69 void proto_register_dhcpv6(void);
70 void proto_reg_handoff_dhcpv6(void);
72 static gboolean dhcpv6_bulk_leasequery_desegment = TRUE;
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;
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;
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;
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;
227 static gint ett_dhcpv6_bulk_leasequery = -1;
228 static gint ett_dhcpv6_bulk_leasequery_options = -1;
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;
234 #define UDP_PORT_DHCPV6_DOWNSTREAM 546
235 #define UDP_PORT_DHCPV6_UPSTREAM 547
237 #define DHCPV6_LEASEDURATION_INFINITY 0xffffffff
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
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
310 /* temporary value until defined by IETF */
311 #define OPTION_MIP6_HA 165
312 #define OPTION_MIP6_HOA 166
313 #define OPTION_NAI 167
315 #define DUID_LLT 1
316 #define DUID_EN 2
317 #define DUID_LL 3
318 #define DUID_LL_OLD 4
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 }
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 }
398 static const value_string statuscode_vals[] =
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 }
415 static const value_string duidtype_vals[] =
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 }
424 #define NTP_SUBOPTION_SRV_ADDR 1
425 #define NTP_SUBOPTION_MC_ADDR 2
426 #define NTP_SUBOPTION_SRV_FQDN 3
428 static const value_string ntp_server_opttype_vals[] =
430 { NTP_SUBOPTION_SRV_ADDR, "NTP Server Address" },
431 { NTP_SUBOPTION_MC_ADDR, "NTP Multicast Address" },
432 { NTP_SUBOPTION_SRV_FQDN, "NTP Server FQDN" },
434 { 0, NULL }
438 static const true_false_string fqdn_n = {
439 "Server should not perform DNS updates",
440 "Server should perform DNS updates"
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"
448 static const true_false_string fqdn_s = {
449 "Server should perform forward DNS updates",
450 "Server should not perform forward DNS updates"
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
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 },
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 */
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 */
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 */
499 /** CableLabs TLVs for DOCS_CMTS_CAP Vendor Option **/
500 #define CL_OPTION_DOCS_CMTS_TLV_VERS_NUM 0x01 /* 1 */
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 }
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 **/
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 **/
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 },
565 static const value_string pkt_ccc_prov_srv_type_vals[] = {
566 { 0, "FQDN" },
567 { 1, "IPv4" },
568 { 0, NULL },
571 static const value_string pkt_cccV6_prov_srv_type_vals[] = {
572 { 0, "FQDN" },
573 { 1, "IPv6" },
574 { 0, NULL },
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 }
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 },
596 #endif
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 },
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 },
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);
682 static gint
683 swap_field_length_with_char(tvbuff_t* tvb, wmem_strbuf_t* strbuf, gint offset, gint subopt_len, gchar replacement)
685 gint len_cnt = 0;
686 gint next_length = 0;
688 while (len_cnt < subopt_len) {
689 next_length = tvb_get_guint8(tvb, offset);
690 offset++;
691 len_cnt++;
693 wmem_strbuf_append(strbuf, tvb_get_string(wmem_packet_scope(), tvb, offset, next_length));
694 len_cnt += next_length;
696 /* Do not append replacement character to end of string. */
697 if (len_cnt+2 < subopt_len) {
698 wmem_strbuf_append_c(strbuf, replacement);
700 offset += next_length;
702 return len_cnt;
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)
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;
723 subopt = tvb_get_ntohs(tvb, optoff);
724 suboptoff += 2;
726 subopt_len = tvb_get_ntohs(tvb, suboptoff);
727 suboptoff += 2;
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);
734 /* g_print("dissect packetcable ccc option subopt_len=%d optend=%d\n\n", subopt_len, optend); */
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);
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);
744 else {
745 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
754 else {
755 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
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);
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);
773 else {
774 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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"));
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);
789 else {
790 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
800 else {
801 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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
816 ':' 58
817 so loop through and
818 make sure it conforms to the expected syntax.
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) {
832 else if (!kr_fail_flag) {
833 kr_pos = i;
834 kr_fail_flag = 1;
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);
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);
849 else {
850 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
860 else {
861 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
873 suboptoff += subopt_len;
874 break;
875 default:
876 suboptoff += subopt_len;
877 break;
881 /** Return the number of bytes processed **/
882 return (suboptoff - optoff);
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)
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;
900 subopt = tvb_get_ntohs(tvb, optoff);
901 suboptoff += 2;
903 subopt_len = tvb_get_ntohs(tvb, suboptoff);
904 suboptoff += 2;
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);
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);
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);
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);
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);
936 /** Type 0 is FQDN **/
937 if (type == 0) {
939 gint len_cnt;
940 wmem_strbuf_t* strbuf = NULL;
941 strbuf = wmem_strbuf_new(wmem_packet_scope(), "");
943 len_cnt = swap_field_length_with_char(tvb, strbuf, suboptoff+1, subopt_len, '.');
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));
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;
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"));
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);
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);
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(), "");
995 len_cnt = swap_field_length_with_char(tvb, strbuf, suboptoff, subopt_len, '.');
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));
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;
1021 if (kr_fail_flag)
1022 expert_add_info_format(pinfo, pi_tmp, &ei_dhcpv6_invalid_byte, "Invalid at byte=%d", kr_pos);
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);
1031 else {
1032 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
1042 else {
1043 expert_add_info_format(pinfo, vti, &ei_dhcpv6_bogus_length, "Bogus length: %d", subopt_len);
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);
1055 suboptoff += subopt_len;
1056 break;
1057 default:
1058 suboptoff += subopt_len;
1059 break;
1061 /** Return the number of bytes processed **/
1062 return (suboptoff - optoff);
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)
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 */
1082 field_len, /* holds the length of one occurrence of a field */
1083 field_value;
1084 gchar* device_type = NULL;
1086 if (len > 4) {
1087 while (off - voff < len) {
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);
1095 /* Values */
1096 sub_off = off + 4;
1098 switch(type) {
1099 /* String types */
1100 case CL_OPTION_DEVICE_TYPE :
1101 opt_len = tlv_len;
1102 field_len = tlv_len;
1104 device_type = tvb_get_string(wmem_packet_scope(), tvb, sub_off, field_len);
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);
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);
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;
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);
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;
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);
1171 else {
1172 proto_item_append_text(ti, "%s",
1173 tvb_bytes_to_str(tvb, sub_off, field_len));
1175 break;
1176 case CL_OPTION_TLV5 :
1177 opt_len = tlv_len;
1179 if (device_type == NULL)
1180 break;
1182 tlv5_counter = 0;
1183 tlv5_cap_index = sub_off;
1185 subtree = proto_item_add_subtree(ti, ett_dhcpv6_tlv5_type);
1187 while (tlv5_counter < tlv_len) {
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;
1197 tlv5_cap_index++;
1198 tlv5_counter++;
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.
1204 subtree2 = proto_item_add_subtree(ti2, ett_dhcpv6_tlv5_type);
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);
1209 tlv5_cap_index++;
1210 tlv5_counter += tlv5_cap_len;
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.
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);
1222 tlv5_cap_index += tlv5_cap_len;
1223 tlv5_counter++;
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);
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);
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);
1270 else
1271 sub_off += tagLen;
1273 field_len += tagLen + 2;
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);
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)); */
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;
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;
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);
1325 else {
1326 proto_item_append_text(ti, "%u", tvb_get_ntohl(tvb, sub_off));
1328 break;
1329 default:
1330 opt_len = tlv_len;
1331 break;
1333 off += (opt_len + 4);
1337 else {
1338 expert_add_info_format(pinfo, v_item, &ei_dhcpv6_bogus_length, "Bogus length: %d", len);
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)
1346 int start_offset=offset;
1347 char domain[256];
1348 int pos;
1349 guint8 len;
1351 pos=0;
1352 while(optlen){
1353 /* this is the start of the domain name */
1354 if(!pos){
1355 start_offset=offset;
1357 domain[pos]=0;
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.
1365 if ( optlen < len ) {
1366 expert_add_info(pinfo, v_item, &ei_dhcpv6_malformed_dns);
1367 return;
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;
1384 /* add the substring to domain */
1385 if(pos){
1386 domain[pos]='.';
1387 pos++;
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;
1394 tvb_memcpy(tvb, domain+pos, offset, len);
1395 pos+=len;
1396 offset+=len;
1397 optlen-=len;
1400 if(pos){
1401 domain[pos]=0;
1402 proto_tree_add_string(subtree, hf_dhcpv6_domain, tvb, start_offset, offset-start_offset, domain);
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)
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;
1420 /* option type and length must be present */
1421 if (eoff - off < 4) {
1422 *at_end = TRUE;
1423 return 0;
1426 opttype = tvb_get_ntohs(tvb, off);
1427 optlen = tvb_get_ntohs(tvb, off + 2);
1429 /* all option data must be present */
1430 if (eoff - off < 4 + optlen) {
1431 *at_end = TRUE;
1432 return 0;
1435 option_item = proto_tree_add_text(bp_tree, tvb, off, 4 + optlen,
1436 "%s", val_to_str(opttype, opttype_vals, "DHCP option %u"));
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);
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;
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:
1463 nstime_t llt_time;
1465 if (optlen < 8) {
1466 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "DUID: malformed option");
1467 break;
1469 proto_tree_add_item(subtree, hf_duidllt_hwtype, tvb, off + 2, 2, ENC_BIG_ENDIAN);
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;
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));
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;
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);
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;
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));
1505 break;
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;
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;
1534 temp_optlen += subopt_len;
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;
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);
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);
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;
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;
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;
1590 break;
1591 case OPTION_IAADDR:
1593 guint32 preferred_lifetime, valid_lifetime;
1595 if (optlen < 24) {
1596 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "IA_TA: malformed option");
1597 break;
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));
1603 preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
1604 valid_lifetime = tvb_get_ntohl(tvb, off + 20);
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);
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);
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;
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);
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;
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;
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);
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;
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;
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;
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;
1704 enterprise_no = tvb_get_ntohl(tvb, off);
1705 ti = proto_tree_add_item(subtree, hf_vendoropts_enterprise, tvb, off, 4, ENC_BIG_ENDIAN);
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;
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);
1725 break;
1726 case OPTION_INTERFACE_ID:
1728 gint namelen;
1730 if (optlen == 0) {
1731 expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "INTERFACE_ID: malformed option");
1732 break;
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);
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));
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;
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);
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;
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;
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);
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);
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;
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;
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);
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);
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;
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;
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);
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;
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;
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;
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 {
1871 * +-----+-+-+-+
1872 * | MBZ |N|O|S|
1873 * +-----+-+-+-+
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);
1880 dhcpv6_domain(subtree, option_item, pinfo, tvb, off+1, optlen-1);
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;
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:
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;
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);
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;
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;
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;
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;
1954 if (protocol == proto_dhcpv6_bulk_leasequery) {
1955 expert_add_info(pinfo, option_item, &ei_dhcpv6_bulk_leasequery_no_lq_relay_data);
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;
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;
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:
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;
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;
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);
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);
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;
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;
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;
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;
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;
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;
2048 return 4 + optlen;
2052 static void
2053 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2054 gboolean downstream, int off, int eoff)
2056 proto_tree *bp_tree = NULL;
2057 proto_item *ti;
2058 guint8 msgtype;
2059 gboolean at_end;
2060 struct e_in6_addr in6;
2062 msgtype = tvb_get_guint8(tvb, off);
2064 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msgtype, msgtype_vals, "Message Type %u"));
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);
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);
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);
2087 col_append_fstr(pinfo->cinfo, COL_INFO, "XID: 0x%x ", tvb_get_ntoh24(tvb, off + 1));
2088 off += 4;
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);
2096 static void
2097 dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
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));
2104 static void
2105 dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
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));
2113 static guint
2114 get_dhcpv6_bulk_leasequery_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
2116 return (tvb_get_ntohs(tvb, offset)+2);
2119 static int
2120 dissect_dhcpv6_bulk_leasequery_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
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;
2129 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6 BulkLease");
2130 col_clear(pinfo->cinfo, COL_INFO);
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);
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;
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);
2148 offset++;
2149 proto_tree_add_item(bulk_tree, hf_dhcpv6_bulk_leasequery_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2150 offset++;
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;
2156 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, Transaction ID: %5u",
2157 val_to_str_const(msg_type, msgtype_vals, "Unknown"), trans_id);
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);
2166 return tvb_length(tvb);
2169 static int
2170 dissect_dhcpv6_bulk_leasequery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2172 tcp_dissect_pdus(tvb, pinfo, tree, dhcpv6_bulk_leasequery_desegment, 2,
2173 get_dhcpv6_bulk_leasequery_pdu_len, dissect_dhcpv6_bulk_leasequery_pdu, data);
2174 return tvb_length(tvb);
2177 void
2178 proto_register_dhcpv6(void)
2180 module_t *bulkquery_module;
2182 static hf_register_info hf[] = {
2184 /* DHCPv6 header */
2185 { &hf_dhcpv6_msgtype,
2186 { "Message type", "dhcpv6.msgtype", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0x0, NULL, HFILL }},
2187 { &hf_dhcpv6_domain,
2188 { "Domain", "dhcpv6.domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2189 { &hf_dhcpv6_hopcount,
2190 { "Hopcount", "dhcpv6.hopcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2191 { &hf_dhcpv6_xid,
2192 { "Transaction ID", "dhcpv6.xid", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL}},
2193 { &hf_dhcpv6_linkaddr,
2194 { "Link address", "dhcpv6.linkaddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
2195 { &hf_dhcpv6_peeraddr,
2196 { "Peer address", "dhcpv6.peeraddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
2197 /* Generic option stuff */
2198 { &hf_option_type,
2199 { "Option", "dhcpv6.option.type", FT_UINT16, BASE_DEC, VALS(opttype_vals), 0x0, NULL, HFILL}},
2200 { &hf_option_length,
2201 { "Length", "dhcpv6.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2202 { &hf_option_value,
2203 { "Value", "dhcpv6.option.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2204 /* Individual options */
2205 { &hf_clientfqdn_reserved,
2206 { "Reserved", "dhcpv6.clientfqdn.reserved", FT_UINT8, BASE_HEX, NULL, 0xF8, NULL, HFILL}},
2207 { &hf_clientfqdn_n,
2208 { "N bit", "dhcpv6.clientfqdn.n", FT_BOOLEAN, 8, TFS(&fqdn_n), 0x4, "Whether the server SHOULD NOT perform any DNS updates", HFILL}},
2209 { &hf_clientfqdn_o,
2210 { "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}},
2211 { &hf_clientfqdn_s,
2212 { "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}},
2213 { &hf_remoteid_enterprise,
2214 { "Enterprise ID", "dhcpv6.remoteid.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "RemoteID Enterprise Number", HFILL }},
2215 { &hf_duid_bytes,
2216 { "DUID", "dhcpv6.duid.bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2217 { &hf_duid_type,
2218 { "DUID Type", "dhcpv6.duid.type", FT_UINT16, BASE_DEC, VALS(duidtype_vals), 0x0, NULL, HFILL}},
2219 { &hf_duidllt_time,
2220 { "DUID Time", "dhcpv6.duidllt.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}},
2221 { &hf_duidllt_link_layer_addr,
2222 { "Link-layer address", "dhcpv6.duidllt.link_layer_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2223 { &hf_duidllt_hwtype,
2224 { "Hardware type", "dhcpv6.duidllt.hwtype", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0, "DUID LLT Hardware Type", HFILL }},
2225 { &hf_duidll_hwtype,
2226 { "Hardware type", "dhcpv6.duidll.hwtype", FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0, "DUID LL Hardware Type", HFILL }},
2227 { &hf_duiden_enterprise,
2228 { "Enterprise ID", "dhcpv6.duiden.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "DUID EN Enterprise Number", HFILL }},
2229 { &hf_duiden_identifier,
2230 { "Identifier", "dhcpv6.duiden.identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2231 { &hf_duidll_link_layer_addr,
2232 { "Link-layer address", "dhcpv6.duidll.link_layer_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2233 { &hf_iaid,
2234 { "IAID", "dhcpv6.iaid", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2235 { &hf_iaid_t1,
2236 { "T1", "dhcpv6.iaid.t1", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2237 { &hf_iaid_t2,
2238 { "T2", "dhcpv6.iaid.t2", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2239 { &hf_iata,
2240 { "IATA", "dhcpv6.iata", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2241 { &hf_iaaddr_ip,
2242 { "IPv6 address", "dhcpv6.iaaddr.ip", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2243 { &hf_iaaddr_pref_lifetime,
2244 { "Preferred lifetime", "dhcpv6.iaaddr.pref_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2245 { &hf_iaaddr_valid_lifetime,
2246 { "Valid lifetime", "dhcpv6.iaaddr.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2247 { &hf_requested_option_code,
2248 { "Requested Option code", "dhcpv6.requested_option_code", FT_UINT16, BASE_DEC, VALS(opttype_vals), 0, NULL, HFILL }},
2249 { &hf_option_preference,
2250 { "Pref-value", "dhcpv6.option_preference", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2251 { &hf_elapsed_time,
2252 { "Elapsed time", "dhcpv6.elapsed_time", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL}},
2253 { &hf_auth_protocol,
2254 { "Protocol", "dhcpv6.auth.protocol", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2255 { &hf_auth_algorithm,
2256 { "Algorithm", "dhcpv6.auth.algorithm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2257 { &hf_auth_rdm,
2258 { "RDM", "dhcpv6.auth.rdm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
2259 { &hf_auth_replay_detection,
2260 { "Replay Detection", "dhcpv6.auth.replay_detection", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2261 { &hf_auth_info,
2262 { "Authentication Information", "dhcpv6.auth.info", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2263 { &hf_opt_unicast,
2264 { "IPv6 address", "dhcpv6.unicast", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2265 { &hf_opt_status_code,
2266 { "Status Code", "dhcpv6.status_code", FT_UINT16, BASE_DEC, VALS(statuscode_vals), 0, NULL, HFILL }},
2267 { &hf_opt_status_msg,
2268 { "Status Message", "dhcpv6.status_msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2269 { &hf_vendorclass_enterprise,
2270 { "Enterprise ID", "dhcpv6.vendorclass.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "Vendor Class Enterprise Number", HFILL }},
2271 { &hf_vendorclass_data,
2272 { "vendor-class-data", "dhcpv6.vendorclass.data", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2273 { &hf_vendoropts_enterprise,
2274 { "Enterprise ID", "dhcpv6.vendoropts.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "Vendor opts Enterprise Number", HFILL }},
2275 { &hf_vendoropts_enterprise_option_code,
2276 { "Option code", "dhcpv6.vendoropts.enterprise.option_code", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2277 { &hf_vendoropts_enterprise_option_length,
2278 { "Option length", "dhcpv6.vendoropts.enterprise.option_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2279 { &hf_vendoropts_enterprise_option_data,
2280 { "Option data", "dhcpv6.vendoropts.enterprise.option_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2281 { &hf_interface_id,
2282 { "Interface-ID", "dhcpv6.interface_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2283 { &hf_interface_id_link_address,
2284 { "Link Address", "dhcpv6.interface_id_link_address", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2285 { &hf_reconf_msg,
2286 { "Reconfigure message type", "dhcpv6.reconf_msg", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0, NULL, HFILL }},
2287 { &hf_sip_server_a,
2288 { "SIP server address", "dhcpv6.sip_server_a", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2289 { &hf_dns_servers,
2290 { "DNS server address", "dhcpv6.dns_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2291 { &hf_nis_servers,
2292 { "NIS server address", "dhcpv6.nis_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2293 { &hf_nisp_servers,
2294 { "NISP server address", "dhcpv6.nisp_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2295 { &hf_sntp_servers,
2296 { "SNTP server address", "dhcpv6.sntp_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2297 { &hf_opt_lifetime,
2298 { "Lifetime", "dhcpv6.lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2299 { &hf_bcmcs_servers_a,
2300 { "BCMCS server address", "dhcpv6.bcmcs_server_a", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2301 { &hf_remoteid_enterprise_id,
2302 { "Remote-ID", "dhcpv6.remoteid_enterprise_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2303 { &hf_subscriber_id,
2304 { "Subscriber-ID", "dhcpv6.subscriber_id", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2305 { &hf_pana_agent,
2306 { "PANA agents address", "dhcpv6.pana_agent", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2307 { &hf_opt_timezone,
2308 { "Time-zone", "dhcpv6.timezone", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2309 { &hf_opt_tzdb,
2310 { "TZ-database", "dhcpv6.tzdb", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2311 { &hf_lq_query,
2312 { "Query-type", "dhcpv6.lq_query", FT_UINT8, BASE_DEC, VALS(lq_query_vals), 0, NULL, HFILL }},
2313 { &hf_lq_query_link_address,
2314 { "Link address", "dhcpv6.lq_query_link_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2315 { &hf_clt_time,
2316 { "Clt_time", "dhcpv6.clt_time", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2317 { &hf_lq_relay_data_peer_addr,
2318 { "Peer address", "dhcpv6.lq_relay_data_peer_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2319 { &hf_lq_relay_data_msg,
2320 { "DHCPv6 relay message", "dhcpv6.lq_relay_data_msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2321 { &hf_lq_client_link,
2322 { "LQ client links address", "dhcpv6.lq_client_link", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2323 { &hf_capwap_ac_v6,
2324 { "CAPWAP Access Controllers address", "dhcpv6.capwap_ac_v6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2325 { &hf_aftr_name,
2326 { "DS-Lite AFTR Name", "dhcpv6.aftr_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2327 { &hf_iaprefix_pref_lifetime,
2328 { "Preferred lifetime", "dhcpv6.iaprefix.pref_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2329 { &hf_iaprefix_valid_lifetime,
2330 { "Valid lifetime", "dhcpv6.iaprefix.valid_lifetime", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
2331 { &hf_iaprefix_pref_len,
2332 { "Prefix length", "dhcpv6.iaprefix.pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2333 { &hf_iaprefix_pref_addr,
2334 { "Prefix address", "dhcpv6.iaprefix.pref_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2335 { &hf_mip6_ha,
2336 { "Home Agent", "dhcpv6.mip6_home_agent", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2337 { &hf_mip6_hoa,
2338 { "Home Address", "dhcpv6.mip6_home_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2339 { &hf_nai,
2340 { "NAI", "dhcpv6.nai", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2341 { &hf_pd_exclude_pref_len,
2342 { "Prefix length", "dhcpv6.pd_exclude.pref_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2343 { &hf_pd_exclude_subnet_id,
2344 { "IPv6 subnet ID", "dhcpv6.pd_exclude.subnet_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
2345 { &hf_option_ntpserver_type,
2346 { "Suboption", "dhcpv6.ntpserver.option.type", FT_UINT16, BASE_DEC, VALS(ntp_server_opttype_vals), 0x0, NULL, HFILL}},
2347 { &hf_option_ntpserver_length,
2348 { "Length", "dhcpv6.ntpserver.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2349 { &hf_option_ntpserver_addr,
2350 { "NTP Server Address", "dhcpv6.ntpserver.addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2351 { &hf_option_ntpserver_mc_addr,
2352 { "NTP Multicast Address", "dhcpv6.ntpserver.mc_addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2353 { &hf_packetcable_ccc_suboption,
2354 { "Sub element", "dhcpv6.packetcable.ccc.suboption", FT_UINT16, BASE_DEC, VALS(pkt_ccc_opt_vals), 0, NULL, HFILL }},
2355 { &hf_packetcable_ccc_pri_dhcp,
2356 { "Primary DHCP", "dhcpv6.packetcable.ccc.pri_dhcp", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2357 { &hf_packetcable_ccc_sec_dhcp,
2358 { "Secondary DHCP", "dhcpv6.packetcable.ccc.sec_dhcp", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2359 { &hf_packetcable_ccc_prov_srv_type,
2360 { "Type", "dhcpv6.packetcable.ccc.prov_srv.type", FT_UINT8, BASE_DEC, VALS(pkt_ccc_prov_srv_type_vals), 0, NULL, HFILL }},
2361 { &hf_packetcable_ccc_prov_srv_fqdn,
2362 { "FQDN", "dhcpv6.packetcable.ccc.prov_srv.fqdn", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2363 { &hf_packetcable_ccc_prov_srv_ipv4,
2364 { "IPv4 address", "dhcpv6.packetcable.ccc.prov_srv.ipv4", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
2365 { &hf_packetcable_ccc_as_krb_nominal_timeout,
2366 { "Nominal Timeout", "dhcpv6.packetcable.ccc.as_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2367 { &hf_packetcable_ccc_as_krb_max_timeout,
2368 { "Maximum Timeout", "dhcpv6.packetcable.ccc.as_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2369 { &hf_packetcable_ccc_as_krb_max_retry_count,
2370 { "Maximum Retry Count", "dhcpv6.packetcable.ccc.as_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2371 { &hf_packetcable_ccc_ap_krb_nominal_timeout,
2372 { "Nominal Timeout", "dhcpv6.packetcable.ccc.ap_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2373 { &hf_packetcable_ccc_ap_krb_max_timeout,
2374 { "Maximum Timeout", "dhcpv6.packetcable.ccc.ap_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2375 { &hf_packetcable_ccc_ap_krb_max_retry_count,
2376 { "Maximum Retry Count", "dhcpv6.packetcable.ccc.ap_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2377 { &hf_packetcable_ccc_krb_realm,
2378 { "KRB Realm", "dhcpv6.packetcable.ccc.krb_realm", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
2379 { &hf_packetcable_ccc_tgt_flag,
2380 { "TGT Flags", "dhcpv6.packetcable.ccc.tgt_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
2381 { &hf_packetcable_ccc_tgt_flag_fetch,
2382 { "Fetch TGT", "dhcpv6.packetcable.ccc.tgt_flag.fetch", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
2383 { &hf_packetcable_ccc_prov_timer,
2384 { "Provisioning timer", "dhcpv6.packetcable.ccc.prov_timer", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2385 { &hf_packetcable_ccc_sec_tcm,
2386 { "SEC TCM Flags", "dhcpv6.packetcable.ccc.sec_tcm", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
2387 { &hf_packetcable_ccc_sec_tcm_provisioning_server,
2388 { "Provisioning Server", "dhcpv6.packetcable.ccc.sec_tcm.provisioning_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x01, NULL, HFILL }},
2389 { &hf_packetcable_ccc_sec_tcm_call_manager_server,
2390 { "Call Manager Servers", "dhcpv6.packetcable.ccc.tgt_flag.call_manager_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x02, NULL, HFILL }},
2391 { &hf_packetcable_cccV6_suboption,
2392 { "Sub element", "dhcpv6.packetcable.cccV6.suboption", FT_UINT16, BASE_DEC, VALS(pkt_cccV6_opt_vals), 0, NULL, HFILL }},
2393 { &hf_modem_capabilities_encoding_type,
2394 { "Type", "dhcpv6.docsis.cccV6.tlv5.suboption", FT_UINT16, BASE_DEC, VALS(modem_capabilities_encoding), 0, NULL, HFILL }},
2395 { &hf_eue_capabilities_encoding_type,
2396 { "Type", "dhcpv6.packetcable.cccV6.tlv5.suboption", FT_UINT16, BASE_DEC, VALS(eue_capabilities_encoding), 0, NULL, HFILL }},
2397 { &hf_capabilities_encoding_length,
2398 { "Length", "dhcpv6.cccV6.tlv5.suboption.length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2399 { &hf_capabilities_encoding_bytes,
2400 { "Value", "dhcpv6.cccV6.tlv5.suboption.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2401 { &hf_capabilities_encoding_number,
2402 { "Value", "dhcpv6.cccV6.tlv5.suboption.value", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
2403 { &hf_packetcable_cccV6_pri_dss,
2404 { "Primary SSID", "dhcpv6.packetcable.cccV6.pri_dss", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2405 { &hf_packetcable_cccV6_sec_dss,
2406 { "Secondary SSID", "dhcpv6.packetcable.cccV6.sec_dss", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2407 { &hf_packetcable_cccV6_prov_srv_type,
2408 { "Type", "dhcpv6.packetcable.cccV6.prov_srv.type", FT_UINT8, BASE_DEC, VALS(pkt_cccV6_prov_srv_type_vals), 0, NULL, HFILL }},
2409 { &hf_packetcable_cccV6_prov_srv_fqdn,
2410 { "FQDN", "dhcpv6.packetcable.cccV6.prov_srv.fqdn", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2411 { &hf_packetcable_cccV6_prov_srv_ipv6,
2412 { "IPv6 address", "dhcpv6.packetcable.cccV6.prov_srv.ipv6", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }},
2413 { &hf_packetcable_cccV6_as_krb_nominal_timeout,
2414 { "Nominal Timeout", "dhcpv6.packetcable.cccV6.as_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2415 { &hf_packetcable_cccV6_as_krb_max_timeout,
2416 { "Maximum Timeout", "dhcpv6.packetcable.cccV6.as_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2417 { &hf_packetcable_cccV6_as_krb_max_retry_count,
2418 { "Maximum Retry Count", "dhcpv6.packetcable.cccV6.as_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2419 { &hf_packetcable_cccV6_ap_krb_nominal_timeout,
2420 { "Nominal Timeout", "dhcpv6.packetcable.cccV6.ap_krb.nominal_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2421 { &hf_packetcable_cccV6_ap_krb_max_timeout,
2422 { "Maximum Timeout", "dhcpv6.packetcable.cccV6.ap_krb.max_timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2423 { &hf_packetcable_cccV6_ap_krb_max_retry_count,
2424 { "Maximum Retry Count", "dhcpv6.packetcable.cccV6.ap_krb.max_retry_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
2425 { &hf_packetcable_cccV6_krb_realm,
2426 { "KRB Realm", "dhcpv6.packetcable.cccV6.krb_realm", FT_STRINGZ, BASE_NONE, NULL, 0, NULL, HFILL }},
2427 { &hf_packetcable_cccV6_tgt_flag,
2428 { "TGT Flags", "dhcpv6.packetcable.cccV6.tgt_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
2429 { &hf_packetcable_cccV6_tgt_flag_fetch,
2430 { "Fetch TGT", "dhcpv6.packetcable.cccV6.tgt_flag.fetch", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }},
2431 { &hf_packetcable_cccV6_prov_timer,
2432 { "Provisioning timer", "dhcpv6.packetcable.cccV6.prov_timer", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
2433 { &hf_packetcable_cccV6_sec_tcm,
2434 { "SEC TCM Flags", "dhcpv6.packetcable.cccV6.sec_tcm", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
2435 { &hf_packetcable_cccV6_sec_tcm_provisioning_server,
2436 { "Provisioning Server", "dhcpv6.packetcable.cccV6.sec_tcm.provisioning_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x01, NULL, HFILL }},
2437 { &hf_packetcable_cccV6_sec_tcm_call_manager_server,
2438 { "Call Manager Servers", "dhcpv6.packetcable.cccV6.tgt_flag.call_manager_server", FT_BOOLEAN, 16, TFS(&tfs_on_off), 0x02, NULL, HFILL }},
2439 { &hf_cablelabs_opts,
2440 { "Suboption", "dhcpv6.cablelabs.opt", FT_UINT16, BASE_DEC, VALS(cl_vendor_subopt_values), 0, NULL, HFILL }},
2441 { &hf_cablelabs_ipv6_server,
2442 { "IPv6 address", "dhcpv6.cablelabs.ipv6_server", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2445 static gint *ett[] = {
2446 &ett_dhcpv6,
2447 &ett_dhcpv6_option,
2448 &ett_dhcpv6_option_vsoption,
2449 &ett_dhcpv6_vendor_option,
2450 &ett_dhcpv6_pkt_option,
2451 &ett_dhcpv6_netserver_option,
2452 &ett_dhcpv6_tlv5_type
2455 static ei_register_info ei[] = {
2456 { &ei_dhcpv6_bogus_length, { "dhcpv6.bogus_length", PI_MALFORMED, PI_ERROR, "Bogus length", EXPFILL }},
2457 { &ei_dhcpv6_malformed_option, { "dhcpv6.malformed_option", PI_MALFORMED, PI_ERROR, "Malformed option", EXPFILL }},
2458 { &ei_dhcpv6_no_suboption_len, { "dhcpv6.no_suboption_len", PI_PROTOCOL, PI_WARN, "no room left in option for suboption length", EXPFILL }},
2459 { &ei_dhcpv6_invalid_byte, { "dhcpv6.invalid_byte", PI_PROTOCOL, PI_WARN, "Invalid at byte", EXPFILL }},
2460 { &ei_dhcpv6_invalid_time_value, { "dhcpv6.invalid_time_value", PI_PROTOCOL, PI_WARN, "Invalid time value", EXPFILL }},
2461 { &ei_dhcpv6_invalid_type, { "dhcpv6.invalid_type", PI_PROTOCOL, PI_WARN, "Invalid type", EXPFILL }},
2462 { &ei_dhcpv6_malformed_dns, { "dhcpv6.malformed_dns", PI_PROTOCOL, PI_WARN, "Malformed DNS name record (MS Vista client?)", EXPFILL }},
2465 static hf_register_info bulk_leasequery_hf[] = {
2466 { &hf_dhcpv6_bulk_leasequery_size,
2467 { "Message size", "dhcpv6.bulk_leasequery.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2468 { &hf_dhcpv6_bulk_leasequery_msgtype,
2469 { "Message type", "dhcpv6.bulk_leasequery.msgtype", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0x0, NULL, HFILL }},
2470 { &hf_dhcpv6_bulk_leasequery_reserved,
2471 { "Reserved", "dhcpv6.bulk_leasequery.reserved", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2472 { &hf_dhcpv6_bulk_leasequery_trans_id,
2473 { "Transaction ID", "dhcpv6.bulk_leasequery.trans_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2476 static gint *ett_bulk_leasequery[] = {
2477 &ett_dhcpv6_bulk_leasequery,
2478 &ett_dhcpv6_bulk_leasequery_options
2481 static ei_register_info ei_bulk_leasequery[] = {
2482 { &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 }},
2483 { &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 }},
2484 { &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 }},
2487 expert_module_t* expert_dhcpv6;
2488 expert_module_t* expert_dhcpv6_bulk_leasequery;
2490 proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
2491 proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
2492 proto_register_subtree_array(ett, array_length(ett));
2494 expert_dhcpv6 = expert_register_protocol(proto_dhcpv6);
2495 expert_register_field_array(expert_dhcpv6, ei, array_length(ei));
2497 proto_dhcpv6_bulk_leasequery = proto_register_protocol("DHCPv6 Bulk Leasequery", "DHCPv6 Bulk Leasequery", "dhcpv6.bulk_leasequery");
2498 proto_register_field_array(proto_dhcpv6_bulk_leasequery, bulk_leasequery_hf, array_length(bulk_leasequery_hf));
2499 proto_register_subtree_array(ett_bulk_leasequery, array_length(ett_bulk_leasequery));
2501 expert_dhcpv6_bulk_leasequery = expert_register_protocol(proto_dhcpv6_bulk_leasequery);
2502 expert_register_field_array(expert_dhcpv6_bulk_leasequery, ei_bulk_leasequery, array_length(ei_bulk_leasequery));
2504 /* Allow other dissectors to find this one by name.
2505 Just choose upstream version for now as they are identical. */
2506 register_dissector("dhcpv6", dissect_dhcpv6_upstream, proto_dhcpv6);
2508 bulkquery_module = prefs_register_protocol(proto_dhcpv6_bulk_leasequery, NULL);
2509 prefs_register_bool_preference(bulkquery_module, "desegment",
2510 "Desegment all Bulk Leasequery messages spanning multiple TCP segments",
2511 "Whether the Bulk Leasequery dissector should desegment all messages spanning multiple TCP segments",
2512 &dhcpv6_bulk_leasequery_desegment);
2516 void
2517 proto_reg_handoff_dhcpv6(void)
2519 dissector_handle_t dhcpv6_handle, dhcpv6_bulkquery_handle;
2521 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_downstream,
2522 proto_dhcpv6);
2523 dissector_add_uint("udp.port", UDP_PORT_DHCPV6_DOWNSTREAM, dhcpv6_handle);
2524 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_upstream,
2525 proto_dhcpv6);
2526 dissector_add_uint("udp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_handle);
2527 dhcpv6_bulkquery_handle = new_create_dissector_handle(dissect_dhcpv6_bulk_leasequery,
2528 proto_dhcpv6_bulk_leasequery);
2529 dissector_add_uint("tcp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_bulkquery_handle);
2533 * Editor modelines
2535 * Local Variables:
2536 * c-basic-offset: 4
2537 * tab-width: 8
2538 * indent-tabs-mode: nil
2539 * End:
2541 * ex: set shiftwidth=4 tabstop=8 expandtab:
2542 * :indentSize=4:tabSize=8:noTabs=true: