2 * Routines for DHCPv6 packet disassembly
3 * Jun-ichiro itojun Hagino <itojun@iijlab.net>
4 * IItom Tsutomu MIENO <iitom@utouto.com>
5 * SHIRASAKI Yasuhiro <yasuhiro@gnome.gr.jp>
6 * Tony Lindstrom <tony.lindstrom@ericsson.com>
8 * $Id: packet-dhcpv6.c,v 1.8 2003/08/18 18:20:11 guy Exp $
10 * The information used comes from:
11 * draft-ietf-dhc-dhcpv6-28.txt
12 * draft-ietf-dhc-dhcpv6-opt-prefix-delegation-04.txt
13 * draft-ietf-dhc-dhcpv6-opt-dnsconfig-03.txt
14 * draft-ietf-dhc-dhcpv6-opt-nisconfig-02.txt
15 * draft-ietf-dhc-dhcpv6-opt-timeconfig-02.txt
16 * Note that protocol constants are still subject to change, based on IANA
17 * assignment decisions.
19 * Ethereal - Network traffic analyzer
20 * By Gerald Combs <gerald@ethereal.com>
21 * Copyright 1998 Gerald Combs
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #include <epan/int-64bit.h>
45 #include <epan/packet.h>
46 #include <epan/ipv6-utils.h>
48 static int proto_dhcpv6 = -1;
49 static int hf_dhcpv6_msgtype = -1;
51 static guint ett_dhcpv6 = -1;
52 static guint ett_dhcpv6_option = -1;
54 #define UDP_PORT_DHCPV6_DOWNSTREAM 546
55 #define UDP_PORT_DHCPV6_UPSTREAM 547
57 #define DHCPV6_LEASEDURATION_INFINITY 0xffffffff
68 #define RECONFIGURE 10
69 #define INFORMATION_REQUEST 11
73 #define OPTION_CLIENTID 1
74 #define OPTION_SERVERID 2
75 #define OPTION_IA_NA 3
76 #define OPTION_IA_TA 4
77 #define OPTION_IAADDR 5
79 #define OPTION_PREFERENCE 7
80 #define OPTION_ELAPSED_TIME 8
81 #define OPTION_RELAY_MSG 9
82 /* #define OPTION_SERVER_MSG 10 */
83 #define OPTION_AUTH 11
84 #define OPTION_UNICAST 12
85 #define OPTION_STATUS_CODE 13
86 #define OPTION_RAPID_COMMIT 14
87 #define OPTION_USER_CLASS 15
88 #define OPTION_VENDOR_CLASS 16
89 #define OPTION_VENDOR_OPTS 17
90 #define OPTION_INTERFACE_ID 18
91 #define OPTION_RECONF_MSG 19
92 #define OPTION_RECONF_ACCEPT 20
94 #define OPTION_IA_PD 21
95 #define OPTION_IAPREFIX 22
96 #define OPTION_DNS_RESOLVERS 30
97 #define OPTION_DOMAIN_LIST 31
98 #define OPTION_NIS_SERVERS 35
99 #define OPTION_NISP_SERVERS 36
100 #define OPTION_NIS_DOMAIN_NAME 37
101 #define OPTION_NISP_DOMAIN_NAME 38
102 #define OPTION_NTP_SERVERS 40
103 #define OPTION_TIME_ZONE 41
104 /* define OPTION_DNS_SERVERS 50 */
109 #define DUID_LL_OLD 4
111 static const value_string msgtype_vals[] = {
112 { SOLICIT, "Solicit" },
113 { ADVERTISE, "Advertise" },
114 { REQUEST, "Request" },
115 { CONFIRM, "Confirm" },
117 { REBIND, "Rebind" },
119 { RELEASE, "Release" },
120 { DECLINE, "Decline" },
121 { RECONFIGURE, "Reconfigure" },
122 { INFORMATION_REQUEST, "Information-request" },
123 { RELAY_FORW, "Relay-forw" },
124 { RELAY_REPL, "Relay-repl" },
128 static const value_string opttype_vals[] = {
129 { OPTION_CLIENTID, "Client Identifier" },
130 { OPTION_SERVERID, "Server Identifier" },
131 { OPTION_IA_NA, "Identify Association" },
132 { OPTION_IA_TA, "Identify Association for Temporary Address" },
133 { OPTION_IAADDR, "IA Address" },
134 { OPTION_ORO, "Option Request" },
135 { OPTION_PREFERENCE, "Preference" },
136 { OPTION_ELAPSED_TIME, "Elapsed time" },
137 { OPTION_RELAY_MSG, "Relay Message" },
138 /* { OPTION_SERVER_MSG, "Server message" }, */
139 { OPTION_AUTH, "Authentication" },
140 { OPTION_UNICAST, "Server unicast" },
141 { OPTION_STATUS_CODE, "Status code" },
142 { OPTION_RAPID_COMMIT, "Rapid Commit" },
143 { OPTION_USER_CLASS, "User Class" },
144 { OPTION_VENDOR_CLASS, "Vendor Class" },
145 { OPTION_VENDOR_OPTS, "Vendor-specific Information" },
146 { OPTION_INTERFACE_ID, "Interface-Id" },
147 { OPTION_RECONF_MSG, "Reconfigure Message" },
148 { OPTION_RECONF_ACCEPT, "Reconfigure Accept" },
149 { OPTION_IA_PD, "Identify Association for Prefix Delegation" },
150 { OPTION_IAPREFIX, "IA Prefix" },
151 { OPTION_DNS_RESOLVERS, "DNS Resolver" },
152 { OPTION_DOMAIN_LIST, "Domain Search List" },
153 { OPTION_NIS_SERVERS, "Network Information Server" },
154 { OPTION_NISP_SERVERS, "Network Information Server V2" },
155 { OPTION_NIS_DOMAIN_NAME, "Network Information Server Domain Name" },
156 { OPTION_NISP_DOMAIN_NAME,"Network Information Server V2 Domain Name" },
157 { OPTION_NTP_SERVERS, "Network Time Protocol Server" },
158 { OPTION_TIME_ZONE, "Time zone" },
159 /* { OPTION_DNS_SERVERS, "Domain Name Server" }, */
163 static const value_string statuscode_vals[] =
170 {5, "UseMulticast" },
171 {6, "NoPrefixAvail" },
175 static const value_string duidtype_vals[] =
177 { DUID_LLT, "link-layer address plus time" },
178 { DUID_EN, "assigned by vendor based on Enterprise number" },
179 { DUID_LL, "link-layer address" },
180 { DUID_LL_OLD, "link-layer address (old)" },
184 /* Returns the number of bytes consumed by this option. */
186 dhcpv6_option(tvbuff_t *tvb, proto_tree *bp_tree, int off, int eoff,
191 guint16 temp_optlen = 0;
195 struct e_in6_addr in6;
198 /* option type and length must be present */
199 if (eoff - off < 4) {
204 opttype = tvb_get_ntohs(tvb, off);
205 optlen = tvb_get_ntohs(tvb, off + 2);
208 if (eoff - off < 4 + optlen) {
213 ti = proto_tree_add_text(bp_tree, tvb, off, 4 + optlen,
214 "%s", val_to_str(opttype, opttype_vals, "DHCP option %u"));
216 subtree = proto_item_add_subtree(ti, ett_dhcpv6_option);
217 proto_tree_add_text(subtree, tvb, off, 2, "option type: %d", opttype);
218 proto_tree_add_text(subtree, tvb, off + 2, 2, "option length: %d",
223 case OPTION_CLIENTID:
224 case OPTION_SERVERID:
226 proto_tree_add_text(subtree, tvb, off, optlen,
227 "DUID: malformed option");
230 duidtype = tvb_get_ntohs(tvb, off);
231 proto_tree_add_text(subtree, tvb, off, 2,
232 "DUID type: %s (%u)",
234 duidtype_vals, "Unknown"),
239 proto_tree_add_text(subtree, tvb, off,
240 optlen, "DUID: malformed option");
243 /* XXX seconds since Jan 1 2000 */
244 proto_tree_add_text(subtree, tvb, off + 2, 2,
246 tvb_get_ntohs(tvb, off + 2));
247 proto_tree_add_text(subtree, tvb, off + 4, 4,
248 "Time: %u", tvb_get_ntohl(tvb, off + 4));
250 proto_tree_add_text(subtree, tvb, off + 8,
251 optlen - 8, "Link-layer address");
256 proto_tree_add_text(subtree, tvb, off,
257 optlen, "DUID: malformed option");
260 proto_tree_add_text(subtree, tvb, off + 2, 4,
261 "enterprise-number");
263 proto_tree_add_text(subtree, tvb, off + 6,
264 optlen - 6, "identifier");
270 proto_tree_add_text(subtree, tvb, off,
271 optlen, "DUID: malformed option");
274 proto_tree_add_text(subtree, tvb, off + 2, 2,
276 tvb_get_ntohs(tvb, off + 2));
278 proto_tree_add_text(subtree, tvb, off + 4,
279 optlen - 4, "Link-layer address");
287 if (opttype == OPTION_IA_NA)
288 proto_tree_add_text(subtree, tvb, off,
289 optlen, "IA_NA: malformed option");
291 proto_tree_add_text(subtree, tvb, off,
292 optlen, "IA_PD: malformed option");
295 proto_tree_add_text(subtree, tvb, off, 4,
297 tvb_get_ntohl(tvb, off));
298 proto_tree_add_text(subtree, tvb, off+4, 4,
299 "T1: %u", tvb_get_ntohl(tvb, off+4));
300 proto_tree_add_text(subtree, tvb, off+8, 4,
301 "T2: %u", tvb_get_ntohl(tvb, off+8));
304 while ((optlen - temp_optlen) > 0) {
305 gboolean at_end_ = FALSE;
306 temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
311 proto_tree_add_text(subtree, tvb, off,
312 optlen, "IA_TA: malformed option");
315 proto_tree_add_text(subtree, tvb, off, 4,
317 tvb_get_ntohl(tvb, off));
319 while ((optlen - temp_optlen) > 0) {
321 temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
326 guint32 preferred_lifetime, valid_lifetime;
329 proto_tree_add_text(subtree, tvb, off,
330 optlen, "IAADDR: malformed option");
333 tvb_memcpy(tvb, (guint8 *)&in6, off, sizeof(in6));
334 proto_tree_add_text(subtree, tvb, off,
335 sizeof(in6), "IPv6 address: %s",
338 preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
339 valid_lifetime = tvb_get_ntohl(tvb, off + 20);
341 if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
342 proto_tree_add_text(subtree, tvb, off + 16, 4,
343 "Preferred lifetime: infinity");
345 proto_tree_add_text(subtree, tvb, off + 16, 4,
346 "Preferred lifetime: %u", preferred_lifetime);
348 if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
349 proto_tree_add_text(subtree, tvb, off + 20, 4,
350 "Valid lifetime: infinity");
352 proto_tree_add_text(subtree, tvb, off + 20, 4,
353 "Valid lifetime: %u", valid_lifetime);
357 while ((optlen - temp_optlen) > 0) {
359 temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
364 for (i = 0; i < optlen; i += 2) {
365 guint16 requested_opt_code;
366 requested_opt_code = tvb_get_ntohs(tvb, off + i);
367 proto_tree_add_text(subtree, tvb, off + i,
368 2, "Requested Option code: %s (%d)",
369 val_to_str(requested_opt_code,
375 case OPTION_PREFERENCE:
377 proto_tree_add_text(subtree, tvb, off,
378 optlen, "PREFERENCE: malformed option");
381 proto_tree_add_text(subtree, tvb, off, 1,
383 (guint32)tvb_get_guint8(tvb, off));
385 case OPTION_ELAPSED_TIME:
387 proto_tree_add_text(subtree, tvb, off,
388 optlen, "ELAPSED-TIME: malformed option");
391 proto_tree_add_text(subtree, tvb, off, 2,
392 "elapsed-time: %d sec",
393 (guint32)tvb_get_ntohs(tvb, off));
395 case OPTION_RELAY_MSG:
397 proto_tree_add_text(subtree, tvb, off,
398 optlen, "RELAY-MSG: malformed option");
402 dhcpv6_option(tvb, subtree, off, off + optlen, &at_end_);
407 proto_tree_add_text(subtree, tvb, off,
408 optlen, "AUTH: malformed option");
411 proto_tree_add_text(subtree, tvb, off, 1,
413 (guint32)tvb_get_guint8(tvb, off));
414 proto_tree_add_text(subtree, tvb, off+1, 1,
416 (guint32)tvb_get_guint8(tvb, off+1));
417 proto_tree_add_text(subtree, tvb, off+2, 1,
419 (guint32)tvb_get_guint8(tvb, off+2));
420 proto_tree_add_text(subtree, tvb, off+3, 8,
422 proto_tree_add_text(subtree, tvb, off+11, optlen-11,
423 "Authentication Information");
427 proto_tree_add_text(subtree, tvb, off,
428 optlen, "UNICAST: malformed option");
431 tvb_memcpy(tvb, (guint8 *)&in6, off, sizeof(in6));
432 proto_tree_add_text(subtree, tvb, off,
433 sizeof(in6), "IPv6 address: %s",
436 case OPTION_STATUS_CODE:
439 char *status_message = 0;
440 status_code = tvb_get_ntohs(tvb, off);
441 proto_tree_add_text(subtree, tvb, off, 2,
442 "Status Code: %s (%d)",
443 val_to_str(status_code, statuscode_vals,
448 status_message = g_malloc(optlen - 2 + 1);
449 if (status_message != 0){
450 memset(status_message, 0, optlen - 2 + 1);
451 status_message = tvb_memcpy(tvb, status_message, off + 2,
453 proto_tree_add_text(subtree, tvb, off + 2, optlen - 2,
454 "Status Message: %s",
456 g_free(status_message);
460 case OPTION_VENDOR_CLASS:
462 proto_tree_add_text(subtree, tvb, off,
463 optlen, "VENDOR_CLASS: malformed option");
466 proto_tree_add_text(subtree, tvb, off, 4,
467 "enterprise-number: %u",
468 tvb_get_ntohl(tvb, off));
470 proto_tree_add_text(subtree, tvb, off+4, optlen-4,
471 "vendor-class-data");
474 case OPTION_VENDOR_OPTS:
476 proto_tree_add_text(subtree, tvb, off,
477 optlen, "VENDOR_OPTS: malformed option");
480 proto_tree_add_text(subtree, tvb, off, 4,
481 "enterprise-number: %u",
482 tvb_get_ntohl(tvb, off));
484 proto_tree_add_text(subtree, tvb, off+4, optlen-4,
488 case OPTION_INTERFACE_ID:
490 proto_tree_add_text(subtree, tvb, off,
491 optlen, "INTERFACE_ID: malformed option");
494 proto_tree_add_text(subtree, tvb, off, optlen, "Interface-ID");
496 case OPTION_RECONF_MSG:
498 proto_tree_add_text(subtree, tvb, off,
499 optlen, "RECONF_MSG: malformed option");
502 proto_tree_add_text(subtree, tvb, off, optlen,
503 "Reconfigure-type: %s",
504 val_to_str(tvb_get_guint8(tvb, off),
508 /* case OPTION_DNS_SERVERS:
510 proto_tree_add_text(subtree, tvb, off, optlen,
511 "DNS servers address: malformed option");
514 for (i = 0; i < optlen; i += 16) {
515 tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
516 proto_tree_add_text(subtree, tvb, off + i,
517 sizeof(in6), "DNS servers address: %s",
522 case OPTION_DNS_RESOLVERS:
524 proto_tree_add_text(subtree, tvb, off, optlen,
525 "DNS resolvers address: malformed option");
528 for (i = 0; i < optlen; i += 16) {
529 tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
530 proto_tree_add_text(subtree, tvb, off + i,
531 sizeof(in6), "DNS resolvers address: %s",
535 case OPTION_DOMAIN_LIST:
537 proto_tree_add_text(subtree, tvb, off, optlen, "Search String");
540 case OPTION_NIS_SERVERS:
542 proto_tree_add_text(subtree, tvb, off, optlen,
543 "NIS servers address: malformed option");
546 for (i = 0; i < optlen; i += 16) {
547 tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
548 proto_tree_add_text(subtree, tvb, off + i,
549 sizeof(in6), "NIS servers address: %s",
553 case OPTION_NISP_SERVERS:
555 proto_tree_add_text(subtree, tvb, off, optlen,
556 "NISP servers address: malformed option");
559 for (i = 0; i < optlen; i += 16) {
560 tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
561 proto_tree_add_text(subtree, tvb, off + i,
562 sizeof(in6), "NISP servers address: %s",
566 case OPTION_NIS_DOMAIN_NAME:
568 proto_tree_add_text(subtree, tvb, off, optlen, "nis-domain-name");
571 case OPTION_NISP_DOMAIN_NAME:
573 proto_tree_add_text(subtree, tvb, off, optlen, "nisp-domain-name");
576 case OPTION_NTP_SERVERS:
578 proto_tree_add_text(subtree, tvb, off, optlen,
579 "NTP servers address: malformed option");
582 for (i = 0; i < optlen; i += 16) {
583 tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
584 proto_tree_add_text(subtree, tvb, off + i,
585 sizeof(in6), "NTP servers address: %s",
589 case OPTION_TIME_ZONE:
591 proto_tree_add_text(subtree, tvb, off, optlen, "time-zone");
594 case OPTION_IAPREFIX:
596 guint32 preferred_lifetime, valid_lifetime;
597 guint8 prefix_length;
598 struct e_in6_addr in6;
601 proto_tree_add_text(subtree, tvb, off,
602 optlen, "IAPREFIX: malformed option");
606 preferred_lifetime = tvb_get_ntohl(tvb, off);
607 valid_lifetime = tvb_get_ntohl(tvb, off + 4);
608 prefix_length = tvb_get_guint8(tvb, off + 8);
609 if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
610 proto_tree_add_text(subtree, tvb, off, 4,
611 "Preferred lifetime: infinity");
613 proto_tree_add_text(subtree, tvb, off, 4,
614 "Preferred lifetime: %u", preferred_lifetime);
616 if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
617 proto_tree_add_text(subtree, tvb, off + 4, 4,
618 "Valid lifetime: infinity");
620 proto_tree_add_text(subtree, tvb, off + 4, 4,
621 "Valid lifetime: %u", valid_lifetime);
623 proto_tree_add_text(subtree, tvb, off + 8, 1,
624 "Prefix length: %d", prefix_length);
625 tvb_memcpy(tvb, (guint8 *)&in6, off + 9 , sizeof(in6));
626 proto_tree_add_text(subtree, tvb, off + 9,
627 16, "Prefix address: %s",
631 while ((optlen - temp_optlen) > 0) {
633 temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
644 dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
647 proto_tree *bp_tree = NULL;
649 guint8 msgtype, hop_count ;
653 struct e_in6_addr in6;
655 gboolean relay_msg_option = FALSE;
658 eoff = tvb_reported_length(tvb);
659 downstream = 0; /* feature reserved */
660 if (check_col(pinfo->cinfo, COL_PROTOCOL))
661 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
662 if (check_col(pinfo->cinfo, COL_INFO))
663 col_clear(pinfo->cinfo, COL_INFO);
665 msgtype = tvb_get_guint8(tvb, off);
668 ti = proto_tree_add_item(tree, proto_dhcpv6, tvb, 0, -1, FALSE);
669 bp_tree = proto_item_add_subtree(ti, ett_dhcpv6);
672 while (msgtype == RELAY_FORW || msgtype == RELAY_REPL) {
674 if (check_col(pinfo->cinfo, COL_INFO)) {
675 col_set_str(pinfo->cinfo, COL_INFO,
681 proto_tree_add_uint(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, msgtype);
683 hop_count = tvb_get_guint8(tvb, off+1);
684 proto_tree_add_text(bp_tree, tvb, off+1, 1, "Hop count: %d", hop_count);
686 tvb_memcpy(tvb, (guint8 *)&in6, off+2, sizeof(in6));
687 proto_tree_add_text(bp_tree, tvb, off+2, sizeof(in6),
688 "Link-address: %s",ip6_to_str(&in6));
690 tvb_memcpy(tvb, (guint8 *)&in6, off+18, sizeof(in6));
691 proto_tree_add_text(bp_tree, tvb, off+18, sizeof(in6),
692 "Peer-address: %s",ip6_to_str(&in6));
695 relay_msg_option = FALSE;
697 while (!relay_msg_option && off < eoff) {
698 length = dhcpv6_option(tvb, bp_tree, off, eoff, &at_end);
700 if (tvb_get_ntohs(tvb, off) == OPTION_RELAY_MSG) {
701 relay_msg_option = TRUE;
708 proto_tree_add_text(bp_tree, tvb, off, eoff, "Message: malformed");
714 msgtype = tvb_get_guint8(tvb, off);
717 xid = tvb_get_ntohl(tvb, off) & 0x00ffffff;
720 if (check_col(pinfo->cinfo, COL_INFO)) {
721 col_set_str(pinfo->cinfo, COL_INFO,
729 proto_tree_add_uint(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1,
731 proto_tree_add_text(bp_tree, tvb, off+1, 3, "Transaction-ID: 0x%08x", xid);
733 tvb_memcpy(tvb, (guint8 *)&in6, 4, sizeof(in6));
734 proto_tree_add_text(bp_tree, tvb, 4, sizeof(in6),
735 "Server address: %s", ip6_to_str(&in6));
742 while (off < eoff && !at_end)
743 off += dhcpv6_option(tvb, bp_tree, off, eoff, &at_end);
747 dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
749 dissect_dhcpv6(tvb, pinfo, tree, TRUE);
753 dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
755 dissect_dhcpv6(tvb, pinfo, tree, FALSE);
760 proto_register_dhcpv6(void)
762 static hf_register_info hf[] = {
763 { &hf_dhcpv6_msgtype,
764 { "Message type", "dhcpv6.msgtype", FT_UINT8,
765 BASE_DEC, VALS(msgtype_vals), 0x0,
768 static gint *ett[] = {
773 proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
774 proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
775 proto_register_subtree_array(ett, array_length(ett));
779 proto_reg_handoff_dhcpv6(void)
781 dissector_handle_t dhcpv6_handle;
783 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_downstream,
785 dissector_add("udp.port", UDP_PORT_DHCPV6_DOWNSTREAM, dhcpv6_handle);
786 dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_upstream,
788 dissector_add("udp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_handle);