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 * draft-ietf-dhc-dhcpv6-opt-timeconfig-03.txt
21 * draft-ietf-dhc-dhcpv6-opt-lifetime-00.txt
23 * Note that protocol constants are still subject to change, based on IANA
24 * assignment decisions.
26 * Wireshark - Network traffic analyzer
27 * By Gerald Combs <gerald@wireshark.org>
28 * Copyright 1998 Gerald Combs
30 * This program is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU General Public License
32 * as published by the Free Software Foundation; either version 2
33 * of the License, or (at your option) any later version.
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50 #include <epan/packet.h>
51 #include <epan/sminmpec.h>
52 #include <epan/strutil.h>
53 #include "packet-arp.h"
55 static int proto_dhcpv6 = -1;
56 static int hf_dhcpv6_msgtype = -1;
57 static int hf_clientfqdn_reserved = -1;
58 static int hf_clientfqdn_n = -1;
59 static int hf_clientfqdn_o = -1;
60 static int hf_clientfqdn_s = -1;
61 static int hf_option_type = -1;
62 static int hf_option_length = -1;
63 static int hf_option_value = -1;
64 static int hf_remoteid_enterprise = -1;
65 static int hf_vendoropts_enterprise = -1;
66 static int hf_duiden_enterprise = -1;
67 static int hf_vendorclass_enterprise = -1;
68 static int hf_dhcpv6_hopcount = -1;
69 static int hf_dhcpv6_xid = -1;
70 static int hf_dhcpv6_peeraddr = -1;
71 static int hf_dhcpv6_linkaddr = -1;
73 static gint ett_dhcpv6 = -1;
74 static gint ett_dhcpv6_option = -1;
75 static gint ett_dhcpv6_option_vsoption = -1;
76 static gint ett_dhcpv6_vendor_option = -1;
77 static gint ett_dhcpv6_pkt_option = -1;
79 #define UDP_PORT_DHCPV6_DOWNSTREAM 546
80 #define UDP_PORT_DHCPV6_UPSTREAM 547
82 #define DHCPV6_LEASEDURATION_INFINITY 0xffffffff
93 #define RECONFIGURE 10
94 #define INFORMATION_REQUEST 11
96 #define RELAY_REPLY 13
98 #define LEASEQUERY_REPLY 15
100 #define OPTION_CLIENTID 1
101 #define OPTION_SERVERID 2
102 #define OPTION_IA_NA 3
103 #define OPTION_IA_TA 4
104 #define OPTION_IAADDR 5
106 #define OPTION_PREFERENCE 7
107 #define OPTION_ELAPSED_TIME 8
108 #define OPTION_RELAY_MSG 9
109 /* #define OPTION_SERVER_MSG 10 */
110 #define OPTION_AUTH 11
111 #define OPTION_UNICAST 12
112 #define OPTION_STATUS_CODE 13
113 #define OPTION_RAPID_COMMIT 14
114 #define OPTION_USER_CLASS 15
115 #define OPTION_VENDOR_CLASS 16
116 #define OPTION_VENDOR_OPTS 17
117 #define OPTION_INTERFACE_ID 18
118 #define OPTION_RECONF_MSG 19
119 #define OPTION_RECONF_ACCEPT 20
120 #define OPTION_SIP_SERVER_D 21
121 #define OPTION_SIP_SERVER_A 22
122 #define OPTION_DNS_SERVERS 23
123 #define OPTION_DOMAIN_LIST 24
124 #define OPTION_IA_PD 25
125 #define OPTION_IAPREFIX 26
126 #define OPTION_NIS_SERVERS 27
127 #define OPTION_NISP_SERVERS 28
128 #define OPTION_NIS_DOMAIN_NAME 29
129 #define OPTION_NISP_DOMAIN_NAME 30
130 #define OPTION_SNTP_SERVERS 31
131 #define OPTION_LIFETIME 32
132 #define OPTION_BCMCS_SERVER_D 33
133 #define OPTION_BCMCS_SERVER_A 34
134 #define OPTION_GEOCONF_CIVIC 36
135 #define OPTION_REMOTE_ID 37
136 #define OPTION_SUBSCRIBER_ID 38
137 #define OPTION_CLIENT_FQDN 39
138 #define OPTION_PANA_AGENT 40
139 #define OPTION_TIME_ZONE 41
140 #define OPTION_TZDB 42
141 #define OPTION_ERO 43
142 #define OPTION_LQ_QUERY 44
143 #define OPTION_CLIENT_DATA 45
144 #define OPTION_CLT_TIME 46
145 #define OPTION_LQ_RELAY_DATA 47
146 #define OPTION_LQ_CLIENT_LINK 48
147 #define OPTION_CAPWAP_AC_V6 52
149 /* temporary value until defined by IETF */
150 #define OPTION_MIP6_HA 165
151 #define OPTION_MIP6_HOA 166
152 #define OPTION_NAI 167
157 #define DUID_LL_OLD 4
159 static const value_string msgtype_vals[] = {
160 { SOLICIT, "Solicit" },
161 { ADVERTISE, "Advertise" },
162 { REQUEST, "Request" },
163 { CONFIRM, "Confirm" },
165 { REBIND, "Rebind" },
167 { RELEASE, "Release" },
168 { DECLINE, "Decline" },
169 { RECONFIGURE, "Reconfigure" },
170 { INFORMATION_REQUEST, "Information-request" },
171 { RELAY_FORW, "Relay-forw" },
172 { RELAY_REPLY, "Relay-reply" },
173 { LEASEQUERY, "Leasequery" },
174 { LEASEQUERY_REPLY, "Leasequery-reply" },
178 static const value_string opttype_vals[] = {
179 { OPTION_CLIENTID, "Client Identifier" },
180 { OPTION_SERVERID, "Server Identifier" },
181 { OPTION_IA_NA, "Identity Association for Non-temporary Address" },
182 { OPTION_IA_TA, "Identity Association for Temporary Address" },
183 { OPTION_IAADDR, "IA Address" },
184 { OPTION_ORO, "Option Request" },
185 { OPTION_PREFERENCE, "Preference" },
186 { OPTION_ELAPSED_TIME, "Elapsed time" },
187 { OPTION_RELAY_MSG, "Relay Message" },
188 /* { OPTION_SERVER_MSG, "Server message" }, */
189 { OPTION_AUTH, "Authentication" },
190 { OPTION_UNICAST, "Server unicast" },
191 { OPTION_STATUS_CODE, "Status code" },
192 { OPTION_RAPID_COMMIT, "Rapid Commit" },
193 { OPTION_USER_CLASS, "User Class" },
194 { OPTION_VENDOR_CLASS, "Vendor Class" },
195 { OPTION_VENDOR_OPTS, "Vendor-specific Information" },
196 { OPTION_INTERFACE_ID, "Interface-Id" },
197 { OPTION_RECONF_MSG, "Reconfigure Message" },
198 { OPTION_RECONF_ACCEPT, "Reconfigure Accept" },
199 { OPTION_SIP_SERVER_D, "SIP Server Domain Name List" },
200 { OPTION_SIP_SERVER_A, "SIP Servers IPv6 Address List" },
201 { OPTION_DNS_SERVERS, "DNS recursive name server" },
202 { OPTION_DOMAIN_LIST, "Domain Search List" },
203 { OPTION_IA_PD, "Identity Association for Prefix Delegation" },
204 { OPTION_IAPREFIX, "IA Prefix" },
205 { OPTION_NIS_SERVERS, "Network Information Server" },
206 { OPTION_NISP_SERVERS, "Network Information Server V2" },
207 { OPTION_NIS_DOMAIN_NAME, "Network Information Server Domain Name" },
208 { OPTION_NISP_DOMAIN_NAME,"Network Information Server V2 Domain Name" },
209 { OPTION_SNTP_SERVERS, "Simple Network Time Protocol Server" },
210 { OPTION_LIFETIME, "Lifetime" },
211 { OPTION_BCMCS_SERVER_D, "BCMCS Server Domain" },
212 { OPTION_BCMCS_SERVER_A, "BCMCS Servers IPv6 Address List" },
213 { OPTION_GEOCONF_CIVIC, "Geoconf Civic Address" },
214 { OPTION_REMOTE_ID, "Remote Identifier" },
215 { OPTION_SUBSCRIBER_ID, "Subscriber Identifier" },
216 { OPTION_CLIENT_FQDN, "Fully Qualified Domain Name" },
217 { OPTION_PANA_AGENT, "PANA Agents IPv6 Address List" },
218 { OPTION_TIME_ZONE, "Time Zone" },
219 { OPTION_TZDB, "Time Zone Database" },
220 { OPTION_ERO, "Echo Request Option" },
221 { OPTION_LQ_QUERY, "Leasequery Query" },
222 { OPTION_CLIENT_DATA, "Leasequery Client Data" },
223 { OPTION_CLT_TIME, "Client Last Transaction Time" },
224 { OPTION_LQ_RELAY_DATA, "Leasequery Relay Data" },
225 { OPTION_LQ_CLIENT_LINK, "Leasequery Client Link Address List" },
226 { OPTION_CAPWAP_AC_V6, "CAPWAP Access Controllers" },
227 { OPTION_MIP6_HA, "Mobile IPv6 Home Agent" },
228 { OPTION_MIP6_HOA, "Mobile IPv6 Home Address" },
229 { OPTION_NAI, "Network Access Identifier" },
233 static const value_string statuscode_vals[] =
240 {5, "UseMulticast" },
241 {6, "NoPrefixAvail" },
242 {7, "UnknownQueryType" },
243 {8, "MalformedQuery" },
244 {9, "NotConfigured" },
249 static const value_string duidtype_vals[] =
251 { DUID_LLT, "link-layer address plus time" },
252 { DUID_EN, "assigned by vendor based on Enterprise number" },
253 { DUID_LL, "link-layer address" },
254 { DUID_LL_OLD, "link-layer address (old)" },
258 /* This FQDN draft is a mess, I've tried to understand,
259 but N,O,S bit descriptions are really cryptic */
260 static const true_false_string fqdn_n = {
261 /* "Client doesn't want server to perform DNS update", "" */
262 "N bit set","N bit cleared"
265 static const true_false_string fqdn_o = {
266 "O bit set", "O bit cleared"
269 static const true_false_string fqdn_s = {
270 /* "Forward mapping (FQDN-to-IPv6, AAAA) performed by client",
271 "Forward mapping (FQDN-to-IPv6, AAAA) performed by server" */
272 "S bit set", "S bit cleared"
275 /* CableLabs Common Vendor Specific Options */
276 #define CL_OPTION_ORO 0x0001 /* 1 */
277 #define CL_OPTION_DEVICE_TYPE 0x0002 /* 2 */
278 #define CL_OPTION_EMBEDDED_COMPONENT_LIST 0x0003 /* 3 */
279 #define CL_OPTION_DEVICE_SERIAL_NUMBER 0x0004 /* 4 */
280 #define CL_OPTION_HARDWARE_VERSION_NUMBER 0x0005 /* 5 */
281 #define CL_OPTION_SOFTWARE_VERSION_NUMBER 0x0006 /* 6 */
282 #define CL_OPTION_BOOT_ROM_VERSION 0x0007 /* 7 */
283 #define CL_OPTION_VENDOR_OUI 0x0008 /* 8 */
284 #define CL_OPTION_MODEL_NUMBER 0x0009 /* 9 */
285 #define CL_OPTION_VENDOR_NAME 0x000a /* 10 */
286 /* 11-32 is currently reserved */
287 #define CL_OPTION_TFTP_SERVERS 0x0020 /* 32 */
288 #define CL_OPTION_CONFIG_FILE_NAME 0x0021 /* 33 */
289 #define CL_OPTION_SYSLOG_SERVERS 0x0022 /* 34 */
290 #define CL_OPTION_TLV5 0x0023 /* 35 */
291 #define CL_OPTION_DEVICE_ID 0x0024 /* 36 */
292 #define CL_OPTION_RFC868_SERVERS 0x0025 /* 37 */
293 #define CL_OPTION_TIME_OFFSET 0x0026 /* 38 */
295 /** CableLabs DOCSIS Project Vendor Specific Options */
296 #define CL_OPTION_DOCS_CMTS_CAP 0x0401 /* 1025 */
297 #define CL_CM_MAC_ADDR 0x0402 /* 1026 */
298 #define CL_EROUTER_CONTAINER_OPTION 0x403 /* 1027 */
300 /** CableLabs PacketCable Project Vendor Specific Options **/
301 #define CL_OPTION_CCC 0x087a /* 2170 */
303 /** CableLabs TLVs for DOCS_CMTS_CAP Vendor Option **/
304 #define CL_OPTION_DOCS_CMTS_TLV_VERS_NUM 0x01 /* 1 */
306 static const value_string cl_vendor_subopt_values[] = {
307 /* 1 */ { CL_OPTION_ORO, "Option Request = " },
308 /* 2 */ { CL_OPTION_DEVICE_TYPE, "Device Type = " },
309 /* 3 */ { CL_OPTION_EMBEDDED_COMPONENT_LIST, "Embedded Components = " },
310 /* 4 */ { CL_OPTION_DEVICE_SERIAL_NUMBER, "Serial Number = " },
311 /* 5 */ { CL_OPTION_HARDWARE_VERSION_NUMBER, "Hardware Version = " },
312 /* 6 */ { CL_OPTION_SOFTWARE_VERSION_NUMBER, "Software Version = " },
313 /* 7 */ { CL_OPTION_BOOT_ROM_VERSION, "Boot ROM Version = " },
314 /* 8 */ { CL_OPTION_VENDOR_OUI, "Organization Unique Identifier = " },
315 /* 9 */ { CL_OPTION_MODEL_NUMBER, "Model Number = " },
316 /* 10 */ { CL_OPTION_VENDOR_NAME, "Vendor Name = " },
317 /* 32 */ { CL_OPTION_TFTP_SERVERS, "TFTP Server Addresses : " },
318 /* 33 */ { CL_OPTION_CONFIG_FILE_NAME, "Configuration File Name = " },
319 /* 34 */ { CL_OPTION_SYSLOG_SERVERS, "Syslog Servers : " },
320 /* 35 */ { CL_OPTION_TLV5, "TLV5 = " },
321 /* 36 */ { CL_OPTION_DEVICE_ID, "Device Identifier = " },
322 /* 37 */ { CL_OPTION_RFC868_SERVERS, "Time Protocol Servers : " },
323 /* 38 */ { CL_OPTION_TIME_OFFSET, "Time Offset = " },
324 /* 1025 */ {CL_OPTION_DOCS_CMTS_CAP, "CMTS Capabilities Option : " },
325 /* 1026 */ {CL_CM_MAC_ADDR, "CM MAC Address Option = " },
326 /* 1027 */ {CL_EROUTER_CONTAINER_OPTION, "eRouter Container Option : " },
327 /* 2170 */ {CL_OPTION_CCC, "CableLabs Client Configuration : " },
331 #define PKT_CCC_PRI_DHCP 0x0001
332 #define PKT_CCC_SEC_DHCP 0x0002
333 #define PKT_CCC_IETF_PROV_SRV 0x0003
334 #define PKT_CCC_IETF_AS_KRB 0x0004
335 #define PKT_CCC_IETF_AP_KRB 0x0005
336 #define PKT_CCC_KRB_REALM 0x0006
337 #define PKT_CCC_TGT_FLAG 0x0007
338 #define PKT_CCC_PROV_TIMER 0x0008
339 #define PKT_CCC_IETF_SEC_TKT 0x0009
340 /** 10 -255 Reservered for future extensions **/
342 static const value_string pkt_ccc_opt_vals[] = {
343 { PKT_CCC_PRI_DHCP, "TSP's Primary DHCP Server" },
344 { PKT_CCC_SEC_DHCP, "TSP's Secondary DHCP Server" },
345 { PKT_CCC_IETF_PROV_SRV, "TSP's Provisioning Server" },
346 { PKT_CCC_IETF_AS_KRB, "TSP's AS-REQ/AS-REP Backoff and Retry" },
347 { PKT_CCC_IETF_AP_KRB, "TSP's AP-REQ/AP-REP Backoff and Retry" },
348 { PKT_CCC_KRB_REALM, "TSP's Kerberos Realm Name" },
349 { PKT_CCC_TGT_FLAG, "TSP's Ticket Granting Server Utilization" },
350 { PKT_CCC_PROV_TIMER, "TSP's Provisioning Timer Value" },
351 { PKT_CCC_IETF_SEC_TKT, "PacketCable Security Ticket Control" },
355 static const value_string sec_tcm_vals[] = {
356 { 1 << 0, "PacketCable Provisioning Server" },
357 { 1 << 1, "PacketCable Call Manager Servers" },
361 /* May be called recursively */
363 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
364 gboolean downstream, int off, int eoff);
367 dissect_packetcable_ccc_option(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
370 /** THE ENCODING OF THIS SUBOPTION HAS CHANGED FROM DHCPv4
371 the code and length fields have grown from a single octet to
373 int suboptoff = optoff;
374 guint16 subopt, subopt_len, sec_tcm;
375 guint8 fetch_tgt, timer_val, type;
377 proto_tree *pkt_s_tree;
378 guint32 ipv4_address;
379 guchar kr_name; /** A character in the kerberos realm name option */
380 guint8 kr_value; /* The integer value of the character currently being tested */
381 int kr_fail_flag = 0; /* Flag indicating an invalid character was found */
382 int kr_pos = 0; /* The position of the first invalid character */
386 subopt = tvb_get_ntohs(tvb, optoff);
389 subopt_len = tvb_get_ntohs(tvb, suboptoff);
392 /* There must be at least five octets left to be a valid sub element */
394 proto_tree_add_text(v_tree, tvb, optoff, 1,
395 "Sub element %d: no room left in option for suboption length",
399 /* g_print("dissect packetcable ccc option subopt_len=%d optend=%d\n\n", subopt_len, optend); */
401 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 4,
402 "Sub element %u: %s: ", subopt,
403 val_to_str(subopt, pkt_ccc_opt_vals, "unknown/reserved") );
406 case PKT_CCC_PRI_DHCP: /* IPv4 address values */
407 case PKT_CCC_SEC_DHCP:
408 if (subopt_len == 4) {
409 ipv4_address = tvb_get_ipv4(tvb, suboptoff);
410 proto_item_append_text(vti, "%s (%u byte%s%s)",
411 ip_to_str((guint8 *)&ipv4_address), subopt_len,
412 plurality(subopt_len, "", "s"),
413 subopt_len != 4 ? " [Invalid]" : "");
416 proto_tree_add_text(vti, tvb, suboptoff, subopt_len,
417 "Bogus length: %d", subopt_len);
421 suboptoff += subopt_len;
423 case PKT_CCC_IETF_PROV_SRV :
424 type = tvb_get_guint8(tvb, suboptoff);
425 /** Type 0 is FQDN **/
427 proto_item_append_text(vti, "%s (%u byte%s)",
428 tvb_format_stringzpad(tvb, suboptoff+1, subopt_len-1),
430 plurality(subopt_len-1, "", "s") );
432 /** Type 0 is IPv4 **/
433 else if (type == 1) {
434 if (subopt_len == 5) {
435 ipv4_address = tvb_get_ipv4(tvb, suboptoff+1);
436 proto_item_append_text(vti, "%s (%u byte%s%s)",
437 ip_to_str((guint8 *)&ipv4_address), subopt_len,
438 plurality(subopt_len, "", "s"),
439 subopt_len != 5 ? " [Invalid]" : "");
442 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
446 proto_item_append_text(vti, "Invalid type: %u (%u byte%s)",
447 type, subopt_len, plurality(subopt_len, "", "s"));
449 suboptoff += subopt_len;
452 case PKT_CCC_IETF_AS_KRB :
453 case PKT_CCC_IETF_AP_KRB :
454 if (subopt_len == 12) {
455 pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
456 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
457 "Nominal Timeout : %u", tvb_get_ntohl(tvb, suboptoff));
458 proto_tree_add_text(pkt_s_tree, tvb, suboptoff+4, 4,
459 "Maximum Timeout : %u", tvb_get_ntohl(tvb, suboptoff+4));
460 proto_tree_add_text(pkt_s_tree, tvb, suboptoff+8, 4,
461 "Maximum Retry Count : %u", tvb_get_ntohl(tvb, suboptoff+8));
465 proto_item_append_text(vti, "Bogus length: %d", subopt_len);
467 suboptoff += subopt_len;
469 case PKT_CCC_KRB_REALM:
470 if (subopt_len > 0) {
471 /** The only allowable characters are
472 A-Z (upper case only) 65-90
482 make sure it conforms to the expected syntax.
484 for (i=0; i < subopt_len; i++) {
485 kr_name = tvb_get_guint8(tvb, suboptoff + i);
486 kr_value = (int)kr_name;
487 if ((kr_value >= 65 && kr_value <= 90) ||
496 else if (!kr_fail_flag) {
500 proto_item_append_text(vti, "%c", kr_name);
504 proto_item_append_text(vti, " (%u byte%s [Invalid at byte=%d]) ",
506 plurality(subopt_len, "", "s"),
510 proto_item_append_text(vti, " (%u byte%s%s) ",
512 plurality(subopt_len, "", "s"),
513 kr_fail_flag != 0 ? " [Invalid]" : "");
516 suboptoff += subopt_len;
519 case PKT_CCC_TGT_FLAG:
520 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
521 proto_item_append_text(vti, "%s (%u byte%s%s)",
522 fetch_tgt == 1 ? "True" : "False",
524 plurality(subopt_len, "", "s"),
525 subopt_len != 1 ? " [Invalid]" : "");
526 suboptoff += subopt_len;
529 case PKT_CCC_PROV_TIMER:
530 timer_val = tvb_get_guint8(tvb, suboptoff);
531 /* proto_item_append_text(vti, "%u%s (%u byte%s%s)", timer_val,
532 timer_val > 30 ? " [Invalid]" : "", */
533 proto_item_append_text(vti, "%u (%u byte%s%s)", timer_val,
535 plurality(subopt_len, "", "s"),
536 subopt_len != 1 ? " [Invalid]" : "");
537 suboptoff += subopt_len;
540 case PKT_CCC_IETF_SEC_TKT :
541 sec_tcm = tvb_get_ntohs(tvb, suboptoff);
542 proto_item_append_text(vti, "0x%04x (%u byte%s%s)",
543 sec_tcm, subopt_len, plurality(subopt_len, "", "s"),
544 subopt_len != 2 ? " [Invalid]" : "");
546 if (subopt_len == 2) {
547 pkt_s_tree = proto_item_add_subtree(vti, ett_dhcpv6_pkt_option);
548 for (i=0; i< 2; i++) {
549 if (sec_tcm & sec_tcm_vals[i].value) {
550 decode_bitfield_value(bit_fld, sec_tcm, sec_tcm_vals[i].value, 16);
551 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 2, "%s %s",
552 bit_fld, sec_tcm_vals[i].strptr);
556 suboptoff += subopt_len;
561 suboptoff += subopt_len;
566 /** Return the number of bytes processed **/
567 return (suboptoff - optoff);
571 dissect_cablelabs_specific_opts(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len)
574 guint16 tlv_len; /* holds the number of elements in the tlv */
575 guint16 opt_len; /* holds the length of the suboption */
578 int sub_off; /** The offset for the sub-option */
581 int field_len; /* holds the lenght of one occurrence of a field */
583 struct e_in6_addr in6;
586 while (off - voff < len) {
589 type = tvb_get_ntohs(tvb, off);
590 ti = proto_tree_add_text(v_tree, tvb, off, 2,
591 "Suboption %d: %s", type, val_to_str(type,
592 cl_vendor_subopt_values, "unknown"));
594 tlv_len = tvb_get_ntohs(tvb, off+2);
601 case CL_OPTION_DEVICE_TYPE :
602 case CL_OPTION_DEVICE_SERIAL_NUMBER :
603 case CL_OPTION_HARDWARE_VERSION_NUMBER :
604 case CL_OPTION_SOFTWARE_VERSION_NUMBER :
605 case CL_OPTION_BOOT_ROM_VERSION :
606 case CL_OPTION_MODEL_NUMBER :
607 case CL_OPTION_VENDOR_NAME :
608 case CL_OPTION_CONFIG_FILE_NAME :
609 case CL_OPTION_EMBEDDED_COMPONENT_LIST :
612 proto_item_append_text(ti, "\"%s\"",
613 tvb_format_stringzpad(tvb, sub_off, field_len));
619 for (i = 0; i < tlv_len; i += field_len) {
620 sub_value = tvb_get_ntohs(tvb, sub_off);
621 proto_item_append_text(ti, " %d", sub_value);
622 sub_off += field_len;
627 /* List of IPv6 Address */
628 case CL_OPTION_TFTP_SERVERS :
629 case CL_OPTION_SYSLOG_SERVERS :
630 case CL_OPTION_RFC868_SERVERS :
633 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
635 if ((tlv_len % field_len) == 0) {
636 for (i = 0; i < tlv_len/field_len; i++) {
637 tvb_get_ipv6(tvb, sub_off, &in6);
638 proto_tree_add_text(subtree, tvb, sub_off,
639 sizeof(in6), "IPv6 address %d: %s",
640 i+1, ip6_to_str(&in6));
641 sub_off += field_len;
646 case CL_OPTION_VENDOR_OUI :
647 case CL_OPTION_DEVICE_ID :
651 proto_item_append_text(ti, "Bogus value length=%d",
655 proto_item_append_text(ti, "%s",
656 tvb_bytes_to_str(tvb, sub_off, field_len));
660 case CL_OPTION_TLV5 :
663 proto_item_append_text(ti, "%s",
664 tvb_bytes_to_str(tvb, sub_off, field_len));
667 case CL_OPTION_TIME_OFFSET :
669 proto_item_append_text(ti, "%d", tvb_get_ntohl(tvb, sub_off));
672 case CL_OPTION_DOCS_CMTS_CAP :
675 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
677 /* tlv_len contains the total length of all the TLVs for this
680 for (i = 0; field_len < opt_len; i++) {
683 tag = tvb_get_guint8(tvb, sub_off);
685 tagLen = tvb_get_guint8(tvb, sub_off);
687 if (tag == CL_OPTION_DOCS_CMTS_TLV_VERS_NUM &&
691 major = tvb_get_guint8(tvb, sub_off);
693 minor = tvb_get_guint8(tvb, sub_off);
695 proto_tree_add_text(subtree, tvb, sub_off,
696 sizeof(4), "DOCSIS Version Number %d.%d",
702 field_len += tagLen + 2;
706 proto_tree_add_text(subtree, tvb, sub_off,
710 case CL_CM_MAC_ADDR :
714 proto_item_append_text(ti, "Bogus value length=%d",
718 /*proto_item_append_text(ti, "CM MAC Address Option = %s", */
719 proto_item_append_text(ti, "%s",
720 bytes_to_str_punct(tvb_get_ptr(tvb, sub_off, opt_len), opt_len, ':'));
721 /* tvb_bytes_to_str(tvb, sub_off, opt_len)); */
723 sub_off += field_len;
726 case CL_EROUTER_CONTAINER_OPTION :
729 proto_item_append_text(ti, " %s (len=%d)",
730 tvb_bytes_to_str(tvb, sub_off, opt_len), tlv_len);
731 sub_off += field_len;
737 subtree = proto_item_add_subtree(ti, ett_dhcpv6_vendor_option);
738 proto_item_append_text(ti, " (%d bytes)", opt_len);
739 while (field_len < opt_len) {
740 sub_value = dissect_packetcable_ccc_option(subtree, tvb,
741 sub_off, (opt_len - field_len));
742 sub_off += sub_value;
743 field_len += sub_value;
745 sub_off += field_len;
751 off += (opt_len + 4);
756 proto_tree_add_text(v_tree, tvb, off, len-off,
757 "Bogus length: %d", len);
763 dhcpv6_domain(proto_tree * subtree, tvbuff_t *tvb, int offset, guint16 optlen)
765 int start_offset=offset;
772 /* this is the start of the domain name */
778 /* read length of the next substring */
779 len = tvb_get_guint8(tvb, offset);
780 /* Microsoft dhcpv6 clients aren't currently RFC 4704 conform: They send an
781 * ASCII string instead of a DNS record encoded domain name. Catch that case
782 * to allow us to continue after such a malformed record.
784 if ( optlen < len ) {
785 proto_tree_add_text(subtree, tvb, start_offset, optlen, "Malformed DNS name record (MS Vista client?)");
790 /* if len==0 and pos>0 we have read an entire domain string */
793 /* empty string, this must be an error? */
794 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Malformed option");
797 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Domain: %s", domain);
803 /* add the substring to domain */
809 /* too long string, this must be an error? */
810 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Malformed option");
813 tvb_memcpy(tvb, domain+pos, offset, len);
821 proto_tree_add_text(subtree, tvb, start_offset, offset-start_offset, "Domain: %s", domain);
825 /* Returns the number of bytes consumed by this option. */
827 dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree,
828 gboolean downstream, int off, int eoff, gboolean *at_end)
834 guint16 temp_optlen = 0;
837 proto_tree *subtree_2;
839 struct e_in6_addr in6;
841 guint32 enterprise_no;
843 /* option type and length must be present */
844 if (eoff - off < 4) {
849 opttype = tvb_get_ntohs(tvb, off);
850 optlen = tvb_get_ntohs(tvb, off + 2);
852 /* all option data must be present */
853 if (eoff - off < 4 + optlen) {
858 ti = proto_tree_add_text(bp_tree, tvb, off, 4 + optlen,
859 "%s", val_to_str(opttype, opttype_vals, "DHCP option %u"));
861 subtree = proto_item_add_subtree(ti, ett_dhcpv6_option);
862 proto_tree_add_item(subtree, hf_option_type, tvb, off, 2, FALSE);
863 proto_tree_add_item(subtree, hf_option_length, tvb, off + 2, 2, FALSE);
865 /* Right now, none of the options can be filtered at, so provide a hex
866 array for minimalistic filtering */
867 proto_tree_add_item(subtree, hf_option_value, tvb, off, optlen, FALSE);
870 case OPTION_CLIENTID:
871 col_append_fstr(pinfo->cinfo, COL_INFO, "CID: %s ", tvb_bytes_to_str(tvb, off, optlen));
873 case OPTION_SERVERID:
875 proto_tree_add_text(subtree, tvb, off, optlen,
876 "DUID: malformed option");
879 proto_item_append_text(ti, ": %s", tvb_bytes_to_str(tvb, off, optlen));
880 duidtype = tvb_get_ntohs(tvb, off);
881 proto_tree_add_text(subtree, tvb, off, 2,
882 "DUID type: %s (%u)",
884 duidtype_vals, "Unknown"),
889 proto_tree_add_text(subtree, tvb, off,
890 optlen, "DUID: malformed option");
893 hwtype=tvb_get_ntohs(tvb, off + 2);
894 proto_tree_add_text(subtree, tvb, off + 2, 2,
895 "Hardware type: %s (%u)", arphrdtype_to_str(hwtype, "Unknown"),
897 /* XXX seconds since Jan 1 2000 */
898 proto_tree_add_text(subtree, tvb, off + 4, 4,
899 "Time: %u", tvb_get_ntohl(tvb, off + 4));
901 proto_tree_add_text(subtree, tvb, off + 8,
902 optlen - 8, "Link-layer address: %s",
903 arphrdaddr_to_str(tvb_get_ptr(tvb, off+8, optlen-8), optlen-8, hwtype));
908 proto_tree_add_text(subtree, tvb, off,
909 optlen, "DUID: malformed option");
912 proto_tree_add_item(subtree, hf_duiden_enterprise, tvb, off + 2, 4, FALSE);
914 buf = tvb_bytes_to_str(tvb, off + 6, optlen - 6);
915 proto_tree_add_text(subtree, tvb, off + 6,
916 optlen - 6, "identifier: %s", buf);
922 proto_tree_add_text(subtree, tvb, off,
923 optlen, "DUID: malformed option");
926 hwtype=tvb_get_ntohs(tvb, off + 2);
927 proto_tree_add_text(subtree, tvb, off + 2, 2,
928 "Hardware type: %s (%u)",
929 arphrdtype_to_str(hwtype, "Unknown"),
932 proto_tree_add_text(subtree, tvb, off + 4,
933 optlen - 4, "Link-layer address: %s",
934 arphrdaddr_to_str(tvb_get_ptr(tvb, off+4, optlen-4), optlen-4, hwtype));
942 if (opttype == OPTION_IA_NA)
943 proto_tree_add_text(subtree, tvb, off,
944 optlen, "IA_NA: malformed option");
946 proto_tree_add_text(subtree, tvb, off,
947 optlen, "IA_PD: malformed option");
950 proto_tree_add_text(subtree, tvb, off, 4,
952 tvb_get_ntohl(tvb, off));
953 if (tvb_get_ntohl(tvb, off+4) == DHCPV6_LEASEDURATION_INFINITY) {
954 proto_tree_add_text(subtree, tvb, off+4, 4,
957 proto_tree_add_text(subtree, tvb, off+4, 4,
958 "T1: %u", tvb_get_ntohl(tvb, off+4));
961 if (tvb_get_ntohl(tvb, off+8) == DHCPV6_LEASEDURATION_INFINITY) {
962 proto_tree_add_text(subtree, tvb, off+8, 4,
965 proto_tree_add_text(subtree, tvb, off+8, 4,
966 "T2: %u", tvb_get_ntohl(tvb, off+8));
970 while ((optlen - temp_optlen) > 0) {
971 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
972 off+temp_optlen, off + optlen, at_end);
974 /* Bad option - just skip to the end */
975 temp_optlen = optlen;
981 proto_tree_add_text(subtree, tvb, off,
982 optlen, "IA_TA: malformed option");
985 proto_tree_add_text(subtree, tvb, off, 4,
987 tvb_get_ntohl(tvb, off));
989 while ((optlen - temp_optlen) > 0) {
990 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
991 off+temp_optlen, off + optlen, at_end);
993 /* Bad option - just skip to the end */
994 temp_optlen = optlen;
1000 guint32 preferred_lifetime, valid_lifetime;
1003 proto_tree_add_text(subtree, tvb, off,
1004 optlen, "IAADDR: malformed option");
1007 tvb_get_ipv6(tvb, off, &in6);
1008 proto_tree_add_text(subtree, tvb, off,
1009 sizeof(in6), "IPv6 address: %s",
1011 col_append_fstr(pinfo->cinfo, COL_INFO, "IAA: %s ", ip6_to_str(&in6));
1012 proto_item_append_text(ti, ": %s", ip6_to_str(&in6));
1014 preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
1015 valid_lifetime = tvb_get_ntohl(tvb, off + 20);
1017 if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1018 proto_tree_add_text(subtree, tvb, off + 16, 4,
1019 "Preferred lifetime: infinity");
1021 proto_tree_add_text(subtree, tvb, off + 16, 4,
1022 "Preferred lifetime: %u", preferred_lifetime);
1024 if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1025 proto_tree_add_text(subtree, tvb, off + 20, 4,
1026 "Valid lifetime: infinity");
1028 proto_tree_add_text(subtree, tvb, off + 20, 4,
1029 "Valid lifetime: %u", valid_lifetime);
1033 while ((optlen - temp_optlen) > 0) {
1034 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1035 off+temp_optlen, off + optlen, at_end);
1037 /* Bad option - just skip to the end */
1038 temp_optlen = optlen;
1045 for (i = 0; i < optlen; i += 2) {
1046 guint16 requested_opt_code;
1047 requested_opt_code = tvb_get_ntohs(tvb, off + i);
1048 proto_tree_add_text(subtree, tvb, off + i,
1049 2, "Requested Option code: %s (%d)",
1050 val_to_str(requested_opt_code,
1053 requested_opt_code);
1056 case OPTION_PREFERENCE:
1058 proto_tree_add_text(subtree, tvb, off,
1059 optlen, "PREFERENCE: malformed option");
1062 proto_tree_add_text(subtree, tvb, off, 1,
1064 (guint32)tvb_get_guint8(tvb, off));
1066 case OPTION_ELAPSED_TIME:
1068 proto_tree_add_text(subtree, tvb, off,
1069 optlen, "ELAPSED-TIME: malformed option");
1072 proto_tree_add_text(subtree, tvb, off, 2,
1073 "elapsed-time: %u ms",
1074 10*(guint32)tvb_get_ntohs(tvb, off));
1076 case OPTION_RELAY_MSG:
1078 proto_tree_add_text(subtree, tvb, off,
1079 optlen, "RELAY-MSG: malformed option");
1081 /* here, we should dissect a full DHCP message */
1082 dissect_dhcpv6(tvb, pinfo, subtree, downstream, off, off + optlen);
1087 proto_tree_add_text(subtree, tvb, off,
1088 optlen, "AUTH: malformed option");
1091 proto_tree_add_text(subtree, tvb, off, 1,
1093 (guint32)tvb_get_guint8(tvb, off));
1094 proto_tree_add_text(subtree, tvb, off+1, 1,
1096 (guint32)tvb_get_guint8(tvb, off+1));
1097 proto_tree_add_text(subtree, tvb, off+2, 1,
1099 (guint32)tvb_get_guint8(tvb, off+2));
1100 proto_tree_add_text(subtree, tvb, off+3, 8,
1101 "Replay Detection");
1103 proto_tree_add_text(subtree, tvb, off+11, optlen-11,
1104 "Authentication Information");
1106 case OPTION_UNICAST:
1108 proto_tree_add_text(subtree, tvb, off,
1109 optlen, "UNICAST: malformed option");
1112 tvb_get_ipv6(tvb, off, &in6);
1113 proto_tree_add_text(subtree, tvb, off,
1114 sizeof(in6), "IPv6 address: %s",
1117 case OPTION_STATUS_CODE:
1119 guint16 status_code;
1120 char *status_message = 0;
1121 status_code = tvb_get_ntohs(tvb, off);
1122 proto_tree_add_text(subtree, tvb, off, 2,
1123 "Status Code: %s (%d)",
1124 val_to_str(status_code, statuscode_vals,
1128 if (optlen - 2 > 0) {
1129 status_message = tvb_get_ephemeral_string(tvb, off + 2, optlen - 2);
1130 proto_tree_add_text(subtree, tvb, off + 2, optlen - 2,
1131 "Status Message: %s",
1136 case OPTION_VENDOR_CLASS:
1138 proto_tree_add_text(subtree, tvb, off,
1139 optlen, "VENDOR_CLASS: malformed option");
1142 proto_tree_add_item(subtree, hf_vendorclass_enterprise, tvb, off, 4, FALSE);
1144 buf = tvb_bytes_to_str(tvb, off + 4, optlen - 4);
1145 proto_tree_add_text(subtree, tvb, off+4, optlen-4,
1146 "vendor-class-data: %s", buf);
1149 case OPTION_VENDOR_OPTS:
1151 proto_tree_add_text(subtree, tvb, off,
1152 optlen, "VENDOR_OPTS: malformed option");
1156 enterprise_no = tvb_get_ntohl(tvb, off);
1157 proto_tree_add_item(subtree, hf_vendoropts_enterprise, tvb, off, 4, FALSE);
1160 if (enterprise_no == 4491) {
1161 dissect_cablelabs_specific_opts(subtree, tvb, off+4, optlen-4);
1165 while((optlen - 4 - optoffset) > 0) {
1166 int olen = tvb_get_ntohs(tvb, off + optoffset + 6);
1167 ti = proto_tree_add_text(subtree, tvb, off + optoffset + 4,
1168 4 + olen, "option");
1169 subtree_2 = proto_item_add_subtree(ti, ett_dhcpv6_option_vsoption);
1171 proto_tree_add_text(subtree_2, tvb, off + optoffset + 4, 2,
1172 "option code: %u", tvb_get_ntohs(tvb, off + optoffset + 4));
1173 proto_tree_add_text(subtree_2, tvb, off + optoffset + 6, 2,
1174 "option length: %u", olen);
1175 proto_tree_add_text(subtree_2, tvb, off + optoffset + 8, olen,
1177 optoffset += (4 + olen);
1182 case OPTION_INTERFACE_ID:
1184 proto_tree_add_text(subtree, tvb, off,
1185 optlen, "INTERFACE_ID: malformed option");
1188 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1189 proto_tree_add_text(subtree, tvb, off, optlen, "Interface-ID: %s", buf);
1191 case OPTION_RECONF_MSG:
1193 proto_tree_add_text(subtree, tvb, off,
1194 optlen, "RECONF_MSG: malformed option");
1197 proto_tree_add_text(subtree, tvb, off, optlen,
1198 "Reconfigure-type: %s",
1199 val_to_str(tvb_get_guint8(tvb, off),
1201 "Message Type %u"));
1203 case OPTION_SIP_SERVER_D:
1205 proto_tree_add_text(subtree, tvb, off, optlen,
1206 "SIP Servers Domain Search List");
1208 dhcpv6_domain(subtree,tvb, off, optlen);
1210 case OPTION_SIP_SERVER_A:
1212 proto_tree_add_text(subtree, tvb, off, optlen,
1213 "SIP servers address: malformed option");
1216 for (i = 0; i < optlen; i += 16) {
1217 tvb_get_ipv6(tvb, off + i, &in6);
1218 proto_tree_add_text(subtree, tvb, off + i,
1219 sizeof(in6), "SIP servers address: %s",
1223 case OPTION_DNS_SERVERS:
1225 proto_tree_add_text(subtree, tvb, off, optlen,
1226 "DNS servers address: malformed option");
1229 for (i = 0; i < optlen; i += 16) {
1230 tvb_get_ipv6(tvb, off + i, &in6);
1231 proto_tree_add_text(subtree, tvb, off + i,
1232 sizeof(in6), "DNS servers address: %s",
1236 case OPTION_DOMAIN_LIST:
1238 proto_tree_add_text(subtree, tvb, off, optlen, "DNS Domain Search List");
1240 dhcpv6_domain(subtree,tvb, off, optlen);
1242 case OPTION_NIS_SERVERS:
1244 proto_tree_add_text(subtree, tvb, off, optlen,
1245 "NIS servers address: malformed option");
1248 for (i = 0; i < optlen; i += 16) {
1249 tvb_get_ipv6(tvb, off + i, &in6);
1250 proto_tree_add_text(subtree, tvb, off + i,
1251 sizeof(in6), "NIS servers address: %s",
1255 case OPTION_NISP_SERVERS:
1257 proto_tree_add_text(subtree, tvb, off, optlen,
1258 "NISP servers address: malformed option");
1261 for (i = 0; i < optlen; i += 16) {
1262 tvb_get_ipv6(tvb, off + i, &in6);
1263 proto_tree_add_text(subtree, tvb, off + i,
1264 sizeof(in6), "NISP servers address: %s",
1268 case OPTION_NIS_DOMAIN_NAME:
1270 proto_tree_add_text(subtree, tvb, off, optlen, "nis-domain-name");
1272 dhcpv6_domain(subtree,tvb, off, optlen);
1274 case OPTION_NISP_DOMAIN_NAME:
1276 proto_tree_add_text(subtree, tvb, off, optlen, "nisp-domain-name");
1278 dhcpv6_domain(subtree,tvb, off, optlen);
1280 case OPTION_SNTP_SERVERS:
1282 proto_tree_add_text(subtree, tvb, off, optlen,
1283 "SNTP servers address: malformed option");
1286 for (i = 0; i < optlen; i += 16) {
1287 tvb_get_ipv6(tvb, off + i, &in6);
1288 proto_tree_add_text(subtree, tvb, off + i,
1289 sizeof(in6), "SNTP servers address: %s",
1293 case OPTION_LIFETIME:
1295 proto_tree_add_text(subtree, tvb, off,
1296 optlen, "LIFETIME: malformed option");
1299 proto_tree_add_text(subtree, tvb, off, 4,
1301 (guint32)tvb_get_ntohl(tvb, off));
1303 case OPTION_BCMCS_SERVER_D:
1305 proto_tree_add_text(subtree, tvb, off, optlen,
1306 "BCMCS Servers Domain Search List");
1308 dhcpv6_domain(subtree,tvb, off, optlen);
1310 case OPTION_BCMCS_SERVER_A:
1312 proto_tree_add_text(subtree, tvb, off, optlen,
1313 "BCMCS servers address: malformed option");
1316 for (i = 0; i < optlen; i += 16) {
1317 tvb_get_ipv6(tvb, off + i, &in6);
1318 proto_tree_add_text(subtree, tvb, off + i,
1319 sizeof(in6), "BCMCS servers address: %s",
1323 case OPTION_REMOTE_ID:
1325 proto_tree_add_text(subtree, tvb, off,
1326 optlen, "REMOTE_ID: malformed option");
1329 proto_tree_add_item(subtree, hf_remoteid_enterprise, tvb, off, 4, FALSE);
1332 buf = tvb_bytes_to_str(tvb, off, optlen);
1333 proto_tree_add_text(subtree, tvb, off, optlen, "Remote-ID: %s", buf);
1335 case OPTION_SUBSCRIBER_ID:
1337 proto_tree_add_text(subtree, tvb, off,
1338 optlen, "SUBSCRIBER_ID: malformed option");
1341 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1342 proto_tree_add_text(subtree, tvb, off, optlen, "Subscriber-ID: %s", buf);
1344 case OPTION_CLIENT_FQDN:
1346 proto_tree_add_text(subtree, tvb, off,
1347 optlen, "FQDN: malformed option");
1354 proto_tree_add_item(subtree, hf_clientfqdn_reserved, tvb, off, 1, FALSE);
1355 proto_tree_add_item(subtree, hf_clientfqdn_n, tvb, off, 1, FALSE);
1356 proto_tree_add_item(subtree, hf_clientfqdn_o, tvb, off, 1, FALSE);
1357 proto_tree_add_item(subtree, hf_clientfqdn_s, tvb, off, 1, FALSE);
1359 proto_tree_add_text(subtree, tvb, off, 1,
1361 (guint32)tvb_get_guint8(tvb, off));
1363 dhcpv6_domain(subtree, tvb, off + 1, optlen - 1);
1366 case OPTION_PANA_AGENT:
1368 proto_tree_add_text(subtree, tvb, off, optlen,
1369 "PANA agent address: malformed option");
1372 for (i = 0; i < optlen; i += 16) {
1373 tvb_get_ipv6(tvb, off + i, &in6);
1374 proto_tree_add_text(subtree, tvb, off + i,
1375 sizeof(in6), "PANA agents address: %s",
1379 case OPTION_TIME_ZONE:
1381 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1382 proto_tree_add_text(subtree, tvb, off, optlen, "time-zone: %s", buf);
1387 buf = tvb_get_ephemeral_string(tvb, off, optlen);
1388 proto_tree_add_text(subtree, tvb, off, optlen, "tz-database: %s", buf);
1391 case OPTION_LQ_QUERY:
1394 struct e_in6_addr in6_local;
1397 proto_tree_add_text(subtree, tvb, off, optlen,
1398 "LQ-QUERY: malformed option");
1401 query_type = tvb_get_guint8(tvb, off);
1402 switch (query_type) {
1404 proto_tree_add_text(subtree, tvb, off, 1,
1405 "Query-type: %s (%u)",
1406 "by-address", query_type);
1409 proto_tree_add_text(subtree, tvb, off, 1,
1410 "Query-type: %s (%u)",
1411 "by-clientID", query_type);
1414 proto_tree_add_text(subtree, tvb, off, 1,
1415 "Query-type: %s (%u)",
1416 "unknown?", query_type);
1419 tvb_get_ipv6(tvb, off + 1, &in6_local);
1420 proto_tree_add_text(subtree, tvb, off + 1, 16,
1421 "Link address: %s", ip6_to_str(&in6_local));
1423 while ((optlen - temp_optlen) > 0) {
1424 temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
1425 downstream, off + temp_optlen,
1426 off + optlen, at_end);
1428 /* Bad option - just skip to the end */
1429 temp_optlen = optlen;
1434 case OPTION_CLIENT_DATA:
1436 while ((optlen - temp_optlen) > 0) {
1437 temp_optlen += dhcpv6_option(tvb, pinfo, subtree,
1438 downstream, off + temp_optlen,
1439 off + optlen, at_end);
1441 /* Bad option - just skip to the end */
1442 temp_optlen = optlen;
1446 case OPTION_CLT_TIME:
1448 proto_tree_add_text(subtree, tvb, off, optlen,
1449 "CLT_TIME: malformed option");
1452 proto_tree_add_text(subtree, tvb, off, 4,
1454 (guint32)tvb_get_ntohl(tvb, off));
1456 case OPTION_LQ_RELAY_DATA:
1458 proto_tree_add_text(subtree, tvb, off, optlen,
1459 "LQ_RELAY_DATA: malformed option");
1462 tvb_get_ipv6(tvb, off, &in6);
1463 proto_tree_add_text(subtree, tvb, off, 16,
1464 "Peer address: %s", ip6_to_str(&in6));
1465 proto_tree_add_text(subtree, tvb, off + 16, optlen - 16,
1466 "DHCPv6 relay message");
1468 case OPTION_LQ_CLIENT_LINK:
1470 proto_tree_add_text(subtree, tvb, off, optlen,
1471 "LQ client links address: malformed option");
1474 for (i = 0; i < optlen; i += 16) {
1475 tvb_get_ipv6(tvb, off + i, &in6);
1476 proto_tree_add_text(subtree, tvb, off + i,
1477 sizeof(in6), "LQ client links address: %s",
1481 case OPTION_CAPWAP_AC_V6:
1483 proto_tree_add_text(subtree, tvb, off, optlen,
1484 "CAPWAP Access Controllers address: malformed option");
1487 for (i = 0; i < optlen; i += 16) {
1488 tvb_get_ipv6(tvb, off + i, &in6);
1489 proto_tree_add_text(subtree, tvb, off + i,
1490 sizeof(in6), "CAPWAP Access Controllers address: %s",
1494 case OPTION_IAPREFIX:
1496 guint32 preferred_lifetime, valid_lifetime;
1497 guint8 prefix_length;
1498 struct e_in6_addr in6_local;
1501 proto_tree_add_text(subtree, tvb, off,
1502 optlen, "IAPREFIX: malformed option");
1506 preferred_lifetime = tvb_get_ntohl(tvb, off);
1507 valid_lifetime = tvb_get_ntohl(tvb, off + 4);
1508 prefix_length = tvb_get_guint8(tvb, off + 8);
1509 if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1510 proto_tree_add_text(subtree, tvb, off, 4,
1511 "Preferred lifetime: infinity");
1513 proto_tree_add_text(subtree, tvb, off, 4,
1514 "Preferred lifetime: %u", preferred_lifetime);
1516 if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
1517 proto_tree_add_text(subtree, tvb, off + 4, 4,
1518 "Valid lifetime: infinity");
1520 proto_tree_add_text(subtree, tvb, off + 4, 4,
1521 "Valid lifetime: %u", valid_lifetime);
1523 proto_tree_add_text(subtree, tvb, off + 8, 1,
1524 "Prefix length: %d", prefix_length);
1525 tvb_get_ipv6(tvb, off + 9, &in6_local);
1526 proto_tree_add_text(subtree, tvb, off + 9,
1527 16, "Prefix address: %s",
1528 ip6_to_str(&in6_local));
1531 while ((optlen - temp_optlen) > 0) {
1532 temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream,
1533 off+temp_optlen, off + optlen, at_end);
1535 /* Bad option - just skip to the end */
1536 temp_optlen = optlen;
1541 case OPTION_MIP6_HA:
1543 proto_tree_add_text(subtree, tvb, off, optlen,
1544 "MIP6_HA: malformed option");
1548 tvb_get_ipv6(tvb, off, &in6);
1549 proto_tree_add_text(subtree, tvb, off,
1550 16, "Home Agent: %s", ip6_to_str(&in6));
1552 case OPTION_MIP6_HOA:
1554 proto_tree_add_text(subtree, tvb, off, optlen,
1555 "MIP6_HOA: malformed option");
1559 tvb_get_ipv6(tvb, off, &in6);
1560 proto_tree_add_text(subtree, tvb, off,
1561 16, "Home Address: %s", ip6_to_str(&in6));
1565 proto_tree_add_text(subtree, tvb, off, optlen,
1566 "NAI: malformed option");
1569 proto_tree_add_text(subtree, tvb, off, optlen,
1570 "NAI : %s", tvb_get_ptr(tvb, off, optlen - 2));
1579 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1580 gboolean downstream, int off, int eoff)
1582 proto_tree *bp_tree = NULL;
1586 struct e_in6_addr in6;
1588 msgtype = tvb_get_guint8(tvb, off);
1590 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msgtype, msgtype_vals, "Message Type %u"));
1593 ti = proto_tree_add_item(tree, proto_dhcpv6, tvb, off, eoff - off, FALSE);
1594 bp_tree = proto_item_add_subtree(ti, ett_dhcpv6);
1598 if (msgtype == RELAY_FORW || msgtype == RELAY_REPLY) {
1600 proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, FALSE);
1601 proto_tree_add_item(bp_tree, hf_dhcpv6_hopcount, tvb, off + 1, 1, FALSE);
1602 proto_tree_add_item(bp_tree, hf_dhcpv6_linkaddr, tvb, off + 2, 16, FALSE);
1603 tvb_get_ipv6(tvb, off + 2, &in6);
1604 col_append_fstr(pinfo->cinfo, COL_INFO, "L: %s ", ip6_to_str(&in6));
1605 proto_tree_add_item(bp_tree, hf_dhcpv6_peeraddr, tvb, off + 18, 16, FALSE);
1610 proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, FALSE);
1611 proto_tree_add_item(bp_tree, hf_dhcpv6_xid, tvb, off + 1, 3, FALSE);
1613 col_append_fstr(pinfo->cinfo, COL_INFO, "XID: 0x%x ", tvb_get_ntoh24(tvb, off + 1));
1618 while (off < eoff && !at_end)
1619 off += dhcpv6_option(tvb, pinfo, bp_tree, downstream, off, eoff, &at_end);
1623 dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1625 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
1626 col_clear(pinfo->cinfo, COL_INFO);
1627 dissect_dhcpv6(tvb, pinfo, tree, TRUE, 0, tvb_reported_length(tvb));
1631 dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1633 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
1634 col_clear(pinfo->cinfo, COL_INFO);
1635 dissect_dhcpv6(tvb, pinfo, tree, FALSE, 0, tvb_reported_length(tvb));
1640 proto_register_dhcpv6(void)
1642 static hf_register_info hf[] = {
1645 { &hf_dhcpv6_msgtype,
1646 { "Message type", "dhcpv6.msgtype", FT_UINT8, BASE_DEC, VALS(msgtype_vals), 0x0, NULL, HFILL }},
1647 { &hf_dhcpv6_hopcount,
1648 { "Hopcount", "dhcpv6.hopcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1650 { "Transaction ID", "dhcpv6.xid", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL}},
1651 { &hf_dhcpv6_linkaddr,
1652 { "Link address", "dhcpv6.linkaddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
1653 { &hf_dhcpv6_peeraddr,
1654 { "Peer address", "dhcpv6.peeraddr", FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL}},
1655 /* Generic option stuff */
1657 { "Option", "dhcpv6.option.type", FT_UINT16, BASE_DEC, VALS(opttype_vals), 0x0, NULL, HFILL}},
1658 { &hf_option_length,
1659 { "Length", "dhcpv6.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1661 { "Value", "dhcpv6.option.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1662 /* Individual options */
1663 { &hf_clientfqdn_reserved,
1664 { "Reserved", "dhcpv6.clientfqdn.reserved", FT_UINT8, BASE_HEX, NULL, 0xF8, NULL, HFILL}},
1666 { "N", "dhcpv6.clientfqdn.n", FT_BOOLEAN, 8, TFS(&fqdn_n), 0x4, NULL, HFILL}},
1668 { "O", "dhcpv6.clientfqdn.o", FT_BOOLEAN, 8, TFS(&fqdn_o), 0x2, NULL, HFILL}},
1670 { "S", "dhcpv6.clientfqdn.s", FT_BOOLEAN, 8, TFS(&fqdn_s), 0x1, NULL, HFILL}},
1671 { &hf_remoteid_enterprise,
1672 { "Enterprise ID", "dhvpv6.remoteid.enterprise", FT_UINT32, BASE_DEC, VALS(sminmpec_values), 0, "RemoteID Enterprise Number", HFILL }},
1673 { &hf_vendoropts_enterprise,
1674 { "Enterprise ID", "dhvpv6.vendoropts.enterprise", FT_UINT32, BASE_DEC, VALS(sminmpec_values), 0, "Vendor opts Enterprise Number", HFILL }},
1675 { &hf_vendorclass_enterprise,
1676 { "Enterprise ID", "dhvpv6.vendorclass.enterprise", FT_UINT32, BASE_DEC, VALS(sminmpec_values), 0, "Vendor Class Enterprise Number", HFILL }},
1677 { &hf_duiden_enterprise,
1678 { "Enterprise ID", "dhvpv6.duiden.enterprise", FT_UINT32, BASE_DEC, VALS(sminmpec_values), 0, "DUID EN Enterprise Number", HFILL }},
1681 static gint *ett[] = {
1684 &ett_dhcpv6_option_vsoption,
1685 &ett_dhcpv6_vendor_option,
1686 &ett_dhcpv6_pkt_option,
1689 proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
1690 proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
1691 proto_register_subtree_array(ett, array_length(ett));
1693 /* Allow other dissectors to find this one by name.
1694 Just choose upstream version for now as they are identical. */
1695 register_dissector("dhcpv6", dissect_dhcpv6_upstream, proto_dhcpv6);
1699 proto_reg_handoff_dhcpv6(void)
1701 dissector_handle_t dhcpv6_handle;
1703 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_downstream,
1705 dissector_add("udp.port", UDP_PORT_DHCPV6_DOWNSTREAM, dhcpv6_handle);
1706 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_upstream,
1708 dissector_add("udp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_handle);