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>
11 * The information used comes from:
12 * RFC3315.txt (DHCPv6)
13 * RFC3319.txt (SIP options)
14 * RFC3633.txt (Prefix options)
15 * RFC3646.txt (DNS servers/domains)
16 * RFC3898.txt (NIS options)
17 * RFC4704.txt (Client FQDN)
18 * RFC5007.txt (DHCPv6 Leasequery)
19 * RFC5417.txt (CAPWAP Access Controller DHCP Option)
20 * RFC6334.txt (Dual-Stack Lite Option)
21 * draft-ietf-dhc-dhcpv6-opt-timeconfig-03.txt
22 * draft-ietf-dhc-dhcpv6-opt-lifetime-00.txt
23 * CL-SP-CANN-DHCP-Reg-I06-110210.doc
25 * Note that protocol constants are still subject to change, based on IANA
26 * assignment decisions.
28 * Wireshark - Network traffic analyzer
29 * By Gerald Combs <gerald@wireshark.org>
30 * Copyright 1998 Gerald Combs
32 * This program is free software; you can redistribute it and/or
33 * modify it under the terms of the GNU General Public License
34 * as published by the Free Software Foundation; either version 2
35 * of the License, or (at your option) any later version.
37 * This program is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 * GNU General Public License for more details.
42 * You should have received a copy of the GNU General Public License
43 * along with this program; if not, write to the Free Software
44 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
52 #include <epan/packet.h>
53 #include <epan/sminmpec.h>
54 #include <epan/strutil.h>
55 #include <epan/arptypes.h>
56 #include "packet-arp.h"
57 #include "packet-dns.h" /* for get_dns_name() */
59 static int proto_dhcpv6 = -1;
60 static int hf_dhcpv6_msgtype = -1;
61 static int hf_clientfqdn_reserved = -1;
62 static int hf_clientfqdn_n = -1;
63 static int hf_clientfqdn_o = -1;
64 static int hf_clientfqdn_s = -1;
65 static int hf_option_type = -1;
66 static int hf_option_length = -1;
67 static int hf_option_value = -1;
68 static int hf_remoteid_enterprise = -1;
69 static int hf_vendoropts_enterprise = -1;
70 static int hf_duiden_enterprise = -1;
71 static int hf_vendorclass_enterprise = -1;
72 static int hf_dhcpv6_hopcount = -1;
73 static int hf_dhcpv6_xid = -1;
74 static int hf_dhcpv6_peeraddr = -1;
75 static int hf_dhcpv6_linkaddr = -1;
77 static gint ett_dhcpv6 = -1;
78 static gint ett_dhcpv6_option = -1;
79 static gint ett_dhcpv6_option_vsoption = -1;
80 static gint ett_dhcpv6_vendor_option = -1;
81 static gint ett_dhcpv6_pkt_option = -1;
83 #define UDP_PORT_DHCPV6_DOWNSTREAM 546
84 #define UDP_PORT_DHCPV6_UPSTREAM 547
86 #define DHCPV6_LEASEDURATION_INFINITY 0xffffffff
97 #define RECONFIGURE 10
98 #define INFORMATION_REQUEST 11
100 #define RELAY_REPLY 13
101 #define LEASEQUERY 14
102 #define LEASEQUERY_REPLY 15
104 #define OPTION_CLIENTID 1
105 #define OPTION_SERVERID 2
106 #define OPTION_IA_NA 3
107 #define OPTION_IA_TA 4
108 #define OPTION_IAADDR 5
110 #define OPTION_PREFERENCE 7
111 #define OPTION_ELAPSED_TIME 8
112 #define OPTION_RELAY_MSG 9
113 /* #define OPTION_SERVER_MSG 10 */
114 #define OPTION_AUTH 11
115 #define OPTION_UNICAST 12
116 #define OPTION_STATUS_CODE 13
117 #define OPTION_RAPID_COMMIT 14
118 #define OPTION_USER_CLASS 15
119 #define OPTION_VENDOR_CLASS 16
120 #define OPTION_VENDOR_OPTS 17
121 #define OPTION_INTERFACE_ID 18
122 #define OPTION_RECONF_MSG 19
123 #define OPTION_RECONF_ACCEPT 20
124 #define OPTION_SIP_SERVER_D 21
125 #define OPTION_SIP_SERVER_A 22
126 #define OPTION_DNS_SERVERS 23
127 #define OPTION_DOMAIN_LIST 24
128 #define OPTION_IA_PD 25
129 #define OPTION_IAPREFIX 26
130 #define OPTION_NIS_SERVERS 27
131 #define OPTION_NISP_SERVERS 28
132 #define OPTION_NIS_DOMAIN_NAME 29
133 #define OPTION_NISP_DOMAIN_NAME 30
134 #define OPTION_SNTP_SERVERS 31
135 #define OPTION_LIFETIME 32
136 #define OPTION_BCMCS_SERVER_D 33
137 #define OPTION_BCMCS_SERVER_A 34
138 #define OPTION_GEOCONF_CIVIC 36
139 #define OPTION_REMOTE_ID 37
140 #define OPTION_SUBSCRIBER_ID 38
141 #define OPTION_CLIENT_FQDN 39
142 #define OPTION_PANA_AGENT 40
143 #define OPTION_TIME_ZONE 41
144 #define OPTION_TZDB 42
145 #define OPTION_ERO 43
146 #define OPTION_LQ_QUERY 44
147 #define OPTION_CLIENT_DATA 45
148 #define OPTION_CLT_TIME 46
149 #define OPTION_LQ_RELAY_DATA 47
150 #define OPTION_LQ_CLIENT_LINK 48
151 #define OPTION_CAPWAP_AC_V6 52
152 #define OPTION_AFTR_NAME 64
154 /* temporary value until defined by IETF */
155 #define OPTION_MIP6_HA 165
156 #define OPTION_MIP6_HOA 166
157 #define OPTION_NAI 167
162 #define DUID_LL_OLD 4
164 static const value_string msgtype_vals[] = {
165 { SOLICIT, "Solicit" },
166 { ADVERTISE, "Advertise" },
167 { REQUEST, "Request" },
168 { CONFIRM, "Confirm" },
170 { REBIND, "Rebind" },
172 { RELEASE, "Release" },
173 { DECLINE, "Decline" },
174 { RECONFIGURE, "Reconfigure" },
175 { INFORMATION_REQUEST, "Information-request" },
176 { RELAY_FORW, "Relay-forw" },
177 { RELAY_REPLY, "Relay-reply" },
178 { LEASEQUERY, "Leasequery" },
179 { LEASEQUERY_REPLY, "Leasequery-reply" },
183 static const value_string opttype_vals[] = {
184 { OPTION_CLIENTID, "Client Identifier" },
185 { OPTION_SERVERID, "Server Identifier" },
186 { OPTION_IA_NA, "Identity Association for Non-temporary Address" },
187 { OPTION_IA_TA, "Identity Association for Temporary Address" },
188 { OPTION_IAADDR, "IA Address" },
189 { OPTION_ORO, "Option Request" },
190 { OPTION_PREFERENCE, "Preference" },
191 { OPTION_ELAPSED_TIME, "Elapsed time" },
192 { OPTION_RELAY_MSG, "Relay Message" },
193 /* { OPTION_SERVER_MSG, "Server message" }, */
194 { OPTION_AUTH, "Authentication" },
195 { OPTION_UNICAST, "Server unicast" },
196 { OPTION_STATUS_CODE, "Status code" },
197 { OPTION_RAPID_COMMIT, "Rapid Commit" },
198 { OPTION_USER_CLASS, "User Class" },
199 { OPTION_VENDOR_CLASS, "Vendor Class" },
200 { OPTION_VENDOR_OPTS, "Vendor-specific Information" },
201 { OPTION_INTERFACE_ID, "Interface-Id" },
202 { OPTION_RECONF_MSG, "Reconfigure Message" },
203 { OPTION_RECONF_ACCEPT, "Reconfigure Accept" },
204 { OPTION_SIP_SERVER_D, "SIP Server Domain Name List" },
205 { OPTION_SIP_SERVER_A, "SIP Servers IPv6 Address List" },
206 { OPTION_DNS_SERVERS, "DNS recursive name server" },
207 { OPTION_DOMAIN_LIST, "Domain Search List" },
208 { OPTION_IA_PD, "Identity Association for Prefix Delegation" },
209 { OPTION_IAPREFIX, "IA Prefix" },
210 { OPTION_NIS_SERVERS, "Network Information Server" },
211 { OPTION_NISP_SERVERS, "Network Information Server V2" },
212 { OPTION_NIS_DOMAIN_NAME, "Network Information Server Domain Name" },
213 { OPTION_NISP_DOMAIN_NAME, "Network Information Server V2 Domain Name" },
214 { OPTION_SNTP_SERVERS, "Simple Network Time Protocol Server" },
215 { OPTION_LIFETIME, "Lifetime" },
216 { OPTION_BCMCS_SERVER_D, "BCMCS Server Domain" },
217 { OPTION_BCMCS_SERVER_A, "BCMCS Servers IPv6 Address List" },
218 { OPTION_GEOCONF_CIVIC, "Geoconf Civic Address" },
219 { OPTION_REMOTE_ID, "Remote Identifier" },
220 { OPTION_SUBSCRIBER_ID, "Subscriber Identifier" },
221 { OPTION_CLIENT_FQDN, "Fully Qualified Domain Name" },
222 { OPTION_PANA_AGENT, "PANA Agents IPv6 Address List" },
223 { OPTION_TIME_ZONE, "Time Zone" },
224 { OPTION_TZDB, "Time Zone Database" },
225 { OPTION_ERO, "Echo Request Option" },
226 { OPTION_LQ_QUERY, "Leasequery Query" },
227 { OPTION_CLIENT_DATA, "Leasequery Client Data" },
228 { OPTION_CLT_TIME, "Client Last Transaction Time" },
229 { OPTION_LQ_RELAY_DATA, "Leasequery Relay Data" },
230 { OPTION_LQ_CLIENT_LINK, "Leasequery Client Link Address List" },
231 { OPTION_CAPWAP_AC_V6, "CAPWAP Access Controllers" },
232 { OPTION_AFTR_NAME, "Dual-Stack Lite AFTR Name" },
233 { OPTION_MIP6_HA, "Mobile IPv6 Home Agent" },
234 { OPTION_MIP6_HOA, "Mobile IPv6 Home Address" },
235 { OPTION_NAI, "Network Access Identifier" },
239 static const value_string statuscode_vals[] =
246 {5, "UseMulticast" },
247 {6, "NoPrefixAvail" },
248 {7, "UnknownQueryType" },
249 {8, "MalformedQuery" },
250 {9, "NotConfigured" },
255 static const value_string duidtype_vals[] =
257 { DUID_LLT, "link-layer address plus time" },
258 { DUID_EN, "assigned by vendor based on Enterprise number" },
259 { DUID_LL, "link-layer address" },
260 { DUID_LL_OLD, "link-layer address (old)" },
264 static const true_false_string fqdn_n = {
265 "Server should not perform DNS updates",
266 "Server should perform DNS updates"
269 static const true_false_string fqdn_o = {
270 "Server has overridden client's S bit preference",
271 "Server has not overridden client's S bit preference"
274 static const true_false_string fqdn_s = {
275 "Server should perform forward DNS updates",
276 "Server should not perform forward DNS updates"
279 /* CableLabs Common Vendor Specific Options */
280 #define CL_OPTION_ORO 0x0001 /* 1 */
281 #define CL_OPTION_DEVICE_TYPE 0x0002 /* 2 */
282 #define CL_OPTION_EMBEDDED_COMPONENT_LIST 0x0003 /* 3 */
283 #define CL_OPTION_DEVICE_SERIAL_NUMBER 0x0004 /* 4 */
284 #define CL_OPTION_HARDWARE_VERSION_NUMBER 0x0005 /* 5 */
285 #define CL_OPTION_SOFTWARE_VERSION_NUMBER 0x0006 /* 6 */
286 #define CL_OPTION_BOOT_ROM_VERSION 0x0007 /* 7 */
287 #define CL_OPTION_VENDOR_OUI 0x0008 /* 8 */
288 #define CL_OPTION_MODEL_NUMBER 0x0009 /* 9 */
289 #define CL_OPTION_VENDOR_NAME 0x000a /* 10 */
290 /* 11-32 is currently reserved */
291 #define CL_OPTION_TFTP_SERVERS 0x0020 /* 32 */
292 #define CL_OPTION_CONFIG_FILE_NAME 0x0021 /* 33 */
293 #define CL_OPTION_SYSLOG_SERVERS 0x0022 /* 34 */
294 #define CL_OPTION_TLV5 0x0023 /* 35 */
295 #define CL_OPTION_DEVICE_ID 0x0024 /* 36 */
296 #define CL_OPTION_RFC868_SERVERS 0x0025 /* 37 */
297 #define CL_OPTION_TIME_OFFSET 0x0026 /* 38 */
298 #define CL_OPTION_IP_PREF 0x0027 /* 39 */
300 /** CableLabs DOCSIS Project Vendor Specific Options */
301 #define CL_OPTION_DOCS_CMTS_CAP 0x0401 /* 1025 */
302 #define CL_CM_MAC_ADDR 0x0402 /* 1026 */
303 #define CL_EROUTER_CONTAINER_OPTION 0x403 /* 1027 */
305 /** CableLabs PacketCable Project Vendor Specific Options **/
306 #define CL_OPTION_CCC 0x087a /* 2170 */
307 #define CL_OPTION_CCCV6 0x087b /* 2171 */
308 #define CL_OPTION_CORRELATION_ID 0x087c /*2172 */
310 /** CableLabs TLVs for DOCS_CMTS_CAP Vendor Option **/
311 #define CL_OPTION_DOCS_CMTS_TLV_VERS_NUM 0x01 /* 1 */
313 static const value_string cl_vendor_subopt_values[] = {
314 /* 1 */ { CL_OPTION_ORO, "Option Request = " },
315 /* 2 */ { CL_OPTION_DEVICE_TYPE, "Device Type = " },
316 /* 3 */ { CL_OPTION_EMBEDDED_COMPONENT_LIST, "Embedded Components = " },
317 /* 4 */ { CL_OPTION_DEVICE_SERIAL_NUMBER, "Serial Number = " },
318 /* 5 */ { CL_OPTION_HARDWARE_VERSION_NUMBER, "Hardware Version = " },
319 /* 6 */ { CL_OPTION_SOFTWARE_VERSION_NUMBER, "Software Version = " },
320 /* 7 */ { CL_OPTION_BOOT_ROM_VERSION, "Boot ROM Version = " },
321 /* 8 */ { CL_OPTION_VENDOR_OUI, "Organization Unique Identifier = " },
322 /* 9 */ { CL_OPTION_MODEL_NUMBER, "Model Number = " },
323 /* 10 */ { CL_OPTION_VENDOR_NAME, "Vendor Name = " },
324 /* 32 */ { CL_OPTION_TFTP_SERVERS, "TFTP Server Addresses : " },
325 /* 33 */ { CL_OPTION_CONFIG_FILE_NAME, "Configuration File Name = " },
326 /* 34 */ { CL_OPTION_SYSLOG_SERVERS, "Syslog Servers : " },
327 /* 35 */ { CL_OPTION_TLV5, "TLV5 = " },
328 /* 36 */ { CL_OPTION_DEVICE_ID, "Device Identifier = " },
329 /* 37 */ { CL_OPTION_RFC868_SERVERS, "Time Protocol Servers : " },
330 /* 38 */ { CL_OPTION_TIME_OFFSET, "Time Offset = " },
331 /* 39 */ { CL_OPTION_IP_PREF, "IP preference : " },
332 /* 1025 */ { CL_OPTION_DOCS_CMTS_CAP, "CMTS Capabilities Option : " },
333 /* 1026 */ { CL_CM_MAC_ADDR, "CM MAC Address Option = " },
334 /* 1027 */ { CL_EROUTER_CONTAINER_OPTION, "eRouter Container Option : " },
335 /* 2170 */ { CL_OPTION_CCC, "CableLabs Client Configuration : " },
336 /* 2171 */ { CL_OPTION_CCCV6, "CableLabs Client Configuration IPv6 : " },
337 /* 2172 */ { CL_OPTION_CORRELATION_ID, "CableLabs Correlation ID = " },
341 #define PKT_CCC_PRI_DHCP 0x0001
342 #define PKT_CCC_SEC_DHCP 0x0002
343 #define PKT_CCC_IETF_PROV_SRV 0x0003
344 #define PKT_CCC_IETF_AS_KRB 0x0004
345 #define PKT_CCC_IETF_AP_KRB 0x0005
346 #define PKT_CCC_KRB_REALM 0x0006
347 #define PKT_CCC_TGT_FLAG 0x0007
348 #define PKT_CCC_PROV_TIMER 0x0008
349 #define PKT_CCC_IETF_SEC_TKT 0x0009
350 /** 10 -255 Reserved for future extensions **/
352 #define PKT_CCCV6_PRI_DSS 0x0001
353 #define PKT_CCCV6_SEC_DSS 0x0002
354 #define PKT_CCCV6_IETF_PROV_SRV 0x0003
355 #define PKT_CCCV6_IETF_AS_KRB 0x0004
356 #define PKT_CCCV6_IETF_AP_KRB 0x0005
357 #define PKT_CCCV6_KRB_REALM 0x0006
358 #define PKT_CCCV6_TGT_FLAG 0x0007
359 #define PKT_CCCV6_PROV_TIMER 0x0008
360 #define PKT_CCCV6_IETF_SEC_TKT 0x0009
361 /** 10 -255 Reserved for future extensions **/
363 static const value_string pkt_ccc_opt_vals[] = {
364 { PKT_CCC_PRI_DHCP, "TSP's Primary DHCP Server" },
365 { PKT_CCC_SEC_DHCP, "TSP's Secondary DHCP Server" },
366 { PKT_CCC_IETF_PROV_SRV, "TSP's Provisioning Server" },
367 { PKT_CCC_IETF_AS_KRB, "TSP's AS-REQ/AS-REP Backoff and Retry" },
368 { PKT_CCC_IETF_AP_KRB, "TSP's AP-REQ/AP-REP Backoff and Retry" },
369 { PKT_CCC_KRB_REALM, "TSP's Kerberos Realm Name" },
370 { PKT_CCC_TGT_FLAG, "TSP's Ticket Granting Server Utilization" },
371 { PKT_CCC_PROV_TIMER, "TSP's Provisioning Timer Value" },
372 { PKT_CCC_IETF_SEC_TKT, "PacketCable Security Ticket Control" },
376 static const value_string pkt_cccV6_opt_vals[] = {
377 { PKT_CCCV6_PRI_DSS, "TSP's Primary DHCPv6 Server Selector ID" },
378 { PKT_CCCV6_SEC_DSS, "TSP's Secondary DHCPv6 Server Selector ID " },
379 { PKT_CCCV6_IETF_PROV_SRV, "TSP's Provisioning Server" },
380 { PKT_CCCV6_IETF_AS_KRB, "TSP's AS-REQ/AS-REP Backoff and Retry" },
381 { PKT_CCCV6_IETF_AP_KRB, "TSP's AP-REQ/AP-REP Backoff and Retry" },
382 { PKT_CCCV6_KRB_REALM, "TSP's Kerberos Realm Name" },
383 { PKT_CCCV6_TGT_FLAG, "TSP's Ticket Granting Server Utilization" },
384 { PKT_CCCV6_PROV_TIMER, "TSP's Provisioning Timer Value" },
385 { PKT_CCCV6_IETF_SEC_TKT, "PacketCable Security Ticket Control" },
389 static const value_string sec_tcm_vals[] = {
390 { 1 << 0, "PacketCable Provisioning Server" },
391 { 1 << 1, "PacketCable Call Manager Servers" },
395 /* May be called recursively */
397 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
398 gboolean downstream, int off, int eoff);
401 dissect_packetcable_ccc_option(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
404 /** THE ENCODING OF THIS SUBOPTION HAS CHANGED FROM DHCPv4
405 the code and length fields have grown from a single octet to
407 int suboptoff = optoff;
408 guint16 subopt, subopt_len, sec_tcm;
409 guint8 fetch_tgt, timer_val, type;
411 proto_tree *pkt_s_tree;
412 guint32 ipv4_address;
413 guchar kr_name; /** A character in the kerberos realm name option */
414 guint8 kr_value; /* The integer value of the character currently being tested */
415 int kr_fail_flag = 0; /* Flag indicating an invalid character was found */
416 int kr_pos = 0; /* The position of the first invalid character */
420 subopt = tvb_get_ntohs(tvb, optoff);
423 subopt_len = tvb_get_ntohs(tvb, suboptoff);
426 /* There must be at least five octets left to be a valid sub element */
428 proto_tree_add_text(v_tree, tvb, optoff, 1,
429 "Sub element %d: no room left in option for suboption length",
433 /* g_print("dissect packetcable ccc option subopt_len=%d optend=%d\n\n", subopt_len, optend); */
435 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 4,
436 "Sub element %u: %s: ", subopt,
437 val_to_str(subopt, pkt_ccc_opt_vals, "unknown/reserved") );
440 case PKT_CCC_PRI_DHCP: /* IPv4 address values */
441 case PKT_CCC_SEC_DHCP:
442 if (subopt_len == 4) {
443 ipv4_address = tvb_get_ipv4(tvb, suboptoff);
444 proto_item_append_text(vti, "%s (%u byte%s%s)",
445 ip_to_str((guint8 *)&ipv4_address), subopt_len,
446 plurality(subopt_len, "", "s"),
447 subopt_len != 4 ? " [Invalid]" : "");
450 proto_tree_add_text(vti, tvb, suboptoff, subopt_len,
451 "Bogus length: %d", subopt_len);
455 suboptoff += subopt_len;
457 case PKT_CCC_IETF_PROV_SRV :
458 type = tvb_get_guint8(tvb, suboptoff);
459 /** Type 0 is FQDN **/
461 proto_item_append_text(vti, "%s (%u byte%s)",
462 tvb_format_stringzpad(tvb, suboptoff+1, subopt_len-1),
464 plurality(subopt_len-1, "", "s") );
466 /** Type 0 is IPv4 **/
467 else if (type == 1) {
468 if (subopt_len == 5) {
469 ipv4_address = tvb_get_ipv4(tvb, suboptoff+1);
470 proto_item_append_text(vti, "%s (%u byte%s%s)",
471 ip_to_str((guint8 *)&ipv4_address), subopt_len,
472 plurality(subopt_len, "", "s"),
473 subopt_len != 5 ? " [Invalid]" : "");
476 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
480 proto_item_append_text(vti, "Invalid type: %u (%u byte%s)",
481 type, subopt_len, plurality(subopt_len, "", "s"));
483 suboptoff += subopt_len;
486 case PKT_CCC_IETF_AS_KRB :
487 case PKT_CCC_IETF_AP_KRB :
488 if (subopt_len == 12) {
489 pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
490 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
491 "Nominal Timeout : %u", tvb_get_ntohl(tvb, suboptoff));
492 proto_tree_add_text(pkt_s_tree, tvb, suboptoff+4, 4,
493 "Maximum Timeout : %u", tvb_get_ntohl(tvb, suboptoff+4));
494 proto_tree_add_text(pkt_s_tree, tvb, suboptoff+8, 4,
495 "Maximum Retry Count : %u", tvb_get_ntohl(tvb, suboptoff+8));
499 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
501 suboptoff += subopt_len;
503 case PKT_CCC_KRB_REALM:
504 if (subopt_len > 0) {
505 /** The only allowable characters are
506 A-Z (upper case only) 65-90
516 make sure it conforms to the expected syntax.
518 for (i=0; i < subopt_len; i++) {
519 kr_name = tvb_get_guint8(tvb, suboptoff + i);
520 kr_value = (int)kr_name;
521 if ((kr_value >= 65 && kr_value <= 90) ||
530 else if (!kr_fail_flag) {
534 proto_item_append_text(vti, "%c", kr_name);
538 proto_item_append_text(vti, " (%u byte%s [Invalid at byte=%d]) ",
540 plurality(subopt_len, "", "s"),
544 proto_item_append_text(vti, " (%u byte%s%s) ",
546 plurality(subopt_len, "", "s"),
547 kr_fail_flag != 0 ? " [Invalid]" : "");
550 suboptoff += subopt_len;
553 case PKT_CCC_TGT_FLAG:
554 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
555 proto_item_append_text(vti, "%s (%u byte%s%s)",
556 fetch_tgt == 1 ? "True" : "False",
558 plurality(subopt_len, "", "s"),
559 subopt_len != 1 ? " [Invalid]" : "");
560 suboptoff += subopt_len;
563 case PKT_CCC_PROV_TIMER:
564 timer_val = tvb_get_guint8(tvb, suboptoff);
565 /* proto_item_append_text(vti, "%u%s (%u byte%s%s)", timer_val,
566 timer_val > 30 ? " [Invalid]" : "", */
567 proto_item_append_text(vti, "%u (%u byte%s%s)", timer_val,
569 plurality(subopt_len, "", "s"),
570 subopt_len != 1 ? " [Invalid]" : "");
571 suboptoff += subopt_len;
574 case PKT_CCC_IETF_SEC_TKT :
575 sec_tcm = tvb_get_ntohs(tvb, suboptoff);
576 proto_item_append_text(vti, "0x%04x (%u byte%s%s)",
577 sec_tcm, subopt_len, plurality(subopt_len, "", "s"),
578 subopt_len != 2 ? " [Invalid]" : "");
580 if (subopt_len == 2) {
581 pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
582 for (i=0; i< 2; i++) {
583 if (sec_tcm & sec_tcm_vals[i].value) {
584 decode_bitfield_value(bit_fld, sec_tcm, sec_tcm_vals[i].value, 16);
585 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 2, "%s %s",
586 bit_fld, sec_tcm_vals[i].strptr);
590 suboptoff += subopt_len;
595 suboptoff += subopt_len;
600 /** Return the number of bytes processed **/
601 return (suboptoff - optoff);
605 dissect_packetcable_cccV6_option(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
608 int suboptoff = optoff;
609 guint16 subopt, subopt_len, sec_tcm;
610 guint8 fetch_tgt, timer_val, type;
612 proto_tree *pkt_s_tree;
613 guchar kr_name; /* A character in the kerberos realm name option */
614 guint8 kr_value; /* The integer value of the character currently being tested */
615 int kr_fail_flag = 0; /* Flag indicating an invalid character was found */
616 int kr_pos = 0; /* The position of the first invalid character */
619 struct e_in6_addr in6;
621 subopt = tvb_get_ntohs(tvb, optoff);
624 subopt_len = tvb_get_ntohs(tvb, suboptoff);
627 /* There must be at least five octets left to be a valid sub element */
629 proto_tree_add_text(v_tree, tvb, optoff, 1,
630 "Sub element %d: no room left in option for suboption length",
635 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 4,
636 "Sub element %u: %s: ", subopt,
637 val_to_str(subopt, pkt_cccV6_opt_vals, "unknown/reserved") );
640 case PKT_CCCV6_PRI_DSS:
641 case PKT_CCCV6_SEC_DSS:
642 if (subopt_len < 35) {
643 proto_item_append_text(vti, "%s (%u byte%s)",
644 tvb_format_stringzpad(tvb, suboptoff, subopt_len),
646 plurality(subopt_len-1, "", "s") );
648 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
650 suboptoff += subopt_len;
653 case PKT_CCCV6_IETF_PROV_SRV:
654 type = tvb_get_guint8(tvb, suboptoff);
655 /** Type 0 is FQDN **/
657 proto_item_append_text(vti, "%s (%u byte%s)",
658 tvb_format_stringzpad(tvb, suboptoff+1, subopt_len-1),
660 plurality(subopt_len-1, "", "s") );
661 /** Type 1 is IPv6 **/
662 } else if (type == 1) {
663 if ((subopt_len % 16) == 0) {
664 for (i = 0; i < subopt_len/16; i++) {
665 tvb_get_ipv6(tvb, suboptoff, &in6);
666 proto_item_append_text(vti, "IPv6 address %d: %s",
667 i+1, ip6_to_str(&in6));
672 proto_item_append_text(vti, "Invalid type: %u (%u byte%s)",
673 type, subopt_len, plurality(subopt_len, "", "s"));
675 suboptoff += subopt_len;
678 case PKT_CCCV6_IETF_AS_KRB:
679 case PKT_CCCV6_IETF_AP_KRB:
680 if (subopt_len == 12) {
681 pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
682 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
683 "Nominal Timeout : %u", tvb_get_ntohl(tvb, suboptoff));
684 proto_tree_add_text(pkt_s_tree, tvb, suboptoff+4, 4,
685 "Maximum Timeout : %u", tvb_get_ntohl(tvb, suboptoff+4));
686 proto_tree_add_text(pkt_s_tree, tvb, suboptoff+8, 4,
687 "Maximum Retry Count : %u", tvb_get_ntohl(tvb, suboptoff+8));
689 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
691 suboptoff += subopt_len;
694 case PKT_CCCV6_KRB_REALM:
695 if (subopt_len > 0) {
696 for (i=0; i < subopt_len; i++) {
697 kr_name = tvb_get_guint8(tvb, suboptoff + i);
698 kr_value = (int)kr_name;
699 if ((kr_value >= 65 && kr_value <= 90) ||
707 } else if (!kr_fail_flag) {
711 proto_item_append_text(vti, "%c", kr_name);
715 proto_item_append_text(vti, " (%u byte%s [Invalid at byte=%d]) ",
717 plurality(subopt_len, "", "s"),
720 proto_item_append_text(vti, " (%u byte%s%s) ",
722 plurality(subopt_len, "", "s"),
723 kr_fail_flag != 0 ? " [Invalid]" : "");
726 suboptoff += subopt_len;
729 case PKT_CCCV6_TGT_FLAG:
730 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
731 proto_item_append_text(vti, "%s (%u byte%s%s)",
732 fetch_tgt == 1 ? "True" : "False",
734 plurality(subopt_len, "", "s"),
735 subopt_len != 1 ? " [Invalid]" : "");
736 suboptoff += subopt_len;
739 case PKT_CCCV6_PROV_TIMER:
740 timer_val = tvb_get_guint8(tvb, suboptoff);
741 proto_item_append_text(vti, "%u (%u byte%s%s)", timer_val,
743 plurality(subopt_len, "", "s"),
744 subopt_len != 1 ? " [Invalid]" : "");
745 suboptoff += subopt_len;
748 case PKT_CCCV6_IETF_SEC_TKT:
749 sec_tcm = tvb_get_ntohs(tvb, suboptoff);
750 proto_item_append_text(vti, "0x%04x (%u byte%s%s)",
751 sec_tcm, subopt_len, plurality(subopt_len, "", "s"),
752 subopt_len != 2 ? " [Invalid]" : "");
754 if (subopt_len == 2) {
755 pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
756 for (i=0; i< 2; i++) {
757 if (sec_tcm & sec_tcm_vals[i].value) {
758 decode_bitfield_value(bit_fld, sec_tcm, sec_tcm_vals[i].value, 16);
759 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 2, "%s %s",
760 bit_fld, sec_tcm_vals[i].strptr);
765 suboptoff += subopt_len;
769 suboptoff += subopt_len;
773 /** Return the number of bytes processed **/
774 return (suboptoff - optoff);
778 dissect_cablelabs_specific_opts(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len)
781 guint16 tlv_len; /* holds the number of elements in the tlv */
782 guint16 opt_len; /* holds the length of the suboption */
785 int sub_off; /** The offset for the sub-option */
788 int field_len; /* holds the length of one occurrence of a field */
791 struct e_in6_addr in6;
794 while (off - voff < len) {
797 type = tvb_get_ntohs(tvb, off);
798 ti = proto_tree_add_text(v_tree, tvb, off, 2,
799 "Suboption %d: %s", type, val_to_str(type,
800 cl_vendor_subopt_values, "unknown"));
802 tlv_len = tvb_get_ntohs(tvb, off+2);
809 case CL_OPTION_DEVICE_TYPE :
810 case CL_OPTION_DEVICE_SERIAL_NUMBER :
811 case CL_OPTION_HARDWARE_VERSION_NUMBER :
812 case CL_OPTION_SOFTWARE_VERSION_NUMBER :
813 case CL_OPTION_BOOT_ROM_VERSION :
814 case CL_OPTION_MODEL_NUMBER :
815 case CL_OPTION_VENDOR_NAME :
816 case CL_OPTION_CONFIG_FILE_NAME :
817 case CL_OPTION_EMBEDDED_COMPONENT_LIST :
820 proto_item_append_text(ti, "\"%s\"",
821 tvb_format_stringzpad(tvb, sub_off, field_len));
824 case CL_OPTION_VENDOR_OUI :
825 /* CableLabs specs treat 17.8 inconsistently
826 * as either binary (3b) or string (6b) */
829 proto_item_append_text(ti, "%s",
830 tvb_bytes_to_str_punct(tvb, sub_off, 3, ':'));
831 } else if (tlv_len == 6) {
832 proto_item_append_text(ti, "\"%s\"", tvb_format_stringzpad(tvb, sub_off, tlv_len));
834 proto_item_append_text(ti, "Suboption %d: suboption length isn't 3 or 6", type);
842 for (i = 0; i < tlv_len; i += field_len) {
843 sub_value = tvb_get_ntohs(tvb, sub_off);
844 proto_item_append_text(ti, " %d", sub_value);
845 sub_off += field_len;
850 /* List of IPv6 Address */
851 case CL_OPTION_TFTP_SERVERS :
852 case CL_OPTION_SYSLOG_SERVERS :
853 case CL_OPTION_RFC868_SERVERS :
856 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
858 if ((tlv_len % field_len) == 0) {
859 for (i = 0; i < tlv_len/field_len; i++) {
860 tvb_get_ipv6(tvb, sub_off, &in6);
861 proto_tree_add_text(subtree, tvb, sub_off,
862 sizeof(in6), "IPv6 address %d: %s",
863 i+1, ip6_to_str(&in6));
864 sub_off += field_len;
869 case CL_OPTION_DEVICE_ID :
873 proto_item_append_text(ti, "Bogus value length=%d",
877 proto_item_append_text(ti, "%s",
878 tvb_bytes_to_str(tvb, sub_off, field_len));
882 case CL_OPTION_TLV5 :
885 proto_item_append_text(ti, "%s",
886 tvb_bytes_to_str(tvb, sub_off, field_len));
889 case CL_OPTION_TIME_OFFSET :
891 proto_item_append_text(ti, "%d", tvb_get_ntohl(tvb, sub_off));
894 case CL_OPTION_IP_PREF :
896 field_value = tvb_get_guint8(tvb, sub_off);
897 if (field_value == 1) {
898 proto_item_append_text(ti, "%s", "IPv4");
899 } else if (field_value == 2) {
900 proto_item_append_text(ti, "%s", "IPv6");
902 proto_item_append_text(ti, "%s", "Unknown");
906 case CL_OPTION_DOCS_CMTS_CAP :
909 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
911 /* tlv_len contains the total length of all the TLVs for this
914 for (i = 0; field_len < opt_len; i++) {
917 tag = tvb_get_guint8(tvb, sub_off);
919 tagLen = tvb_get_guint8(tvb, sub_off);
921 if (tag == CL_OPTION_DOCS_CMTS_TLV_VERS_NUM &&
925 major = tvb_get_guint8(tvb, sub_off);
927 minor = tvb_get_guint8(tvb, sub_off);
929 proto_tree_add_text(subtree, tvb, sub_off-2,
930 2, "DOCSIS Version Number %d.%d",
936 field_len += tagLen + 2;
940 proto_tree_add_text(subtree, tvb, sub_off, 0, "empty");
943 case CL_CM_MAC_ADDR :
947 proto_item_append_text(ti, "Bogus value length=%d",
951 /*proto_item_append_text(ti, "CM MAC Address Option = %s", */
952 proto_item_append_text(ti, "%s", tvb_bytes_to_str_punct(tvb, sub_off, opt_len, ':'));
953 /* tvb_bytes_to_str(tvb, sub_off, opt_len)); */
955 sub_off += field_len;
958 case CL_EROUTER_CONTAINER_OPTION :
961 proto_item_append_text(ti, " %s (len=%d)",
962 tvb_bytes_to_str(tvb, sub_off, opt_len), tlv_len);
963 sub_off += field_len;
969 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
970 proto_item_append_text(ti, " (%d bytes)", opt_len);
971 while (field_len < opt_len) {
972 sub_value = dissect_packetcable_ccc_option(subtree, tvb,
973 sub_off, (opt_len - field_len));
974 sub_off += sub_value;
975 field_len += sub_value;
977 sub_off += field_len;
980 case CL_OPTION_CCCV6 :
983 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
984 proto_item_append_text(ti, " (%d bytes)", opt_len);
985 while (field_len < opt_len) {
986 sub_value = dissect_packetcable_cccV6_option(subtree, tvb,
987 sub_off, (opt_len - field_len));
988 sub_off += sub_value;
989 field_len += sub_value;
991 sub_off += field_len;
994 case CL_OPTION_CORRELATION_ID :
997 proto_item_append_text(ti, "Bogus value length=%d",
1001 proto_item_append_text(ti, "%d", tvb_get_ntohl(tvb, sub_off));
1009 off += (opt_len + 4);
1014 proto_tree_add_text(v_tree, tvb, off, len-off,
1015 "Bogus length: %d", len);
1021 dhcpv6_domain(proto_tree * subtree, tvbuff_t *tvb, int offset, guint16 optlen)
1023 int start_offset=offset;
1030 /* this is the start of the domain name */
1032 start_offset=offset;
1036 /* read length of the next substring */
1037 len = tvb_get_guint8(tvb, offset);
1038 /* Microsoft dhcpv6 clients aren't currently RFC 4704 conform: They send an
1039 * ASCII string instead of a DNS record encoded domain name. Catch that case
1040 * to allow us to continue after such a malformed record.
1042 if ( optlen < len ) {
1043 proto_tree_add_text(subtree, tvb, start_offset, optlen, "Malformed DNS name record (MS Vista client?)");
1048 /* if len==0 and pos>0 we have read an entire domain string */
1051 /* empty string, this must be an error? */
1052 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Malformed option");
1055 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Domain: %s", domain);
1061 /* add the substring to domain */
1067 /* too long string, this must be an error? */
1068 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Malformed option");
1071 tvb_memcpy(tvb, domain+pos, offset, len);
1079 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Domain: %s", domain);
1083 /* Returns the number of bytes consumed by this option. */
1085 dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree,
1086 gboolean downstream, int off, int eoff, gboolean *at_end)
1092 guint16 temp_optlen = 0;
1094 proto_tree *subtree;
1095 proto_tree *subtree_2;
1097 struct e_in6_addr in6;
1099 guint32 enterprise_no;
1101 /* option type and length must be present */
1102 if (eoff - off < 4) {
1107 opttype = tvb_get_ntohs(tvb, off);
1108 optlen = tvb_get_ntohs(tvb, off + 2);
1110 /* all option data must be present */
1111 if (eoff - off < 4 + optlen) {
1116 ti = proto_tree_add_text(bp_tree, tvb, off, 4 + optlen,
1117 "%s", val_to_str(opttype, opttype_vals, "DHCP option %u"));
1119 subtree = proto_item_add_subtree(ti, ett_dhcpv6_option);
1120 proto_tree_add_item(subtree, hf_option_type, tvb, off, 2, FALSE);
1121 proto_tree_add_item(subtree, hf_option_length, tvb, off + 2, 2, FALSE);
1123 /* Right now, none of the options can be filtered at, so provide a hex
1124 array for minimalistic filtering */
1126 proto_tree_add_item(subtree, hf_option_value, tvb, off, optlen, ENC_NA);
1129 case OPTION_CLIENTID:
1130 col_append_fstr(pinfo->cinfo, COL_INFO, "CID: %s ", tvb_bytes_to_str(tvb, off, optlen));
1132 case OPTION_SERVERID:
1134 proto_tree_add_text(subtree, tvb, off, optlen,
1135 "DUID: malformed option");
1138 proto_item_append_text(ti, ": %s", tvb_bytes_to_str(tvb, off, optlen));
1139 duidtype = tvb_get_ntohs(tvb, off);
1140 proto_tree_add_text(subtree, tvb, off, 2,
1141 "DUID type: %s (%u)",
1142 val_to_str(duidtype,
1143 duidtype_vals, "Unknown"),
1148 proto_tree_add_text(subtree, tvb, off,
1149 optlen, "DUID: malformed option");
1152 hwtype=tvb_get_ntohs(tvb, off + 2);
1153 proto_tree_add_text(subtree, tvb, off + 2, 2,
1154 "Hardware type: %s (%u)", arphrdtype_to_str(hwtype, "Unknown"),
1156 /* Packet specifies seconds since Jan 1 2000, so add 946684800U (30 years) to get back to epoch */
1157 proto_tree_add_text(subtree, tvb, off + 4, 4,
1159 abs_time_secs_to_str(tvb_get_ntohl(tvb, off + 4)+946684800U, ABSOLUTE_TIME_LOCAL, TRUE));
1161 proto_tree_add_text(subtree, tvb, off + 8,
1162 optlen - 8, "Link-layer address: %s",
1163 tvb_arphrdaddr_to_str(tvb, off+8, optlen-8, hwtype));
1168 proto_tree_add_text(subtree, tvb, off,
1169 optlen, "DUID: malformed option");
1172 proto_tree_add_item(subtree, hf_duiden_enterprise, tvb, off + 2, 4, FALSE);
1174 buf = tvb_bytes_to_str(tvb, off + 6, optlen - 6);
1175 proto_tree_add_text(subtree, tvb, off + 6,
1176 optlen - 6, "identifier: %s", buf);
1182 proto_tree_add_text(subtree, tvb, off,
1183 optlen, "DUID: malformed option");
1186 hwtype=tvb_get_ntohs(tvb, off + 2);
1187 proto_tree_add_text(subtree, tvb, off + 2, 2,
1188 "Hardware type: %s (%u)",
1189 arphrdtype_to_str(hwtype, "Unknown"),
1192 proto_tree_add_text(subtree, tvb, off + 4,
1193 optlen - 4, "Link-layer address: %s",
1194 tvb_arphrdaddr_to_str(tvb, off+4, optlen-4, hwtype));
1202 if (opttype == OPTION_IA_NA)
1203 proto_tree_add_text(subtree, tvb, off,
1204 optlen, "IA_NA: malformed option");
1206 proto_tree_add_text(subtree, tvb, off,
1207 optlen, "IA_PD: malformed option");
1210 proto_tree_add_text(subtree, tvb, off, 4,
1212 tvb_arphrdaddr_to_str(tvb, off, 4, opttype));
1213 if (tvb_get_ntohl(tvb, off+4) == DHCPV6_LEASEDURATION_INFINITY) {
1214 proto_tree_add_text(subtree, tvb, off+4, 4,
1217 proto_tree_add_text(subtree, tvb, off+4, 4,
1218 "T1: %u", tvb_get_ntohl(tvb, off+4));
1221 if (tvb_get_ntohl(tvb, off+8) == DHCPV6_LEASEDURATION_INFINITY) {
1222 proto_tree_add_text(subtree, tvb, off+8, 4,
1225 proto_tree_add_text(subtree, tvb, off+8, 4,
1226 "T2: %u", tvb_get_ntohl(tvb, off+8));
1230 while ((optlen - temp_optlen) > 0) {
1231 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1232 off+temp_optlen, off + optlen, at_end);
1234 /* Bad option - just skip to the end */
1235 temp_optlen = optlen;
1241 proto_tree_add_text(subtree, tvb, off,
1242 optlen, "IA_TA: malformed option");
1245 proto_tree_add_text(subtree, tvb, off, 4,
1247 tvb_arphrdaddr_to_str(tvb, off, 4, opttype));
1249 while ((optlen - temp_optlen) > 0) {
1250 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1251 off+temp_optlen, off + optlen, at_end);
1253 /* Bad option - just skip to the end */
1254 temp_optlen = optlen;
1260 guint32 preferred_lifetime, valid_lifetime;
1263 proto_tree_add_text(subtree, tvb, off,
1264 optlen, "IAADDR: malformed option");
1267 tvb_get_ipv6(tvb, off, &in6);
1268 proto_tree_add_text(subtree, tvb, off,
1269 sizeof(in6), "IPv6 address: %s",
1271 col_append_fstr(pinfo->cinfo, COL_INFO, "IAA: %s ", ip6_to_str(&in6));
1272 proto_item_append_text(ti, ": %s", ip6_to_str(&in6));
1274 preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
1275 valid_lifetime = tvb_get_ntohl(tvb, off + 20);
1277 if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1278 proto_tree_add_text(subtree, tvb, off + 16, 4,
1279 "Preferred lifetime: infinity");
1281 proto_tree_add_text(subtree, tvb, off + 16, 4,
1282 "Preferred lifetime: %u", preferred_lifetime);
1284 if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1285 proto_tree_add_text(subtree, tvb, off + 20, 4,
1286 "Valid lifetime: infinity");
1288 proto_tree_add_text(subtree, tvb, off + 20, 4,
1289 "Valid lifetime: %u", valid_lifetime);
1293 while ((optlen - temp_optlen) > 0) {
1294 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1295 off+temp_optlen, off + optlen, at_end);
1297 /* Bad option - just skip to the end */
1298 temp_optlen = optlen;
1305 for (i = 0; i < optlen; i += 2) {
1306 guint16 requested_opt_code;
1307 requested_opt_code = tvb_get_ntohs(tvb, off + i);
1308 proto_tree_add_text(subtree, tvb, off + i,
1309 2, "Requested Option code: %s (%d)",
1310 val_to_str(requested_opt_code,
1313 requested_opt_code);
1316 case OPTION_PREFERENCE:
1318 proto_tree_add_text(subtree, tvb, off,
1319 optlen, "PREFERENCE: malformed option");
1322 proto_tree_add_text(subtree, tvb, off, 1,
1324 (guint32)tvb_get_guint8(tvb, off));
1326 case OPTION_ELAPSED_TIME:
1328 proto_tree_add_text(subtree, tvb, off,
1329 optlen, "ELAPSED-TIME: malformed option");
1332 proto_tree_add_text(subtree, tvb, off, 2,
1333 "elapsed-time: %u ms",
1334 10*(guint32)tvb_get_ntohs(tvb, off));
1336 case OPTION_RELAY_MSG:
1338 proto_tree_add_text(subtree, tvb, off,
1339 optlen, "RELAY-MSG: malformed option");
1341 /* here, we should dissect a full DHCP message */
1342 dissect_dhcpv6(tvb, pinfo, subtree, downstream, off, off + optlen);
1347 proto_tree_add_text(subtree, tvb, off,
1348 optlen, "AUTH: malformed option");
1351 proto_tree_add_text(subtree, tvb, off, 1,
1353 (guint32)tvb_get_guint8(tvb, off));
1354 proto_tree_add_text(subtree, tvb, off+1, 1,
1356 (guint32)tvb_get_guint8(tvb, off+1));
1357 proto_tree_add_text(subtree, tvb, off+2, 1,
1359 (guint32)tvb_get_guint8(tvb, off+2));
1360 proto_tree_add_text(subtree, tvb, off+3, 8,
1361 "Replay Detection");
1363 proto_tree_add_text(subtree, tvb, off+11, optlen-11,
1364 "Authentication Information");
1366 case OPTION_UNICAST:
1368 proto_tree_add_text(subtree, tvb, off,
1369 optlen, "UNICAST: malformed option");
1372 tvb_get_ipv6(tvb, off, &in6);
1373 proto_tree_add_text(subtree, tvb, off,
1374 sizeof(in6), "IPv6 address: %s",
1377 case OPTION_STATUS_CODE:
1379 guint16 status_code;
1380 char *status_message = 0;
1381 status_code = tvb_get_ntohs(tvb, off);
1382 proto_tree_add_text(subtree, tvb, off, 2,
1383 "Status Code: %s (%d)",
1384 val_to_str(status_code, statuscode_vals,
1388 if (optlen - 2 > 0) {
1389 status_message = tvb_get_ephemeral_string(tvb, off + 2, optlen - 2);
1390 proto_tree_add_text(subtree, tvb, off + 2, optlen - 2,
1391 "Status Message: %s",
1396 case OPTION_VENDOR_CLASS:
1398 proto_tree_add_text(subtree, tvb, off,
1399 optlen, "VENDOR_CLASS: malformed option");
1402 proto_tree_add_item(subtree, hf_vendorclass_enterprise, tvb, off, 4, FALSE);
1404 proto_tree_add_text(subtree, tvb, off+6, optlen-6,
1405 "vendor-class-data: \"%s\"", tvb_format_stringzpad(tvb, off + 6, optlen - 6));
1408 case OPTION_VENDOR_OPTS:
1410 proto_tree_add_text(subtree, tvb, off,
1411 optlen, "VENDOR_OPTS: malformed option");
1415 enterprise_no = tvb_get_ntohl(tvb, off);
1416 proto_tree_add_item(subtree, hf_vendoropts_enterprise, tvb, off, 4, FALSE);
1419 if (enterprise_no == 4491) {
1420 dissect_cablelabs_specific_opts(subtree, tvb, off+4, optlen-4);
1424 while((optlen - 4 - optoffset) > 0) {
1425 int olen = tvb_get_ntohs(tvb, off + optoffset + 6);
1426 ti = proto_tree_add_text(subtree, tvb, off + optoffset + 4,
1427 4 + olen, "option");
1428 subtree_2 = proto_item_add_subtree(ti, ett_dhcpv6_option_vsoption);
1430 proto_tree_add_text(subtree_2, tvb, off + optoffset + 4, 2,
1431 "option code: %u", tvb_get_ntohs(tvb, off + optoffset + 4));
1432 proto_tree_add_text(subtree_2, tvb, off + optoffset + 6, 2,
1433 "option length: %u", olen);
1434 proto_tree_add_text(subtree_2, tvb, off + optoffset + 8, olen,
1436 optoffset += (4 + olen);
1441 case OPTION_INTERFACE_ID:
1446 proto_tree_add_text(subtree, tvb, off,
1447 optlen, "INTERFACE_ID: malformed option");
1451 namelen = tvb_strnlen(tvb, off, optlen)+1;
1454 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1455 proto_tree_add_text(subtree, tvb, off, optlen, "Interface-ID: %s", buf);
1457 buf = tvb_get_ephemeral_string(tvb, off, namelen-1);
1458 proto_tree_add_text(subtree, tvb, off, namelen, "Interface-ID: %s", buf);
1460 temp_optlen = optlen - namelen;
1462 if (temp_optlen >= 6)
1463 proto_tree_add_text(subtree, tvb, off,
1464 temp_optlen, "Link-layer address: %s",
1465 tvb_arphrdaddr_to_str(tvb, off, 6, ARPHRD_ETHER));
1469 case OPTION_RECONF_MSG:
1471 proto_tree_add_text(subtree, tvb, off,
1472 optlen, "RECONF_MSG: malformed option");
1475 proto_tree_add_text(subtree, tvb, off, optlen,
1476 "Reconfigure-type: %s",
1477 val_to_str(tvb_get_guint8(tvb, off),
1479 "Message Type %u"));
1481 case OPTION_SIP_SERVER_D:
1483 proto_tree_add_text(subtree, tvb, off, optlen,
1484 "SIP Servers Domain Search List");
1486 dhcpv6_domain(subtree,tvb, off, optlen);
1488 case OPTION_SIP_SERVER_A:
1490 proto_tree_add_text(subtree, tvb, off, optlen,
1491 "SIP servers address: malformed option");
1494 for (i = 0; i < optlen; i += 16) {
1495 tvb_get_ipv6(tvb, off + i, &in6);
1496 proto_tree_add_text(subtree, tvb, off + i,
1497 sizeof(in6), "SIP servers address: %s",
1501 case OPTION_DNS_SERVERS:
1503 proto_tree_add_text(subtree, tvb, off, optlen,
1504 "DNS servers address: malformed option");
1507 for (i = 0; i < optlen; i += 16) {
1508 tvb_get_ipv6(tvb, off + i, &in6);
1509 proto_tree_add_text(subtree, tvb, off + i,
1510 sizeof(in6), "DNS servers address: %s",
1514 case OPTION_DOMAIN_LIST:
1516 proto_tree_add_text(subtree, tvb, off, optlen, "DNS Domain Search List");
1518 dhcpv6_domain(subtree,tvb, off, optlen);
1520 case OPTION_NIS_SERVERS:
1522 proto_tree_add_text(subtree, tvb, off, optlen,
1523 "NIS servers address: malformed option");
1526 for (i = 0; i < optlen; i += 16) {
1527 tvb_get_ipv6(tvb, off + i, &in6);
1528 proto_tree_add_text(subtree, tvb, off + i,
1529 sizeof(in6), "NIS servers address: %s",
1533 case OPTION_NISP_SERVERS:
1535 proto_tree_add_text(subtree, tvb, off, optlen,
1536 "NISP servers address: malformed option");
1539 for (i = 0; i < optlen; i += 16) {
1540 tvb_get_ipv6(tvb, off + i, &in6);
1541 proto_tree_add_text(subtree, tvb, off + i,
1542 sizeof(in6), "NISP servers address: %s",
1546 case OPTION_NIS_DOMAIN_NAME:
1548 proto_tree_add_text(subtree, tvb, off, optlen, "nis-domain-name");
1550 dhcpv6_domain(subtree,tvb, off, optlen);
1552 case OPTION_NISP_DOMAIN_NAME:
1554 proto_tree_add_text(subtree, tvb, off, optlen, "nisp-domain-name");
1556 dhcpv6_domain(subtree,tvb, off, optlen);
1558 case OPTION_SNTP_SERVERS:
1560 proto_tree_add_text(subtree, tvb, off, optlen,
1561 "SNTP servers address: malformed option");
1564 for (i = 0; i < optlen; i += 16) {
1565 tvb_get_ipv6(tvb, off + i, &in6);
1566 proto_tree_add_text(subtree, tvb, off + i,
1567 sizeof(in6), "SNTP servers address: %s",
1571 case OPTION_LIFETIME:
1573 proto_tree_add_text(subtree, tvb, off,
1574 optlen, "LIFETIME: malformed option");
1577 proto_tree_add_text(subtree, tvb, off, 4,
1579 (guint32)tvb_get_ntohl(tvb, off));
1581 case OPTION_BCMCS_SERVER_D:
1583 proto_tree_add_text(subtree, tvb, off, optlen,
1584 "BCMCS Servers Domain Search List");
1586 dhcpv6_domain(subtree,tvb, off, optlen);
1588 case OPTION_BCMCS_SERVER_A:
1590 proto_tree_add_text(subtree, tvb, off, optlen,
1591 "BCMCS servers address: malformed option");
1594 for (i = 0; i < optlen; i += 16) {
1595 tvb_get_ipv6(tvb, off + i, &in6);
1596 proto_tree_add_text(subtree, tvb, off + i,
1597 sizeof(in6), "BCMCS servers address: %s",
1601 case OPTION_REMOTE_ID:
1603 proto_tree_add_text(subtree, tvb, off,
1604 optlen, "REMOTE_ID: malformed option");
1607 proto_tree_add_item(subtree, hf_remoteid_enterprise, tvb, off, 4, FALSE);
1609 buf = tvb_bytes_to_str(tvb, off, optlen - 4);
1610 proto_tree_add_text(subtree, tvb, off, optlen - 4, "Remote-ID: %s", buf);
1612 case OPTION_SUBSCRIBER_ID:
1614 proto_tree_add_text(subtree, tvb, off,
1615 optlen, "SUBSCRIBER_ID: malformed option");
1618 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1619 proto_tree_add_text(subtree, tvb, off, optlen, "Subscriber-ID: %s", buf);
1621 case OPTION_CLIENT_FQDN:
1623 proto_tree_add_text(subtree, tvb, off,
1624 optlen, "FQDN: malformed option");
1631 proto_tree_add_item(subtree, hf_clientfqdn_reserved, tvb, off, 1, FALSE);
1632 proto_tree_add_item(subtree, hf_clientfqdn_n, tvb, off, 1, FALSE);
1633 proto_tree_add_item(subtree, hf_clientfqdn_o, tvb, off, 1, FALSE);
1634 proto_tree_add_item(subtree, hf_clientfqdn_s, tvb, off, 1, FALSE);
1636 dhcpv6_domain(subtree, tvb, off+1, optlen-1);
1639 case OPTION_PANA_AGENT:
1641 proto_tree_add_text(subtree, tvb, off, optlen,
1642 "PANA agent address: malformed option");
1645 for (i = 0; i < optlen; i += 16) {
1646 tvb_get_ipv6(tvb, off + i, &in6);
1647 proto_tree_add_text(subtree, tvb, off + i,
1648 sizeof(in6), "PANA agents address: %s",
1652 case OPTION_TIME_ZONE:
1654 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1655 proto_tree_add_text(subtree, tvb, off, optlen, "time-zone: %s", buf);
1660 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1661 proto_tree_add_text(subtree, tvb, off, optlen, "tz-database: %s", buf);
1664 case OPTION_LQ_QUERY:
1667 struct e_in6_addr in6_local;
1670 proto_tree_add_text(subtree, tvb, off, optlen,
1671 "LQ-QUERY: malformed option");
1674 query_type = tvb_get_guint8(tvb, off);
1675 switch (query_type) {
1677 proto_tree_add_text(subtree, tvb, off, 1,
1678 "Query-type: %s (%u)",
1679 "by-address", query_type);
1682 proto_tree_add_text(subtree, tvb, off, 1,
1683 "Query-type: %s (%u)",
1684 "by-clientID", query_type);
1687 proto_tree_add_text(subtree, tvb, off, 1,
1688 "Query-type: %s (%u)",
1689 "unknown?", query_type);
1692 tvb_get_ipv6(tvb, off + 1, &in6_local);
1693 proto_tree_add_text(subtree, tvb, off + 1, 16,
1694 "Link address: %s", ip6_to_str(&in6_local));
1696 while ((optlen - temp_optlen) > 0) {
1697 temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
1698 downstream, off + temp_optlen,
1699 off + optlen, at_end);
1701 /* Bad option - just skip to the end */
1702 temp_optlen = optlen;
1707 case OPTION_CLIENT_DATA:
1709 while ((optlen - temp_optlen) > 0) {
1710 temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
1711 downstream, off + temp_optlen,
1712 off + optlen, at_end);
1714 /* Bad option - just skip to the end */
1715 temp_optlen = optlen;
1719 case OPTION_CLT_TIME:
1721 proto_tree_add_text(subtree, tvb, off, optlen,
1722 "CLT_TIME: malformed option");
1725 proto_tree_add_text(subtree, tvb, off, 4,
1727 (guint32)tvb_get_ntohl(tvb, off));
1729 case OPTION_LQ_RELAY_DATA:
1731 proto_tree_add_text(subtree, tvb, off, optlen,
1732 "LQ_RELAY_DATA: malformed option");
1735 tvb_get_ipv6(tvb, off, &in6);
1736 proto_tree_add_text(subtree, tvb, off, 16,
1737 "Peer address: %s", ip6_to_str(&in6));
1738 proto_tree_add_text(subtree, tvb, off + 16, optlen - 16,
1739 "DHCPv6 relay message");
1741 case OPTION_LQ_CLIENT_LINK:
1743 proto_tree_add_text(subtree, tvb, off, optlen,
1744 "LQ client links address: malformed option");
1747 for (i = 0; i < optlen; i += 16) {
1748 tvb_get_ipv6(tvb, off + i, &in6);
1749 proto_tree_add_text(subtree, tvb, off + i,
1750 sizeof(in6), "LQ client links address: %s",
1754 case OPTION_CAPWAP_AC_V6:
1756 proto_tree_add_text(subtree, tvb, off, optlen,
1757 "CAPWAP Access Controllers address: malformed option");
1760 for (i = 0; i < optlen; i += 16) {
1761 tvb_get_ipv6(tvb, off + i, &in6);
1762 proto_tree_add_text(subtree, tvb, off + i,
1763 sizeof(in6), "CAPWAP Access Controllers address: %s",
1767 case OPTION_AFTR_NAME:
1769 const guchar *dns_name;
1770 get_dns_name(tvb, off, optlen, off, &dns_name);
1771 proto_tree_add_text(subtree, tvb, off, optlen,
1772 "DS-Lite AFTR Name: %s", dns_name);
1775 case OPTION_IAPREFIX:
1777 guint32 preferred_lifetime, valid_lifetime;
1778 guint8 prefix_length;
1779 struct e_in6_addr in6_local;
1782 proto_tree_add_text(subtree, tvb, off,
1783 optlen, "IAPREFIX: malformed option");
1787 preferred_lifetime = tvb_get_ntohl(tvb, off);
1788 valid_lifetime = tvb_get_ntohl(tvb, off + 4);
1789 prefix_length = tvb_get_guint8(tvb, off + 8);
1790 if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1791 proto_tree_add_text(subtree, tvb, off, 4,
1792 "Preferred lifetime: infinity");
1794 proto_tree_add_text(subtree, tvb, off, 4,
1795 "Preferred lifetime: %u", preferred_lifetime);
1797 if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1798 proto_tree_add_text(subtree, tvb, off + 4, 4,
1799 "Valid lifetime: infinity");
1801 proto_tree_add_text(subtree, tvb, off + 4, 4,
1802 "Valid lifetime: %u", valid_lifetime);
1804 proto_tree_add_text(subtree, tvb, off + 8, 1,
1805 "Prefix length: %d", prefix_length);
1806 tvb_get_ipv6(tvb, off + 9, &in6_local);
1807 proto_tree_add_text(subtree, tvb, off + 9,
1808 16, "Prefix address: %s",
1809 ip6_to_str(&in6_local));
1812 while ((optlen - temp_optlen) > 0) {
1813 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1814 off+temp_optlen, off + optlen, at_end);
1816 /* Bad option - just skip to the end */
1817 temp_optlen = optlen;
1822 case OPTION_MIP6_HA:
1824 proto_tree_add_text(subtree, tvb, off, optlen,
1825 "MIP6_HA: malformed option");
1829 tvb_get_ipv6(tvb, off, &in6);
1830 proto_tree_add_text(subtree, tvb, off,
1831 16, "Home Agent: %s", ip6_to_str(&in6));
1833 case OPTION_MIP6_HOA:
1835 proto_tree_add_text(subtree, tvb, off, optlen,
1836 "MIP6_HOA: malformed option");
1840 tvb_get_ipv6(tvb, off, &in6);
1841 proto_tree_add_text(subtree, tvb, off,
1842 16, "Home Address: %s", ip6_to_str(&in6));
1846 proto_tree_add_text(subtree, tvb, off, optlen,
1847 "NAI: malformed option");
1850 proto_tree_add_text(subtree, tvb, off, optlen,
1851 "NAI : %s", tvb_get_ephemeral_string(tvb, off, optlen - 2));
1860 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1861 gboolean downstream, int off, int eoff)
1863 proto_tree *bp_tree = NULL;
1867 struct e_in6_addr in6;
1869 msgtype = tvb_get_guint8(tvb, off);
1871 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msgtype, msgtype_vals, "Message Type %u"));
1874 ti = proto_tree_add_item(tree, proto_dhcpv6, tvb, off, eoff - off, FALSE);
1875 bp_tree = proto_item_add_subtree(ti, ett_dhcpv6);
1879 if (msgtype == RELAY_FORW || msgtype == RELAY_REPLY) {
1881 proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, FALSE);
1882 proto_tree_add_item(bp_tree, hf_dhcpv6_hopcount, tvb, off + 1, 1, FALSE);
1883 proto_tree_add_item(bp_tree, hf_dhcpv6_linkaddr, tvb, off + 2, 16, FALSE);
1884 tvb_get_ipv6(tvb, off + 2, &in6);
1885 col_append_fstr(pinfo->cinfo, COL_INFO, "L: %s ", ip6_to_str(&in6));
1886 proto_tree_add_item(bp_tree, hf_dhcpv6_peeraddr, tvb, off + 18, 16, FALSE);
1891 proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, FALSE);
1892 proto_tree_add_item(bp_tree, hf_dhcpv6_xid, tvb, off + 1, 3, FALSE);
1894 col_append_fstr(pinfo->cinfo, COL_INFO, "XID: 0x%x ", tvb_get_ntoh24(tvb, off + 1));
1899 while (off < eoff && !at_end)
1900 off += dhcpv6_option(tvb, pinfo, bp_tree, downstream, off, eoff, &at_end);
1904 dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1906 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
1907 col_clear(pinfo->cinfo, COL_INFO);
1908 dissect_dhcpv6(tvb, pinfo, tree, TRUE, 0, tvb_reported_length(tvb));
1912 dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1914 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
1915 col_clear(pinfo->cinfo, COL_INFO);
1916 dissect_dhcpv6(tvb, pinfo, tree, FALSE, 0, tvb_reported_length(tvb));
1921 proto_register_dhcpv6(void)
1923 static hf_register_info hf[] = {
1926 { &hf_dhcpv6_msgtype,
1927 { "Message type", "dhcpv6.msgtype", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0x0, NULL, HFILL }},
1928 { &hf_dhcpv6_hopcount,
1929 { "Hopcount", "dhcpv6.hopcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1931 { "Transaction ID", "dhcpv6.xid", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL}},
1932 { &hf_dhcpv6_linkaddr,
1933 { "Link address", "dhcpv6.linkaddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
1934 { &hf_dhcpv6_peeraddr,
1935 { "Peer address", "dhcpv6.peeraddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
1936 /* Generic option stuff */
1938 { "Option", "dhcpv6.option.type", FT_UINT16, BASE_DEC, VALS(opttype_vals), 0x0, NULL, HFILL}},
1939 { &hf_option_length,
1940 { "Length", "dhcpv6.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1942 { "Value", "dhcpv6.option.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1943 /* Individual options */
1944 { &hf_clientfqdn_reserved,
1945 { "Reserved", "dhcpv6.clientfqdn.reserved", FT_UINT8, BASE_HEX, NULL, 0xF8, NULL, HFILL}},
1947 { "N bit", "dhcpv6.clientfqdn.n", FT_BOOLEAN, 8, TFS(&fqdn_n), 0x4, "Whether the server SHOULD NOT perform any DNS updates", HFILL}},
1949 { "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}},
1951 { "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}},
1952 { &hf_remoteid_enterprise,
1953 { "Enterprise ID", "dhcpv6.remoteid.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "RemoteID Enterprise Number", HFILL }},
1954 { &hf_vendoropts_enterprise,
1955 { "Enterprise ID", "dhcpv6.vendoropts.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "Vendor opts Enterprise Number", HFILL }},
1956 { &hf_vendorclass_enterprise,
1957 { "Enterprise ID", "dhcpv6.vendorclass.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "Vendor Class Enterprise Number", HFILL }},
1958 { &hf_duiden_enterprise,
1959 { "Enterprise ID", "dhcpv6.duiden.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &sminmpec_values_ext, 0, "DUID EN Enterprise Number", HFILL }},
1962 static gint *ett[] = {
1965 &ett_dhcpv6_option_vsoption,
1966 &ett_dhcpv6_vendor_option,
1967 &ett_dhcpv6_pkt_option,
1970 proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
1971 proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
1972 proto_register_subtree_array(ett, array_length(ett));
1974 /* Allow other dissectors to find this one by name.
1975 Just choose upstream version for now as they are identical. */
1976 register_dissector("dhcpv6", dissect_dhcpv6_upstream, proto_dhcpv6);
1980 proto_reg_handoff_dhcpv6(void)
1982 dissector_handle_t dhcpv6_handle;
1984 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_downstream,
1986 dissector_add_uint("udp.port", UDP_PORT_DHCPV6_DOWNSTREAM, dhcpv6_handle);
1987 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_upstream,
1989 dissector_add_uint("udp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_handle);