2 * Routines for ICMPv6 packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
11 * Copyright 2006, Nicolas DICHTEL - 6WIND - <nicolas.dichtel@6wind.com>
13 * HMIPv6 support added by Martti Kuparinen <martti.kuparinen@iki.fi>
15 * FMIPv6 support added by Martin Andre <andre@clarinet.u-strasbg.fr>
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 #include <epan/packet.h>
48 #include <epan/in_cksum.h>
49 #include <epan/addr_resolv.h>
50 #include <epan/ipproto.h>
51 #include <epan/emem.h>
52 #include <epan/asn1.h>
53 #include <epan/strutil.h>
55 #include "packet-ber.h"
56 #include "packet-ipv6.h"
57 #include "packet-dns.h"
58 #include "packet-x509af.h"
59 #include "packet-x509if.h"
63 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
67 * See, under http://www.ietf.org/internet-drafts/
69 * draft-ietf-mobileip-ipv6-15.txt
73 * draft-ietf-ipngwg-icmp-name-lookups-08.txt
77 * draft-ietf-mobileip-hmipv6-05.txt
84 static int proto_icmpv6 = -1;
85 static int hf_icmpv6_type = -1;
86 static int hf_icmpv6_code = -1;
87 static int hf_icmpv6_checksum = -1;
88 static int hf_icmpv6_checksum_bad = -1;
89 static int hf_icmpv6_haad_ha_addrs = -1;
90 static int hf_icmpv6_ra_cur_hop_limit = -1;
91 static int hf_icmpv6_ra_router_lifetime = -1;
92 static int hf_icmpv6_ra_reachable_time = -1;
93 static int hf_icmpv6_ra_retrans_timer = -1;
95 static int hf_icmpv6_option = -1;
96 static int hf_icmpv6_option_type = -1;
97 static int hf_icmpv6_option_length = -1;
98 static int hf_icmpv6_opt_cga_pad_len = -1;
99 static int hf_icmpv6_opt_cga = -1;
100 static int hf_icmpv6_opt_rsa_key_hash = -1;
101 static int hf_icmpv6_opt_name_type = -1;
102 static int hf_icmpv6_opt_name_x501 = -1;
103 static int hf_icmpv6_opt_name_fqdn = -1;
104 static int hf_icmpv6_opt_cert_type = -1;
105 static int hf_icmpv6_identifier = -1;
106 static int hf_icmpv6_all_comp = -1;
107 static int hf_icmpv6_comp = -1;
108 static int hf_icmpv6_x509if_Name = -1;
109 static int hf_icmpv6_x509af_Certificate = -1;
111 static gint ett_icmpv6 = -1;
112 static gint ett_icmpv6opt = -1;
113 static gint ett_icmpv6flag = -1;
114 static gint ett_nodeinfo_flag = -1;
115 static gint ett_nodeinfo_subject4 = -1;
116 static gint ett_nodeinfo_subject6 = -1;
117 static gint ett_nodeinfo_node4 = -1;
118 static gint ett_nodeinfo_node6 = -1;
119 static gint ett_nodeinfo_nodebitmap = -1;
120 static gint ett_nodeinfo_nodedns = -1;
121 static gint ett_multicastRR = -1;
122 static gint ett_icmpv6opt_name = -1;
124 static dissector_handle_t ipv6_handle;
125 static dissector_handle_t data_handle;
127 static const value_string names_nodeinfo_qtype[] = {
128 { NI_QTYPE_NOOP, "NOOP" },
129 { NI_QTYPE_SUPTYPES, "Supported query types" },
130 { NI_QTYPE_DNSNAME, "DNS name" },
131 { NI_QTYPE_NODEADDR, "Node addresses" },
132 { NI_QTYPE_IPV4ADDR, "IPv4 node addresses" },
136 static const value_string names_rrenum_matchcode[] = {
137 { RPM_PCO_ADD, "Add" },
138 { RPM_PCO_CHANGE, "Change" },
139 { RPM_PCO_SETGLOBAL, "Set Global" },
143 static const value_string names_router_pref[] = {
144 { ND_RA_FLAG_RTPREF_HIGH, "High" },
145 { ND_RA_FLAG_RTPREF_MEDIUM, "Medium" },
146 { ND_RA_FLAG_RTPREF_LOW, "Low" },
147 { ND_RA_FLAG_RTPREF_RSV, "Reserved" },
151 static const value_string names_fmip6_prrtadv_code[] = {
152 { FMIP6_PRRTADV_MNTUP, "MN should use AP-ID, AR-info tuple" },
153 { FMIP6_PRRTADV_NI_HOVER, "Network Initiated Handover trigger" },
154 { FMIP6_PRRTADV_NORTINFO, "No new router information" },
155 { FMIP6_PRRTADV_LIMRTINFO, "Limited new router information" },
156 { FMIP6_PRRTADV_UNSOL, "Unsolicited" },
160 static const value_string names_fmip6_hi_code[] = {
161 { FMIP6_HI_PCOA, "FBU sent from previous link" },
162 { FMIP6_HI_NOTPCOA, "FBU sent from new link" },
166 static const value_string names_fmip6_hack_code[] = {
167 { FMIP6_HACK_VALID, "Handover Accepted, NCoA valid" },
168 { FMIP6_HACK_INVALID, "Handover Accepted, NCoA not valid" },
169 { FMIP6_HACK_INUSE, "Handover Accepted, NCoA in use" },
170 { FMIP6_HACK_ASSIGNED, "Handover Accepted, NCoA assigned" },
171 { FMIP6_HACK_NOTASSIGNED, "Handover Accepted, NCoA not assigned" },
172 { FMIP6_HACK_NOTACCEPTED, "Handover Not Accepted, reason unspecified" },
173 { FMIP6_HACK_PROHIBITED, "Administratively prohibited" },
174 { FMIP6_HACK_INSUFFICIENT, "Insufficient resources" },
178 static const value_string names_fmip6_ip_addr_opt_code[] = {
179 { FMIP6_OPT_IP_ADDRESS_OPTCODE_PCOA, "Old Care-of Address" },
180 { FMIP6_OPT_IP_ADDRESS_OPTCODE_NCOA, "New Care-of Address" },
181 { FMIP6_OPT_IP_ADDRESS_OPTCODE_NAR, "NAR's IP address" },
185 static const value_string names_fmip6_lla_opt_code[] = {
186 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_WILDCARD, "Wildcard" },
187 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAP, "Link-layer Address of the New Access Point" },
188 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_MN, "Link-layer Address of the MN" },
189 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAR, "Link-layer Address of the NAR" },
190 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_SRC, "Link-layer Address of the source" },
191 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_CURROUTER, "The AP belongs to the current interface of the router" },
192 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOPREFIX, "No prefix information available" },
193 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOSUPPORT, "No fast handovers support available" },
197 static const value_string names_fmip6_naack_opt_status[] = {
198 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID, "New CoA is invalid" },
199 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID_NEW, "New CoA is invalid, use the supplied CoA" },
200 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_UNRECOGNIZED, "LLA is unrecognized" },
204 /* http://www.iana.org/assignments/icmpv6-parameters */
205 static const value_string option_vals[] = {
206 { ND_OPT_SOURCE_LINKADDR, "Source link-layer address" },
207 { ND_OPT_TARGET_LINKADDR, "Target link-layer address" },
208 { ND_OPT_PREFIX_INFORMATION, "Prefix information" },
209 { ND_OPT_REDIRECTED_HEADER, "Redirected header" },
210 { ND_OPT_MTU, "MTU" },
211 { ND_OPT_ADVINTERVAL, "Advertisement Interval" },
212 { ND_OPT_HOMEAGENT_INFO, "Home Agent Information" },
213 { ND_OPT_CGA, "CGA" }, /* [RFC3971] */
214 { ND_OPT_RSA, "RSA Signature" }, /* [RFC3971] */
215 { ND_OPT_TIMESTAMP, "Timestamp" }, /* [RFC3971] */
216 { ND_OPT_NONCE, "Nonce" }, /* [RFC3971] */
217 { ND_OPT_TRUST_ANCHOR, "Trust Anchor" }, /* [RFC3971] */
218 { 16, "Certificate" }, /* [RFC3971] */
219 { FMIP6_OPT_IP_ADDRESS, "IP Address Option" }, /* [RFC4068] */
220 { FMIP6_OPT_NEW_ROUTER_PREFIX_INFO, "New Router Prefix Information" }, /* [RFC4068] */
221 { FMIP6_OPT_LINK_LAYER_ADDRESS, "Link-layer Address" }, /* [RFC4068] */
222 { FMIP6_OPT_NEIGHBOR_ADV_ACK, "Neighbor Advertisement Acknowledgment" }, /* [RFC4068] */
223 { 21, "CARD Request" }, /* [RFC4065] */
224 { 22, "CARD Reply" }, /* [RFC4065] */
225 { 23, "MAP" }, /* [RFC4140] */
226 { 24, "Route Information" }, /* [RFC4191] */
227 { 25, "Recursive DNS Server" }, /* [RFC5006] */
228 { 26, "RA Flags Extension" }, /* [RFC5075] */
229 { 27, "Handover Key Request" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
230 { 28, "Handover Key Reply" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
231 { ND_OPT_MAP, "HMIPv6 MAP option" },
232 /*29-252 Unassigned */
233 { 253, "RFC3692-style Experiment 1" }, /* [RFC4727] */
234 { 254, "RFC3692-style Experiment 2" }, /* [RFC4727] */
238 static const value_string icmpv6_option_name_type_vals[] = {
239 { 1, "DER Encoded X.501 Name" },
244 static const value_string icmpv6_option_cert_type_vals[] = {
245 { 1, "X.509v3 Certificate" },
250 dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
252 gboolean save_in_error_pkt;
255 /* Save the current value of the "we're inside an error packet"
256 flag, and set that flag; subdissectors may treat packets
257 that are the payload of error packets differently from
259 save_in_error_pkt = pinfo->in_error_pkt;
260 pinfo->in_error_pkt = TRUE;
262 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
264 /* tiny sanity check */
265 if ((tvb_get_guint8(tvb, offset) & 0xf0) == 0x60) {
266 /* The contained packet is an IPv6 datagram; dissect it. */
267 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
269 call_dissector(data_handle,next_tvb, pinfo, tree);
271 /* Restore the "we're inside an error packet" flag. */
272 pinfo->in_error_pkt = save_in_error_pkt;
276 dissect_icmpv6ndopt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
278 proto_tree *icmp6opt_tree, *field_tree, *name_tree;
279 proto_item *ti, *tf, *name_item;
280 struct nd_opt_hdr nd_opt_hdr, *opt;
282 const char *typename;
283 static const guint8 nd_redirect_reserved[6] = {0, 0, 0, 0, 0, 0};
284 guint8 nd_redirect_res[6];
286 guint8 padd_length = 0;
288 guint8 name_type = 0;
289 guint8 cert_type = 0;
297 if ((int)tvb_reported_length(tvb) <= offset)
298 return; /* No more options left */
301 tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
302 len = opt->nd_opt_len << 3;
304 /* !!! specify length */
305 ti = proto_tree_add_item(tree, hf_icmpv6_option, tvb, offset, len, FALSE);
306 icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
309 proto_tree_add_text(icmp6opt_tree, tvb,
310 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
311 "Invalid option length: %u",
313 return; /* we must not try to decode this */
316 typename = val_to_str(opt->nd_opt_type, option_vals, "Unknown");
318 /* Add option name to option root label */
319 proto_item_append_text(ti, " (%s)", typename);
322 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_option_type, tvb,
323 offset + offsetof(struct nd_opt_hdr, nd_opt_type), 1, FALSE);
325 proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_option_length, tvb,
326 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
327 opt->nd_opt_len << 3);
330 switch (opt->nd_opt_type) {
331 case ND_OPT_SOURCE_LINKADDR:
332 case ND_OPT_TARGET_LINKADDR:
336 p = offset + sizeof(*opt);
337 len = (opt->nd_opt_len << 3) - sizeof(*opt);
338 proto_tree_add_text(icmp6opt_tree, tvb,
339 offset + sizeof(*opt), len, "Link-layer address: %s",
340 bytestring_to_str(tvb_get_ptr(tvb, p, len), len, ':'));
343 case ND_OPT_PREFIX_INFORMATION:
345 struct nd_opt_prefix_info nd_opt_prefix_info, *pi;
348 pi = &nd_opt_prefix_info;
349 tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
350 proto_tree_add_text(icmp6opt_tree, tvb,
351 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix_len),
352 1, "Prefix length: %u", pi->nd_opt_pi_prefix_len);
354 flagoff = offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved);
355 tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1, "Flags: 0x%02x",
356 tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved)));
357 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
358 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
359 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
360 ND_OPT_PI_FLAG_ONLINK, 8, "Onlink", "Not onlink"));
361 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
362 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
363 ND_OPT_PI_FLAG_AUTO, 8, "Auto", "Not auto"));
364 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
365 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
366 ND_OPT_PI_FLAG_ROUTER, 8,
367 "Router Address", "Not router address"));
368 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
369 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
370 ND_OPT_PI_FLAG_SITEPREF, 8,
371 "Site prefix", "Not site prefix"));
372 if (pntohl(&pi->nd_opt_pi_valid_time) == 0xffffffff)
373 proto_tree_add_text(icmp6opt_tree, tvb,
374 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
375 4, "Valid lifetime: infinity");
377 proto_tree_add_text(icmp6opt_tree, tvb,
378 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
379 4, "Valid lifetime: %u",
380 pntohl(&pi->nd_opt_pi_valid_time));
381 if (pntohl(&pi->nd_opt_pi_preferred_time) == 0xffffffff)
382 proto_tree_add_text(icmp6opt_tree, tvb,
383 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
384 4, "Preferred lifetime: infinity");
386 proto_tree_add_text(icmp6opt_tree, tvb,
387 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
388 4, "Preferred lifetime: %u",
389 pntohl(&pi->nd_opt_pi_preferred_time));
390 proto_tree_add_text(icmp6opt_tree, tvb,
391 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix),
392 16, "Prefix: %s", ip6_to_str(&pi->nd_opt_pi_prefix));
395 case ND_OPT_REDIRECTED_HEADER:
396 tvb_memcpy(tvb, (guint8 *)&nd_redirect_res, offset + 2, 6);
397 if (memcmp(nd_redirect_res, nd_redirect_reserved, 6) == 0)
398 proto_tree_add_text(icmp6opt_tree, tvb,
399 offset + 2, 6, "Reserved: 0 (correct)");
401 proto_tree_add_text(icmp6opt_tree, tvb,
402 offset +2, 6, "Reserved: MUST be 0 (incorrect!)");
403 proto_tree_add_text(icmp6opt_tree, tvb,
404 offset + 8, (opt->nd_opt_len << 3) - 8, "Redirected packet");
405 dissect_contained_icmpv6(tvb, offset + 8, pinfo, icmp6opt_tree);
408 proto_tree_add_text(icmp6opt_tree, tvb,
409 offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu), 4,
410 "MTU: %u", tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu)));
412 case ND_OPT_ADVINTERVAL:
413 proto_tree_add_text(icmp6opt_tree, tvb,
414 offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint), 4,
415 "Advertisement Interval: %u",
416 tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint)));
418 case ND_OPT_HOMEAGENT_INFO: /* 8 */
420 struct nd_opt_ha_info pibuf, *pi;
423 tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
424 proto_tree_add_text(icmp6opt_tree, tvb,
425 offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_pref),
426 2, "Home Agent Preference: %d",
427 (gint16)pntohs(&pi->nd_opt_ha_info_ha_pref));
428 proto_tree_add_text(icmp6opt_tree, tvb,
429 offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_life),
430 2, "Home Agent Lifetime: %u",
431 pntohs(&pi->nd_opt_ha_info_ha_life));
434 case ND_OPT_CGA: /* 11 */
435 /* RFC 3971 5.1. CGA Option */
437 opt_offset = offset +2;
438 padd_length = tvb_get_guint8(tvb,opt_offset);
439 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
441 /* Reserved 8 bits */
442 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
444 /* CGA Parameters A variable-length field containing the CGA Parameters data
445 * structure described in Section 4 of
446 * "Cryptographically Generated Addresses (CGA)", RFC3972.
448 par_len = len-4-padd_length;
449 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga, tvb, opt_offset, par_len, FALSE);
450 opt_offset = opt_offset + par_len;
452 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
454 case ND_OPT_RSA: /* 12 */
455 /*5.2. RSA Signature Option */
456 opt_offset = offset +2;
457 /* Reserved, A 16-bit field reserved for future use. */
458 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Reserved");
459 opt_offset = opt_offset + 2;
461 * A 128-bit field containing the most significant (leftmost) 128
462 * bits of a SHA-1 [14] hash of the public key used for constructing
465 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_rsa_key_hash, tvb, opt_offset, 16, FALSE);
466 opt_offset = opt_offset + 16;
467 /* Digital Signature */
469 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Digital Signature + Padding");
471 /* TODO: Calculate padding length and exlude from the signature */
473 case ND_OPT_TIMESTAMP: /* 13 */
474 opt_offset = offset +2;
475 /* Reserved A 48-bit field reserved for future use. */
476 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Reserved");
477 opt_offset = opt_offset + 6;
479 * A 64-bit unsigned integer field containing a timestamp. The value
480 * indicates the number of seconds since January 1, 1970, 00:00 UTC,
481 * by using a fixed point format. In this format, the integer number
482 * of seconds is contained in the first 48 bits of the field, and the
483 * remaining 16 bits indicate the number of 1/64K fractions of a
486 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Timestamp(number of seconds since January 1, 1970, 00:00 UTC)");
487 opt_offset = opt_offset + 6;
488 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Timestamp(1/64K fractions of a second)");
491 /* 5.3.2. Nonce Option */
492 opt_offset = offset +2;
495 case ND_OPT_TRUST_ANCHOR:
496 opt_offset = offset +2;
498 name_type = tvb_get_guint8(tvb,opt_offset);
499 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_type, tvb, opt_offset, 1, FALSE);
502 padd_length = tvb_get_guint8(tvb,opt_offset);
503 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
505 par_len = len - 4 - padd_length;
508 /* DER Encoded X.501 Name */
509 name_item =proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_x501, tvb, opt_offset, par_len, FALSE);
510 name_tree = proto_item_add_subtree(name_item, ett_icmpv6opt_name);
511 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
512 dissect_x509if_Name(FALSE, tvb, opt_offset, &asn1_ctx, name_tree, hf_icmpv6_x509if_Name);
516 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_fqdn, tvb, opt_offset, par_len, FALSE);
519 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset, par_len,"Unknown name type");
522 opt_offset = opt_offset + par_len;
524 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
525 opt_offset = opt_offset + padd_length;
527 case ND_OPT_CERTIFICATE:
528 opt_offset = offset +2;
530 cert_type = tvb_get_guint8(tvb,opt_offset);
531 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cert_type, tvb, opt_offset, 1, FALSE);
534 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
539 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
540 opt_offset = dissect_x509af_Certificate(FALSE, tvb, opt_offset, &asn1_ctx, icmp6opt_tree, hf_icmpv6_x509af_Certificate);
541 par_len = len - (opt_offset - offset);
543 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Padding");
546 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Unknown Certificate + padding");
552 struct nd_opt_map_info mapbuf, *map;
556 tvb_memcpy(tvb, (guint8 *)map, offset, sizeof *map);
557 proto_tree_add_text(icmp6opt_tree, tvb,
558 offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
559 1, "Distance: %u", (map->nd_opt_map_dist_and_pref >> 4));
560 proto_tree_add_text(icmp6opt_tree, tvb,
561 offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
562 1, "Preference: %u", (map->nd_opt_map_dist_and_pref & 0x0F));
563 flagoff = offset + offsetof(struct nd_opt_map_info,
565 tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
567 tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_map_info,
569 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
570 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
571 decode_boolean_bitfield(map->nd_opt_map_flags,
572 ND_OPT_MAP_FLAG_R, 8, "R", "No R"));
573 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
574 decode_boolean_bitfield(map->nd_opt_map_flags,
575 ND_OPT_MAP_FLAG_M, 8, "M", "No M"));
576 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
577 decode_boolean_bitfield(map->nd_opt_map_flags,
578 ND_OPT_MAP_FLAG_I, 8, "I", "No I"));
579 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
580 decode_boolean_bitfield(map->nd_opt_map_flags,
581 ND_OPT_MAP_FLAG_T, 8, "T", "No T"));
582 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
583 decode_boolean_bitfield(map->nd_opt_map_flags,
584 ND_OPT_MAP_FLAG_P, 8, "P", "No P"));
585 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
586 decode_boolean_bitfield(map->nd_opt_map_flags,
587 ND_OPT_MAP_FLAG_V, 8, "V", "No V"));
588 proto_tree_add_text(icmp6opt_tree, tvb,
589 offset + offsetof(struct nd_opt_map_info, nd_opt_map_lifetime),
590 4, "Lifetime: %u", pntohl(&map->nd_opt_map_lifetime));
592 proto_tree_add_text(icmp6opt_tree, tvb,
593 offset + offsetof(struct nd_opt_map_info, nd_opt_map_address), 16,
595 "Address of MAP: %s (%s)",
596 get_hostname6(&map->nd_opt_map_address),
598 "Address of MAP: %s",
600 ip6_to_str(&map->nd_opt_map_address));
603 case ND_OPT_ROUTE_INFO:
605 struct nd_opt_route_info ribuf, *ri;
606 struct e_in6_addr in6;
611 tvb_memcpy(tvb, (guint8 *)ri, offset, sizeof *ri);
612 memset(&in6, 0, sizeof(in6));
613 switch (ri->nd_opt_rti_len) {
618 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 8);
621 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 16);
628 proto_tree_add_text(icmp6opt_tree, tvb,
629 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_prefixlen),
630 1, "Prefix length: %u", ri->nd_opt_rti_prefixlen);
631 tf = proto_tree_add_text(icmp6opt_tree, tvb,
632 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
633 1, "Flags: 0x%02x", ri->nd_opt_rti_flags);
634 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
635 proto_tree_add_text(field_tree, tvb,
636 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
638 decode_enumerated_bitfield(ri->nd_opt_rti_flags,
639 ND_RA_FLAG_RTPREF_MASK, 8, names_router_pref,
640 "Router preference: %s"));
641 lifetime = pntohl(&ri->nd_opt_rti_lifetime);
642 if (lifetime == 0xffffffff)
643 proto_tree_add_text(icmp6opt_tree, tvb,
644 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
645 sizeof(ri->nd_opt_rti_lifetime), "Lifetime: infinity");
647 proto_tree_add_text(icmp6opt_tree, tvb,
648 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
649 sizeof(ri->nd_opt_rti_lifetime), "Lifetime: %u", lifetime);
650 proto_tree_add_text(icmp6opt_tree, tvb,
651 offset + sizeof(*ri), l, "Prefix: %s", ip6_to_str(&in6));
653 proto_tree_add_text(icmp6opt_tree, tvb,
654 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
655 "Invalid option length: %u", opt->nd_opt_len);
660 case FMIP6_OPT_NEIGHBOR_ADV_ACK:
662 struct fmip6_opt_neighbor_advertisement_ack fmip6_opt_neighbor_advertisement_ack, *opt_naack;
663 struct e_in6_addr in6;
665 opt_naack = &fmip6_opt_neighbor_advertisement_ack;
666 tvb_memcpy(tvb, (guint8 *)opt_naack, offset, sizeof *opt_naack);
668 proto_tree_add_text(icmp6opt_tree, tvb,
669 offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_optcode),
670 1, "Option-Code: %u",
671 opt_naack->fmip6_opt_optcode);
673 proto_tree_add_text(icmp6opt_tree, tvb,
674 offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_status),
676 val_to_str(opt_naack->fmip6_opt_status, names_fmip6_naack_opt_status, "Unknown"));
678 if (opt_naack->fmip6_opt_len == 3)
680 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*opt_naack), 16);
681 proto_tree_add_text(icmp6opt_tree, tvb,
682 offset + sizeof(*opt_naack),
683 16, "New Care-of Address: %s",
691 offset += (opt->nd_opt_len << 3);
693 /* Set length of option tree */
694 proto_item_set_len(ti, opt->nd_opt_len << 3);
699 dissect_icmpv6fmip6opt(tvbuff_t *tvb, int offset, proto_tree *tree)
701 proto_tree *icmp6opt_tree;
703 struct fmip6_opt_hdr fmip6_opt_hdr, *opt;
711 if ((int)tvb_reported_length(tvb) <= offset)
712 return; /* No more options left */
714 opt = &fmip6_opt_hdr;
715 tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
716 len = opt->fmip6_opt_len << 3;
718 /* !!! specify length */
719 ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
720 icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
723 proto_tree_add_text(icmp6opt_tree, tvb,
724 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
725 "Invalid option length: %u",
727 return; /* we must not try to decode this */
730 switch (opt->fmip6_opt_type) {
731 case FMIP6_OPT_IP_ADDRESS:
732 typename = "IP Address";
734 case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
735 typename = "New Router Prefix Information";
737 case FMIP6_OPT_LINK_LAYER_ADDRESS:
738 typename = "Link-layer Address";
741 typename = "Unknown";
745 proto_tree_add_text(icmp6opt_tree, tvb,
746 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_type), 1,
747 "Type: %u (%s)", opt->fmip6_opt_type, typename);
748 proto_tree_add_text(icmp6opt_tree, tvb,
749 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
750 "Length: %u bytes (%u)", opt->fmip6_opt_len << 3, opt->fmip6_opt_len);
753 switch (opt->fmip6_opt_type) {
754 case FMIP6_OPT_IP_ADDRESS:
756 struct fmip6_opt_ip_address fmip6_opt_ip_address, *opt_ip;
758 opt_ip = &fmip6_opt_ip_address;
759 tvb_memcpy(tvb, (guint8 *)opt_ip, offset, sizeof *opt_ip);
761 proto_tree_add_text(icmp6opt_tree, tvb,
762 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
763 val_to_str(opt->fmip6_opt_optcode, names_fmip6_ip_addr_opt_code, "Unknown"));
765 proto_tree_add_text(icmp6opt_tree, tvb,
766 offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_prefix_len),
767 1, "Prefix length: %u", opt_ip->fmip6_opt_prefix_len);
769 proto_tree_add_text(icmp6opt_tree, tvb,
770 offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_ip6_address),
771 16, "IPv6 Address: %s",
772 ip6_to_str(&opt_ip->fmip6_opt_ip6_address));
775 case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
777 struct fmip6_opt_new_router_prefix_info fmip6_opt_new_router_prefix_info, *opt_nr;
779 opt_nr = &fmip6_opt_new_router_prefix_info;
780 tvb_memcpy(tvb, (guint8 *)opt_nr, offset, sizeof *opt_nr);
782 proto_tree_add_text(icmp6opt_tree, tvb,
783 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %u",
784 opt->fmip6_opt_optcode);
786 proto_tree_add_text(icmp6opt_tree, tvb,
787 offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix_len),
788 1, "Prefix length: %u", opt_nr->fmip6_opt_prefix_len);
790 proto_tree_add_text(icmp6opt_tree, tvb,
791 offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix),
793 ip6_to_str(&opt_nr->fmip6_opt_prefix));
796 case FMIP6_OPT_LINK_LAYER_ADDRESS:
800 p = offset + sizeof(*opt);
801 proto_tree_add_text(icmp6opt_tree, tvb,
802 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
803 val_to_str(opt->fmip6_opt_optcode, names_fmip6_lla_opt_code, "Unknown"));
804 len = (opt->fmip6_opt_len << 3) - sizeof(*opt);
805 proto_tree_add_text(icmp6opt_tree, tvb,
806 offset + sizeof(*opt), len, "Link-layer address: %s",
807 bytestring_to_str(tvb_get_ptr(tvb, p, len), len, ':'));
812 offset += (opt->fmip6_opt_len << 3);
817 * draft-ietf-ipngwg-icmp-name-lookups-07.txt
818 * Note that the packet format was changed several times in the past.
822 bitrange0(guint32 v, int s, char *buf, int buflen)
838 ep = buf + buflen - 1;
839 memset(buf, 0, buflen);
842 /* shift till we have 0x01 */
843 if ((v & 0x01) == 0) {
846 v >>= 4; off += 4; continue;
848 v >>= 3; off += 3; continue;
849 case 0x04: case 0x0c:
850 v >>= 2; off += 2; continue;
852 v >>= 1; off += 1; continue;
856 /* we have 0x01 with us */
857 for (i = 0; i < 32 - off; i++) {
858 if ((v & (0x01 << i)) == 0)
862 l = g_snprintf(p, ep - p, ",%d", s + off);
864 l = g_snprintf(p, ep - p, ",%d-%d", s + off,
867 if (l == -1 || l >= ep - p) {
877 bitrange(tvbuff_t *tvb, int offset, int l, int s)
879 static char buf[1024];
883 memset(buf, 0, sizeof(buf));
885 eq = buf + sizeof(buf) - 1;
886 for (i = 0; i < l; i++) {
887 if (bitrange0(tvb_get_ntohl(tvb, offset + i * 4), s + i * 4, q, eq - q) == NULL) {
888 if (q != buf && q + 5 < buf + sizeof(buf))
889 g_strlcpy(q, ",...", 5);
898 dissect_nodeinfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
900 proto_tree *field_tree;
902 struct icmp6_nodeinfo icmp6_nodeinfo, *ni;
910 ni = &icmp6_nodeinfo;
911 tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
913 flags = pntohs(&ni->ni_flags);
914 tf = proto_tree_add_text(tree, tvb,
915 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
916 sizeof(ni->ni_flags), "Flags: 0x%04x", flags);
917 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_flag);
918 switch (pntohs(&ni->ni_qtype)) {
919 case NI_QTYPE_SUPTYPES:
920 if (ni->ni_type == ICMP6_NI_QUERY) {
921 proto_tree_add_text(field_tree, tvb,
922 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
923 sizeof(ni->ni_flags), "%s",
924 decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
925 "Compressed reply supported",
926 "No compressed reply support"));
928 proto_tree_add_text(field_tree, tvb,
929 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
930 sizeof(ni->ni_flags), "%s",
931 decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
932 "Compressed", "Not compressed"));
935 case NI_QTYPE_DNSNAME:
936 if (ni->ni_type == ICMP6_NI_REPLY) {
937 proto_tree_add_text(field_tree, tvb,
938 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
939 sizeof(ni->ni_flags), "%s",
940 decode_boolean_bitfield(flags, NI_FQDN_FLAG_VALIDTTL, sizeof(flags) * 8,
941 "Valid TTL field", "Meaningless TTL field"));
944 case NI_QTYPE_NODEADDR:
945 proto_tree_add_text(field_tree, tvb,
946 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
947 sizeof(ni->ni_flags), "%s",
948 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_GLOBAL, sizeof(flags) * 8,
950 "Not global address"));
951 proto_tree_add_text(field_tree, tvb,
952 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
953 sizeof(ni->ni_flags), "%s",
954 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_SITELOCAL, sizeof(flags) * 8,
955 "Site-local address",
956 "Not site-local address"));
957 proto_tree_add_text(field_tree, tvb,
958 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
959 sizeof(ni->ni_flags), "%s",
960 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_LINKLOCAL, sizeof(flags) * 8,
961 "Link-local address",
962 "Not link-local address"));
963 proto_tree_add_text(field_tree, tvb,
964 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
965 sizeof(ni->ni_flags), "%s",
966 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_COMPAT, sizeof(flags) * 8,
967 "IPv4 compatible/mapped address",
968 "Not IPv4 compatible/mapped address"));
970 case NI_QTYPE_IPV4ADDR:
971 proto_tree_add_text(field_tree, tvb,
972 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
973 sizeof(ni->ni_flags), "%s",
974 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_ALL, sizeof(flags) * 8,
975 "All unicast address",
976 "Unicast addresses on the queried interface"));
977 proto_tree_add_text(field_tree, tvb,
978 offset + offsetof(struct icmp6_nodeinfo, ni_flags),
979 sizeof(ni->ni_flags), "%s",
980 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_TRUNCATE, sizeof(flags) * 8,
981 "Truncated", "Not truncated"));
986 proto_tree_add_text(tree, tvb,
987 offset + offsetof(struct icmp6_nodeinfo, icmp6_ni_nonce[0]),
988 sizeof(ni->icmp6_ni_nonce), "Nonce: 0x%08x%08x",
989 pntohl(&ni->icmp6_ni_nonce[0]), pntohl(&ni->icmp6_ni_nonce[4]));
991 /* offset for "the rest of data" */
995 if (!tvb_bytes_exist(tvb, offset, sizeof(*ni)))
997 if (ni->ni_type == ICMP6_NI_QUERY) {
998 switch (ni->ni_code) {
999 case ICMP6_NI_SUBJ_IPV6:
1000 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1001 n /= sizeof(struct e_in6_addr);
1002 tf = proto_tree_add_text(tree, tvb,
1003 offset + sizeof(*ni), -1, "IPv6 subject addresses");
1004 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject6);
1005 p = offset + sizeof *ni;
1006 for (i = 0; i < n; i++) {
1007 struct e_in6_addr e_in6_addr;
1008 tvb_get_ipv6(tvb, p, &e_in6_addr);
1009 proto_tree_add_text(field_tree, tvb,
1010 p, sizeof(struct e_in6_addr),
1011 "%s", ip6_to_str(&e_in6_addr));
1012 p += sizeof(struct e_in6_addr);
1014 off = tvb_length_remaining(tvb, offset);
1016 case ICMP6_NI_SUBJ_FQDN:
1017 l = get_dns_name(tvb, offset + sizeof(*ni),
1018 offset + sizeof(*ni), &dname);
1019 if (tvb_bytes_exist(tvb, offset + sizeof(*ni) + l, 1) &&
1020 tvb_get_guint8(tvb, offset + sizeof(*ni) + l) == 0) {
1022 proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
1023 "DNS label: %s (truncated)", dname);
1025 proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
1026 "DNS label: %s", dname);
1028 off = tvb_length_remaining(tvb, offset + sizeof(*ni) + l);
1030 case ICMP6_NI_SUBJ_IPV4:
1031 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1032 n /= sizeof(guint32);
1033 tf = proto_tree_add_text(tree, tvb,
1034 offset + sizeof(*ni), -1, "IPv4 subject addresses");
1035 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject4);
1036 p = offset + sizeof *ni;
1037 for (i = 0; i < n; i++) {
1038 ipaddr = tvb_get_ipv4(tvb, p);
1039 proto_tree_add_text(field_tree, tvb,
1040 p, sizeof(guint32), "%s", ip_to_str((guint8 *)&ipaddr));
1041 p += sizeof(guint32);
1043 off = tvb_length_remaining(tvb, offset);
1047 switch (pntohs(&ni->ni_qtype)) {
1050 case NI_QTYPE_SUPTYPES:
1051 p = offset + sizeof *ni;
1052 tf = proto_tree_add_text(tree, tvb,
1053 offset + sizeof(*ni), -1,
1054 "Supported type bitmap%s",
1055 (flags & 0x0001) ? ", compressed" : "");
1056 field_tree = proto_item_add_subtree(tf,
1057 ett_nodeinfo_nodebitmap);
1059 while (tvb_bytes_exist(tvb, p, sizeof(guint32))) { /* XXXX Check what? */
1060 if ((flags & 0x0001) == 0) {
1061 l = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1062 l /= sizeof(guint32);
1065 l = tvb_get_ntohs(tvb, p);
1066 i = tvb_get_ntohs(tvb, p + sizeof(guint16)); /*skip*/
1068 if (n + l * 32 > (1 << 16))
1070 if (n + (l + i) * 32 > (1 << 16))
1072 if ((flags & 0x0001) == 0) {
1073 proto_tree_add_text(field_tree, tvb, p,
1074 l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
1075 bitrange(tvb, p, l, n));
1078 proto_tree_add_text(field_tree, tvb, p,
1079 4 + l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
1080 bitrange(tvb, p + 4, l, n));
1083 n += l * 32 + i * 32;
1085 off = tvb_length_remaining(tvb, offset);
1087 case NI_QTYPE_DNSNAME:
1088 proto_tree_add_text(tree, tvb, offset + sizeof(*ni),
1089 sizeof(gint32), "TTL: %d", (gint32)tvb_get_ntohl(tvb, offset + sizeof *ni));
1090 tf = proto_tree_add_text(tree, tvb,
1091 offset + sizeof(*ni) + sizeof(guint32), -1,
1093 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
1094 j = offset + sizeof (*ni) + sizeof(guint32);
1095 while (j < tvb_reported_length(tvb)) {
1096 l = get_dns_name(tvb, j,
1097 offset + sizeof (*ni) + sizeof(guint32),
1099 if (tvb_bytes_exist(tvb, j + l, 1) &&
1100 tvb_get_guint8(tvb, j + l) == 0) {
1102 proto_tree_add_text(field_tree, tvb, j, l,
1103 "DNS label: %s (truncated)", dname);
1105 proto_tree_add_text(field_tree, tvb, j, l,
1106 "DNS label: %s", dname);
1110 off = tvb_length_remaining(tvb, offset);
1112 case NI_QTYPE_NODEADDR:
1113 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1114 n /= sizeof(gint32) + sizeof(struct e_in6_addr);
1115 tf = proto_tree_add_text(tree, tvb,
1116 offset + sizeof(*ni), -1, "IPv6 node addresses");
1117 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node6);
1118 p = offset + sizeof (*ni);
1119 for (i = 0; i < n; i++) {
1120 struct e_in6_addr e_in6_addr;
1122 ttl = (gint32)tvb_get_ntohl(tvb, p);
1123 tvb_get_ipv6(tvb, p + sizeof ttl, &e_in6_addr);
1124 proto_tree_add_text(field_tree, tvb,
1125 p, sizeof(struct e_in6_addr) + sizeof(gint32),
1126 "%s (TTL %d)", ip6_to_str(&e_in6_addr), ttl);
1127 p += sizeof(struct e_in6_addr) + sizeof(gint32);
1129 off = tvb_length_remaining(tvb, offset);
1131 case NI_QTYPE_IPV4ADDR:
1132 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1133 n /= sizeof(gint32) + sizeof(guint32);
1134 tf = proto_tree_add_text(tree, tvb,
1135 offset + sizeof(*ni), -1, "IPv4 node addresses");
1136 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node4);
1137 p = offset + sizeof *ni;
1138 for (i = 0; i < n; i++) {
1139 ipaddr = tvb_get_ipv4(tvb, sizeof(gint32) + p);
1140 proto_tree_add_text(field_tree, tvb,
1141 p, sizeof(guint32), "%s (TTL %d)",
1142 ip_to_str((guint8 *)&ipaddr), tvb_get_ntohl(tvb, p));
1143 p += sizeof(gint32) + sizeof(guint32);
1145 off = tvb_length_remaining(tvb, offset);
1151 /* the rest of data */
1152 call_dissector(data_handle,tvb_new_subset(tvb, offset + off, -1, -1), pinfo, tree);
1156 dissect_rrenum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1158 proto_tree *field_tree, *opt_tree;
1160 struct icmp6_router_renum icmp6_router_renum, *rr;
1161 struct rr_pco_match rr_pco_match, *match;
1162 struct rr_pco_use rr_pco_use, *use;
1167 rr = &icmp6_router_renum;
1168 tvb_memcpy(tvb, (guint8 *)rr, offset, sizeof *rr);
1169 proto_tree_add_text(tree, tvb,
1170 offset + offsetof(struct icmp6_router_renum, rr_seqnum), 4,
1171 "Sequence number: 0x%08x", pntohl(&rr->rr_seqnum));
1172 proto_tree_add_text(tree, tvb,
1173 offset + offsetof(struct icmp6_router_renum, rr_segnum), 1,
1174 "Segment number: 0x%02x", rr->rr_segnum);
1176 flagoff = offset + offsetof(struct icmp6_router_renum, rr_flags);
1177 flags = tvb_get_guint8(tvb, flagoff);
1178 tf = proto_tree_add_text(tree, tvb, flagoff, 1,
1179 "Flags: 0x%02x", flags);
1180 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1181 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1182 decode_boolean_bitfield(flags, 0x80, 8,
1183 "Test command", "Not test command"));
1184 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1185 decode_boolean_bitfield(flags, 0x40, 8,
1186 "Result requested", "Result not requested"));
1187 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1188 decode_boolean_bitfield(flags, 0x20, 8,
1189 "All interfaces", "Not all interfaces"));
1190 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1191 decode_boolean_bitfield(flags, 0x10, 8,
1192 "Site specific", "Not site specific"));
1193 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1194 decode_boolean_bitfield(flags, 0x08, 8,
1195 "Processed previously", "Complete result"));
1197 proto_tree_add_text(tree, tvb,
1198 offset + offsetof(struct icmp6_router_renum, rr_maxdelay), 2,
1199 "Max delay: 0x%04x", pntohs(&rr->rr_maxdelay));
1200 call_dissector(data_handle,tvb_new_subset(tvb, offset + sizeof(*rr), -1, -1), pinfo, tree); /*XXX*/
1202 if (rr->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
1203 off = offset + sizeof(*rr);
1204 match = &rr_pco_match;
1205 tvb_memcpy(tvb, (guint8 *)match, off, sizeof *match);
1206 tf = proto_tree_add_text(tree, tvb, off, sizeof(*match),
1207 "Match-Prefix: %s/%u (%u-%u)", ip6_to_str(&match->rpm_prefix),
1208 match->rpm_matchlen, match->rpm_minlen, match->rpm_maxlen);
1209 opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
1210 proto_tree_add_text(opt_tree, tvb,
1211 off + offsetof(struct rr_pco_match, rpm_code),
1212 sizeof(match->rpm_code), "OpCode: %s (%u)",
1213 val_to_str(match->rpm_code, names_rrenum_matchcode, "Unknown"),
1215 proto_tree_add_text(opt_tree, tvb,
1216 off + offsetof(struct rr_pco_match, rpm_len),
1217 sizeof(match->rpm_len), "OpLength: %u (%u octets)",
1218 match->rpm_len, match->rpm_len * 8);
1219 proto_tree_add_text(opt_tree, tvb,
1220 off + offsetof(struct rr_pco_match, rpm_ordinal),
1221 sizeof(match->rpm_ordinal), "Ordinal: %u", match->rpm_ordinal);
1222 proto_tree_add_text(opt_tree, tvb,
1223 off + offsetof(struct rr_pco_match, rpm_matchlen),
1224 sizeof(match->rpm_matchlen), "MatchLen: %u", match->rpm_matchlen);
1225 proto_tree_add_text(opt_tree, tvb,
1226 off + offsetof(struct rr_pco_match, rpm_minlen),
1227 sizeof(match->rpm_minlen), "MinLen: %u", match->rpm_minlen);
1228 proto_tree_add_text(opt_tree, tvb,
1229 off + offsetof(struct rr_pco_match, rpm_maxlen),
1230 sizeof(match->rpm_maxlen), "MaxLen: %u", match->rpm_maxlen);
1231 proto_tree_add_text(opt_tree, tvb,
1232 off + offsetof(struct rr_pco_match, rpm_prefix),
1233 sizeof(match->rpm_prefix), "MatchPrefix: %s",
1234 ip6_to_str(&match->rpm_prefix));
1236 off += sizeof(*match);
1238 for (l = match->rpm_len * 8 - sizeof(*match);
1239 l >= sizeof(*use); l -= sizeof(*use), off += sizeof(*use)) {
1240 tvb_memcpy(tvb, (guint8 *)use, off, sizeof *use);
1241 tf = proto_tree_add_text(tree, tvb, off, sizeof(*use),
1242 "Use-Prefix: %s/%u (keep %u)", ip6_to_str(&use->rpu_prefix),
1243 use->rpu_uselen, use->rpu_keeplen);
1244 opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
1245 proto_tree_add_text(opt_tree, tvb,
1246 off + offsetof(struct rr_pco_use, rpu_uselen),
1247 sizeof(use->rpu_uselen), "UseLen: %u", use->rpu_uselen);
1248 proto_tree_add_text(opt_tree, tvb,
1249 off + offsetof(struct rr_pco_use, rpu_keeplen),
1250 sizeof(use->rpu_keeplen), "KeepLen: %u", use->rpu_keeplen);
1251 tf = proto_tree_add_text(opt_tree, tvb,
1252 flagoff = off + offsetof(struct rr_pco_use, rpu_ramask),
1253 sizeof(use->rpu_ramask), "FlagMask: 0x%x", use->rpu_ramask);
1254 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1255 flags = tvb_get_guint8(tvb, flagoff);
1256 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1257 decode_boolean_bitfield(flags,
1258 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
1259 "Onlink", "Not onlink"));
1260 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1261 decode_boolean_bitfield(flags,
1262 ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8,
1263 "Auto", "Not auto"));
1264 tf = proto_tree_add_text(opt_tree, tvb,
1265 flagoff = off + offsetof(struct rr_pco_use, rpu_raflags),
1266 sizeof(use->rpu_raflags), "RAFlags: 0x%x", use->rpu_raflags);
1267 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1268 flags = tvb_get_guint8(tvb, flagoff);
1269 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1270 decode_boolean_bitfield(flags,
1271 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
1272 "Onlink", "Not onlink"));
1273 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1274 decode_boolean_bitfield(flags,
1275 ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8, "Auto", "Not auto"));
1276 if (pntohl(&use->rpu_vltime) == 0xffffffff)
1277 proto_tree_add_text(opt_tree, tvb,
1278 off + offsetof(struct rr_pco_use, rpu_vltime),
1279 sizeof(use->rpu_vltime), "Valid Lifetime: infinity");
1281 proto_tree_add_text(opt_tree, tvb,
1282 off + offsetof(struct rr_pco_use, rpu_vltime),
1283 sizeof(use->rpu_vltime), "Valid Lifetime: %u",
1284 pntohl(&use->rpu_vltime));
1285 if (pntohl(&use->rpu_pltime) == 0xffffffff)
1286 proto_tree_add_text(opt_tree, tvb,
1287 off + offsetof(struct rr_pco_use, rpu_pltime),
1288 sizeof(use->rpu_pltime), "Preferred Lifetime: infinity");
1290 proto_tree_add_text(opt_tree, tvb,
1291 off + offsetof(struct rr_pco_use, rpu_pltime),
1292 sizeof(use->rpu_pltime), "Preferred Lifetime: %u",
1293 pntohl(&use->rpu_pltime));
1294 tf = proto_tree_add_text(opt_tree, tvb,
1295 flagoff = off + offsetof(struct rr_pco_use, rpu_flags),
1296 sizeof(use->rpu_flags), "Flags: 0x%08x",
1297 pntohl(&use->rpu_flags));
1298 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1299 flags = tvb_get_guint8(tvb, flagoff);
1300 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1301 decode_boolean_bitfield(flags,
1302 ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, 32,
1303 "Decrement valid lifetime", "No decrement valid lifetime"));
1304 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1305 decode_boolean_bitfield(flags,
1306 ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, 32,
1307 "Decrement preferred lifetime",
1308 "No decrement preferred lifetime"));
1309 proto_tree_add_text(opt_tree, tvb,
1310 off + offsetof(struct rr_pco_use, rpu_prefix),
1311 sizeof(use->rpu_prefix), "UsePrefix: %s",
1312 ip6_to_str(&use->rpu_prefix));
1319 * See I-D draft-vida-mld-v2-08
1321 static const value_string mldrv2ModesNames[] = {
1324 { 3, "Changed to include" },
1325 { 4, "Changed to exclude" },
1326 { 5, "Allow new sources" },
1327 { 6, "Block old sources" },
1332 dissect_mldrv2( tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree )
1334 proto_tree *sub_tree;
1337 guint8 recordType, auxDataLen;
1338 guint32 sourceNb, recordSize, localOffset;
1339 struct e_in6_addr addr;
1341 for( ; count; count--, offset += recordSize ) {
1342 localOffset = offset;
1343 recordType = tvb_get_guint8( tvb, localOffset );
1345 auxDataLen = tvb_get_guint8( tvb, localOffset );
1347 sourceNb = tvb_get_ntohs( tvb, localOffset );
1349 recordSize = 4 + 16 + (16 * sourceNb) + (auxDataLen * 4);
1351 tvb_get_ipv6(tvb, localOffset, &addr);
1352 tf = proto_tree_add_text( tree, tvb, offset, recordSize,
1354 "%s: %s (%s)", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
1355 get_hostname6(&addr), ip6_to_str(&addr)
1357 "%s: %s", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
1361 sub_tree = proto_item_add_subtree(tf, ett_multicastRR);
1363 proto_tree_add_text( sub_tree, tvb, offset, 1, "Mode: %s",
1364 val_to_str(recordType, mldrv2ModesNames,"Unknown mode") );
1365 proto_tree_add_text( sub_tree, tvb, offset+1, 1, "Aux data len: %u", auxDataLen * 4);
1366 proto_tree_add_text( sub_tree, tvb, localOffset, 16, "Multicast Address: %s", ip6_to_str(&addr) );
1369 for( ; sourceNb; sourceNb--, localOffset += 16 ) {
1370 tvb_get_ipv6(tvb, localOffset, &addr);
1371 proto_tree_add_text( sub_tree, tvb, localOffset, 16,
1373 "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr) );
1375 "Source Address: %s", ip6_to_str(&addr) );
1382 dissect_mldqv2(tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree)
1384 struct e_in6_addr addr;
1386 for ( ; count; count--, offset += 16) {
1387 tvb_get_ipv6(tvb, offset, &addr);
1388 proto_tree_add_text(tree, tvb, offset, 16,
1389 "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr));
1394 dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1396 proto_tree *icmp6_tree, *field_tree;
1397 proto_item *ti, *tf = NULL;
1398 struct icmp6_hdr icmp6_hdr, *dp;
1399 struct icmp6_nodeinfo *ni = NULL;
1400 const char *codename, *typename;
1401 const char *colcodename, *coltypename;
1403 guint length, reported_length;
1406 guint16 cksum, computed_cksum;
1410 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1411 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMPv6");
1412 if (check_col(pinfo->cinfo, COL_INFO))
1413 col_clear(pinfo->cinfo, COL_INFO);
1416 tvb_memcpy(tvb, (guint8 *)&icmp6_hdr, offset, sizeof icmp6_hdr);
1418 codename = typename = colcodename = coltypename = "Unknown";
1420 switch (dp->icmp6_type) {
1421 case ICMP6_DST_UNREACH:
1422 typename = coltypename = "Unreachable";
1423 switch (dp->icmp6_code) {
1424 case ICMP6_DST_UNREACH_NOROUTE:
1425 codename = colcodename = "Route unreachable";
1427 case ICMP6_DST_UNREACH_ADMIN:
1428 codename = colcodename = "Administratively prohibited";
1430 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
1431 codename = colcodename = "Not a neighbor";
1433 case ICMP6_DST_UNREACH_ADDR:
1434 codename = colcodename = "Address unreachable";
1436 case ICMP6_DST_UNREACH_NOPORT:
1437 codename = colcodename = "Port unreachable";
1441 case ICMP6_PACKET_TOO_BIG:
1442 typename = coltypename = "Too big";
1443 codename = colcodename = NULL;
1445 case ICMP6_TIME_EXCEEDED:
1446 typename = coltypename = "Time exceeded";
1447 switch (dp->icmp6_code) {
1448 case ICMP6_TIME_EXCEED_TRANSIT:
1449 codename = colcodename = "In-transit";
1451 case ICMP6_TIME_EXCEED_REASSEMBLY:
1452 codename = colcodename = "Reassembly";
1456 case ICMP6_PARAM_PROB:
1457 typename = coltypename = "Parameter problem";
1458 switch (dp->icmp6_code) {
1459 case ICMP6_PARAMPROB_HEADER:
1460 codename = colcodename = "Header";
1462 case ICMP6_PARAMPROB_NEXTHEADER:
1463 codename = colcodename = "Next header";
1465 case ICMP6_PARAMPROB_OPTION:
1466 codename = colcodename = "Option";
1470 case ICMP6_ECHO_REQUEST:
1471 typename = coltypename = "Echo request";
1472 codename = colcodename = NULL;
1474 case ICMP6_ECHO_REPLY:
1475 typename = coltypename = "Echo reply";
1476 codename = colcodename = NULL;
1478 case ICMP6_MEMBERSHIP_QUERY:
1479 typename = coltypename = "Multicast listener query";
1480 codename = colcodename = NULL;
1482 case ICMP6_MEMBERSHIP_REPORT:
1483 typename = coltypename = "Multicast listener report";
1484 codename = colcodename = NULL;
1486 case ICMP6_MEMBERSHIP_REDUCTION:
1487 typename = coltypename = "Multicast listener done";
1488 codename = colcodename = NULL;
1490 case ND_ROUTER_SOLICIT:
1491 typename = coltypename = "Router solicitation";
1492 codename = colcodename = NULL;
1493 len = sizeof(struct nd_router_solicit);
1495 case ND_ROUTER_ADVERT:
1496 typename = coltypename = "Router advertisement";
1497 codename = colcodename = NULL;
1498 len = sizeof(struct nd_router_advert);
1500 case ND_NEIGHBOR_SOLICIT:
1501 typename = coltypename = "Neighbor solicitation";
1502 codename = colcodename = NULL;
1503 len = sizeof(struct nd_neighbor_solicit);
1505 case ND_NEIGHBOR_ADVERT:
1506 typename = coltypename = "Neighbor advertisement";
1507 codename = colcodename = NULL;
1508 len = sizeof(struct nd_neighbor_advert);
1511 typename = coltypename = "Redirect";
1512 codename = colcodename = NULL;
1513 len = sizeof(struct nd_redirect);
1515 case ICMP6_ROUTER_RENUMBERING:
1516 typename = coltypename = "Router renumbering";
1517 switch (dp->icmp6_code) {
1518 case ICMP6_ROUTER_RENUMBERING_COMMAND:
1519 codename = colcodename = "Command";
1521 case ICMP6_ROUTER_RENUMBERING_RESULT:
1522 codename = colcodename = "Result";
1524 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
1525 codename = colcodename = "Sequence number reset";
1528 len = sizeof(struct icmp6_router_renum);
1530 case ICMP6_NI_QUERY:
1531 case ICMP6_NI_REPLY:
1532 ni = (struct icmp6_nodeinfo *)dp;
1533 if (ni->ni_type == ICMP6_NI_QUERY) {
1534 typename = coltypename = "Node information query";
1535 switch (ni->ni_code) {
1536 case ICMP6_NI_SUBJ_IPV6:
1537 codename = "Query subject = IPv6 addresses";
1539 case ICMP6_NI_SUBJ_FQDN:
1540 if (tvb_bytes_exist(tvb, offset, sizeof(*ni)))
1541 codename = "Query subject = DNS name";
1543 codename = "Query subject = empty";
1545 case ICMP6_NI_SUBJ_IPV4:
1546 codename = "Query subject = IPv4 addresses";
1550 typename = coltypename = "Node information reply";
1551 switch (ni->ni_code) {
1552 case ICMP6_NI_SUCCESS:
1553 codename = "Successful";
1555 case ICMP6_NI_REFUSED:
1556 codename = "Refused";
1558 case ICMP6_NI_UNKNOWN:
1559 codename = "Unknown query type";
1563 colcodename = val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
1565 len = sizeof(struct icmp6_nodeinfo);
1567 case ICMP6_MIP6_DHAAD_REQUEST:
1568 typename = coltypename = "Dynamic Home Agent Address Discovery Request";
1569 codename = "Should always be zero";
1572 case ICMP6_MIP6_DHAAD_REPLY:
1573 typename = coltypename = "Dynamic Home Agent Address Discovery Reply";
1574 codename = "Should always be zero";
1577 case ICMP6_MIP6_MPS:
1578 typename = coltypename = "Mobile Prefix Solicitation";
1579 codename = "Should always be zero";
1582 case ICMP6_MIP6_MPA:
1583 typename = coltypename = "Mobile Prefix Advertisement";
1584 codename = "Should always be zero";
1587 case ICMP6_CERT_PATH_SOL:
1588 typename = coltypename = "Certification Path Solicitation";
1589 codename = "Should always be zero";
1592 case ICMP6_CERT_PATH_AD:
1593 typename = coltypename = "Certification Path Advertisement";
1594 codename = "Should always be zero";
1597 case ICMP6_MLDV2_REPORT:
1598 typename = coltypename = "Multicast Listener Report Message v2";
1599 codename = "Should always be zero";
1602 case ICMP6_EXPERIMENTAL_MOBILITY:
1603 typename = coltypename ="Experimental Mobility";
1604 switch (dp->icmp6_data8[0]) {
1605 case FMIP6_SUBTYPE_RTSOLPR:
1606 typename = coltypename ="RtSolPr (ICMPv6 Experimental Mobility)";
1607 codename = "Should always be zero";
1610 case FMIP6_SUBTYPE_PRRTADV:
1611 typename = coltypename ="PrRtAdv (ICMPv6 Experimental Mobility)";
1612 codename = val_to_str(dp->icmp6_code, names_fmip6_prrtadv_code, "Unknown");
1615 case FMIP6_SUBTYPE_HI:
1616 typename = coltypename ="HI (ICMPv6 Experimental Mobility)";
1617 codename = val_to_str(dp->icmp6_code, names_fmip6_hi_code, "Unknown");
1620 case FMIP6_SUBTYPE_HACK:
1621 typename = coltypename ="HAck (ICMPv6 Experimental Mobility)";
1622 codename = val_to_str(dp->icmp6_code, names_fmip6_hack_code, "Unknown");
1629 if (check_col(pinfo->cinfo, COL_INFO)) {
1630 char typebuf[256], codebuf[256];
1632 if (coltypename && strcmp(coltypename, "Unknown") == 0) {
1633 g_snprintf(typebuf, sizeof(typebuf), "Unknown (0x%02x)",
1635 coltypename = typebuf;
1637 if (colcodename && strcmp(colcodename, "Unknown") == 0) {
1638 g_snprintf(codebuf, sizeof(codebuf), "Unknown (0x%02x)",
1640 colcodename = codebuf;
1643 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", coltypename, colcodename);
1645 col_add_str(pinfo->cinfo, COL_INFO, coltypename);
1650 /* !!! specify length */
1651 ti = proto_tree_add_item(tree, proto_icmpv6, tvb, offset, -1, FALSE);
1652 icmp6_tree = proto_item_add_subtree(ti, ett_icmpv6);
1654 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_type, tvb,
1655 offset + offsetof(struct icmp6_hdr, icmp6_type), 1,
1657 "Type: %u (%s)", dp->icmp6_type, typename);
1659 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
1660 offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
1662 "Code: %u (%s)", dp->icmp6_code, codename);
1664 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
1665 offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
1667 "Code: %u", dp->icmp6_code);
1669 cksum = (guint16)g_htons(dp->icmp6_cksum);
1670 length = tvb_length(tvb);
1671 reported_length = tvb_reported_length(tvb);
1672 if (!pinfo->fragmented && length >= reported_length) {
1673 /* The packet isn't part of a fragmented datagram and isn't
1674 truncated, so we can checksum it. */
1676 /* Set up the fields of the pseudo-header. */
1677 cksum_vec[0].ptr = pinfo->src.data;
1678 cksum_vec[0].len = pinfo->src.len;
1679 cksum_vec[1].ptr = pinfo->dst.data;
1680 cksum_vec[1].len = pinfo->dst.len;
1681 cksum_vec[2].ptr = (const guint8 *)&phdr;
1682 phdr[0] = g_htonl(tvb_reported_length(tvb));
1683 phdr[1] = g_htonl(IP_PROTO_ICMPV6);
1684 cksum_vec[2].len = 8;
1685 cksum_vec[3].len = tvb_reported_length(tvb);
1686 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, cksum_vec[3].len);
1687 computed_cksum = in_cksum(cksum_vec, 4);
1688 if (computed_cksum == 0) {
1689 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
1691 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1693 "Checksum: 0x%04x [correct]", cksum);
1695 proto_tree_add_boolean_hidden(icmp6_tree, hf_icmpv6_checksum_bad,
1697 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1699 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
1701 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1703 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1704 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1707 proto_tree_add_uint(icmp6_tree, hf_icmpv6_checksum, tvb,
1708 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1713 switch (dp->icmp6_type) {
1714 case ICMP6_DST_UNREACH:
1715 case ICMP6_TIME_EXCEEDED:
1716 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1719 case ICMP6_PACKET_TOO_BIG:
1720 proto_tree_add_text(icmp6_tree, tvb,
1721 offset + offsetof(struct icmp6_hdr, icmp6_mtu), 4,
1722 "MTU: %u", pntohl(&dp->icmp6_mtu));
1723 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1726 case ICMP6_PARAM_PROB:
1727 proto_tree_add_text(icmp6_tree, tvb,
1728 offset + offsetof(struct icmp6_hdr, icmp6_pptr), 4,
1729 "Problem pointer: 0x%04x", pntohl(&dp->icmp6_pptr));
1730 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1733 case ICMP6_ECHO_REQUEST:
1734 case ICMP6_ECHO_REPLY:
1735 proto_tree_add_text(icmp6_tree, tvb,
1736 offset + offsetof(struct icmp6_hdr, icmp6_id), 2,
1737 "ID: 0x%04x", (guint16)g_ntohs(dp->icmp6_id));
1738 proto_tree_add_text(icmp6_tree, tvb,
1739 offset + offsetof(struct icmp6_hdr, icmp6_seq), 2,
1740 "Sequence: 0x%04x", (guint16)g_ntohs(dp->icmp6_seq));
1741 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
1742 call_dissector(data_handle,next_tvb, pinfo, icmp6_tree);
1744 case ICMP6_MEMBERSHIP_QUERY:
1745 case ICMP6_MEMBERSHIP_REPORT:
1746 case ICMP6_MEMBERSHIP_REDUCTION:
1747 #define MLDV2_MINLEN 28
1748 #define MLDV1_MINLEN 24
1749 if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) {
1750 if (length >= MLDV2_MINLEN) {
1756 mrc = g_ntohs(dp->icmp6_maxdelay);
1757 flag = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16);
1758 qqi = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16 + 1);
1759 nsrcs = tvb_get_ntohs(tvb, offset + sizeof(*dp) + 16 + 2);
1762 mrc = ((mrc & 0x0fff) | 0x1000) <<
1763 (((mrc & 0x7000) >> 12) + 3);
1764 proto_tree_add_text(icmp6_tree, tvb,
1765 offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
1766 "Maximum response delay[ms]: %u", mrc);
1768 proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp),
1769 16, "Multicast Address: %s",
1770 ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb,
1771 offset + sizeof *dp, sizeof (struct e_in6_addr)))));
1773 proto_tree_add_text(icmp6_tree, tvb,
1774 offset + sizeof(*dp) + 16, 1, "S Flag: %s",
1775 flag & 0x08 ? "ON" : "OFF");
1776 proto_tree_add_text(icmp6_tree, tvb,
1777 offset + sizeof(*dp) + 16, 1, "Robustness: %d",
1780 qqi = ((qqi & 0x0f) | 0x10) << (((qqi & 0x70) >> 4) + 3);
1781 proto_tree_add_text(icmp6_tree, tvb,
1782 offset + sizeof(*dp) + 17, 1, "QQI: %d", qqi);
1784 dissect_mldqv2(tvb, offset + sizeof(*dp) + 20, nsrcs,
1787 } else if (length > MLDV1_MINLEN) {
1788 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
1789 call_dissector(data_handle,next_tvb, pinfo, tree);
1792 /* MLDv1 Query -> FALLTHOUGH */
1796 proto_tree_add_text(icmp6_tree, tvb,
1797 offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
1798 "Maximum response delay: %u",
1799 (guint16)g_ntohs(dp->icmp6_maxdelay));
1800 proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp), 16,
1801 "Multicast Address: %s",
1802 ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb, offset + sizeof *dp, sizeof (struct e_in6_addr)))));
1804 case ND_ROUTER_SOLICIT:
1805 dissect_icmpv6ndopt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
1807 case ICMP6_MLDV2_REPORT: {
1810 nbRecords = tvb_get_ntohs( tvb, offset+4+2 );
1811 dissect_mldrv2( tvb, offset+4+2+2, nbRecords, icmp6_tree );
1814 case ND_ROUTER_ADVERT:
1816 struct nd_router_advert nd_router_advert, *ra;
1820 ra = &nd_router_advert;
1821 tvb_memcpy(tvb, (guint8 *)ra, offset, sizeof *ra);
1823 /* Current hop limit */
1824 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_cur_hop_limit, tvb,
1825 offset + offsetof(struct nd_router_advert, nd_ra_curhoplimit),
1826 1, ra->nd_ra_curhoplimit);
1829 flagoff = offset + offsetof(struct nd_router_advert, nd_ra_flags_reserved);
1830 ra_flags = tvb_get_guint8(tvb, flagoff);
1831 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", ra_flags);
1832 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1834 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1835 decode_boolean_bitfield(ra_flags,
1836 ND_RA_FLAG_MANAGED, 8, "Managed", "Not managed"));
1837 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1838 decode_boolean_bitfield(ra_flags,
1839 ND_RA_FLAG_OTHER, 8, "Other", "Not other"));
1840 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1841 decode_boolean_bitfield(ra_flags,
1842 ND_RA_FLAG_HOME_AGENT, 8,
1843 "Home Agent", "Not Home Agent"));
1844 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1845 decode_enumerated_bitfield(ra_flags, ND_RA_FLAG_RTPREF_MASK, 8,
1846 names_router_pref, "Router preference: %s"));
1848 /* Router lifetime */
1849 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_router_lifetime, tvb,
1850 offset + offsetof(struct nd_router_advert, nd_ra_router_lifetime),
1851 2, (guint16)g_ntohs(ra->nd_ra_router_lifetime));
1853 /* Reachable time */
1854 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_reachable_time, tvb,
1855 offset + offsetof(struct nd_router_advert, nd_ra_reachable), 4,
1856 pntohl(&ra->nd_ra_reachable));
1859 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_retrans_timer, tvb,
1860 offset + offsetof(struct nd_router_advert, nd_ra_retransmit), 4,
1861 pntohl(&ra->nd_ra_retransmit));
1863 dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
1866 case ND_NEIGHBOR_SOLICIT:
1868 struct nd_neighbor_solicit nd_neighbor_solicit, *ns;
1870 ns = &nd_neighbor_solicit;
1871 tvb_memcpy(tvb, (guint8 *)ns, offset, sizeof *ns);
1872 proto_tree_add_text(icmp6_tree, tvb,
1873 offset + offsetof(struct nd_neighbor_solicit, nd_ns_target), 16,
1876 get_hostname6(&ns->nd_ns_target),
1880 ip6_to_str(&ns->nd_ns_target));
1882 dissect_icmpv6ndopt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
1885 case ND_NEIGHBOR_ADVERT:
1887 int flagoff, targetoff;
1889 struct e_in6_addr na_target;
1891 flagoff = offset + offsetof(struct nd_neighbor_advert, nd_na_flags_reserved);
1892 na_flags = tvb_get_ntohl(tvb, flagoff);
1894 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 4, "Flags: 0x%08x", na_flags);
1895 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1896 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1897 decode_boolean_bitfield(na_flags,
1898 ND_NA_FLAG_ROUTER, 32, "Router", "Not router"));
1899 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1900 decode_boolean_bitfield(na_flags,
1901 ND_NA_FLAG_SOLICITED, 32, "Solicited", "Not adverted"));
1902 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1903 decode_boolean_bitfield(na_flags,
1904 ND_NA_FLAG_OVERRIDE, 32, "Override", "Not override"));
1906 targetoff = offset + offsetof(struct nd_neighbor_advert, nd_na_target);
1907 tvb_memcpy(tvb, (guint8 *)&na_target, targetoff, sizeof na_target);
1908 proto_tree_add_text(icmp6_tree, tvb, targetoff, 16,
1911 get_hostname6(&na_target),
1915 ip6_to_str(&na_target));
1917 dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
1922 struct nd_redirect nd_redirect, *rd;
1925 tvb_memcpy(tvb, (guint8 *)rd, offset, sizeof *rd);
1926 proto_tree_add_text(icmp6_tree, tvb,
1927 offset + offsetof(struct nd_redirect, nd_rd_target), 16,
1930 get_hostname6(&rd->nd_rd_target),
1934 ip6_to_str(&rd->nd_rd_target));
1936 proto_tree_add_text(icmp6_tree, tvb,
1937 offset + offsetof(struct nd_redirect, nd_rd_dst), 16,
1939 "Destination: %s (%s)",
1940 get_hostname6(&rd->nd_rd_dst),
1944 ip6_to_str(&rd->nd_rd_dst));
1946 dissect_icmpv6ndopt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
1949 case ICMP6_ROUTER_RENUMBERING:
1950 dissect_rrenum(tvb, offset, pinfo, icmp6_tree);
1952 case ICMP6_NI_QUERY:
1953 case ICMP6_NI_REPLY:
1954 ni = (struct icmp6_nodeinfo *)dp;
1955 proto_tree_add_text(icmp6_tree, tvb,
1956 offset + offsetof(struct icmp6_nodeinfo, ni_qtype),
1957 sizeof(ni->ni_qtype),
1958 "Query type: 0x%04x (%s)", pntohs(&ni->ni_qtype),
1959 val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
1961 dissect_nodeinfo(tvb, offset, pinfo, icmp6_tree);
1963 case ICMP6_MIP6_DHAAD_REQUEST:
1964 proto_tree_add_text(icmp6_tree, tvb,
1965 offset + 4, 2, "Identifier: %d (0x%02x)",
1966 tvb_get_ntohs(tvb, offset + 4),
1967 tvb_get_ntohs(tvb, offset + 4));
1968 proto_tree_add_text(icmp6_tree, tvb,
1969 offset + 6, 2, "Reserved: %d",
1970 tvb_get_ntohs(tvb, offset + 6));
1972 case ICMP6_MIP6_DHAAD_REPLY:
1973 proto_tree_add_text(icmp6_tree, tvb,
1974 offset + 4, 2, "Identifier: %d (0x%02x)",
1975 tvb_get_ntohs(tvb, offset + 4),
1976 tvb_get_ntohs(tvb, offset + 4));
1977 proto_tree_add_text(icmp6_tree, tvb,
1978 offset + 6, 2, "Reserved: %d",
1979 tvb_get_ntohs(tvb, offset + 6));
1980 /* Show all Home Agent Addresses */
1983 int ha_num = (length - 8)/16;
1985 for (i = 0; i < ha_num; i++) {
1987 proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_haad_ha_addrs,
1988 tvb, offset + 8 + suboffset, 16,
1989 tvb_get_ptr(tvb, offset + 8 + suboffset, 16));
1993 case ICMP6_MIP6_MPS:
1994 proto_tree_add_text(icmp6_tree, tvb,
1995 offset + 4, 2, "Identifier: %d (0x%02x)",
1996 tvb_get_ntohs(tvb, offset + 4),
1997 tvb_get_ntohs(tvb, offset + 4));
1998 proto_tree_add_text(icmp6_tree, tvb,
1999 offset + 6, 2, "Reserved: %d",
2000 tvb_get_ntohs(tvb, offset + 6));
2002 case ICMP6_MIP6_MPA:
2003 proto_tree_add_text(icmp6_tree, tvb,
2004 offset + 4, 2, "Identifier: %d (0x%02x)",
2005 tvb_get_ntohs(tvb, offset + 4),
2006 tvb_get_ntohs(tvb, offset + 4));
2007 proto_tree_add_text(icmp6_tree, tvb,
2009 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
2011 "Managed Address Configuration",
2012 "No Managed Address Configuration"));
2013 proto_tree_add_text(icmp6_tree, tvb,
2015 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
2017 "Other Stateful Configuration",
2018 "No Other Stateful Configuration"));
2019 proto_tree_add_text(icmp6_tree, tvb,
2020 offset + 7, 1, "Reserved: %d",
2021 tvb_get_guint8(tvb, offset + 7));
2022 /* Show all options */
2023 dissect_icmpv6ndopt(tvb, offset + 8, pinfo, icmp6_tree);
2025 case ICMP6_EXPERIMENTAL_MOBILITY:
2026 switch (dp->icmp6_data8[0]) {
2027 case FMIP6_SUBTYPE_RTSOLPR:
2029 struct fmip6_rtsolpr *rtsolpr;
2030 rtsolpr = (struct fmip6_rtsolpr*) dp;
2031 proto_tree_add_text(icmp6_tree, tvb,
2033 "Subtype: Router Solicitation for Proxy Advertisement");
2034 proto_tree_add_text(icmp6_tree, tvb,
2036 "Identifier: %d", pntohs(&rtsolpr->fmip6_rtsolpr_id));
2037 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2040 case FMIP6_SUBTYPE_PRRTADV:
2042 struct fmip6_prrtadv *prrtadv;
2043 prrtadv = (struct fmip6_prrtadv*) dp;
2044 proto_tree_add_text(icmp6_tree, tvb,
2046 "Subtype: Proxy Router Advertisement");
2047 proto_tree_add_text(icmp6_tree, tvb,
2049 "Identifier: %d", pntohs(&prrtadv->fmip6_prrtadv_id));
2050 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2053 case FMIP6_SUBTYPE_HI:
2055 struct fmip6_hi *hi;
2058 hi = (struct fmip6_hi*) dp;
2059 proto_tree_add_text(icmp6_tree, tvb,
2061 "Subtype: Handover Initiate");
2063 flagoff = offset + offsetof(struct fmip6_hi, fmip6_hi_flags_reserved);
2064 hi_flags = tvb_get_guint8(tvb, flagoff);
2065 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", hi_flags);
2066 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
2067 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
2068 decode_boolean_bitfield(hi_flags,
2069 FMIP_HI_FLAG_ASSIGNED, 8, "Assigned", "Not assigned"));
2070 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
2071 decode_boolean_bitfield(hi_flags,
2072 FMIP_HI_FLAG_BUFFER, 8, "Buffered", "Not buffered"));
2073 proto_tree_add_text(icmp6_tree, tvb,
2075 "Identifier: %d", pntohs(&hi->fmip6_hi_id));
2076 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2079 case FMIP6_SUBTYPE_HACK:
2081 struct fmip6_hack *hack;
2082 hack = (struct fmip6_hack*) dp;
2083 proto_tree_add_text(icmp6_tree, tvb,
2085 "Subtype: Handover Acknowledge");
2086 proto_tree_add_text(icmp6_tree, tvb,
2088 "Identifier: %d", pntohs(&hack->fmip6_hack_id));
2089 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2094 case ICMP6_CERT_PATH_AD:
2095 /*RFC 3971 6.4.2. Certification Path Advertisement Message Format */
2097 proto_tree_add_text(icmp6_tree, tvb, offset, -1,"Certification Path Advertisement Message");
2099 /* Identifier A 16-bit unsigned integer field */
2100 proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset, 2, FALSE);
2101 offset = offset + 2;
2102 /* All Components A 16-bit unsigned integer field*/
2103 proto_tree_add_item(icmp6_tree, hf_icmpv6_all_comp, tvb, offset, 2, FALSE);
2104 offset = offset + 2;
2106 /* Component A 16-bit unsigned integer field, used to inform the receiver
2107 * which certificate is being sent.
2109 proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2, FALSE);
2110 offset = offset + 2;
2113 proto_tree_add_text(icmp6_tree, tvb, offset, 2,"Reserved");
2114 offset = offset + 2;
2116 dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
2119 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
2120 call_dissector(data_handle,next_tvb, pinfo, tree);
2127 proto_register_icmpv6(void)
2129 static hf_register_info hf[] = {
2131 { "Type", "icmpv6.type", FT_UINT8, BASE_DEC, NULL, 0x0,
2134 { "Code", "icmpv6.code", FT_UINT8, BASE_DEC, NULL, 0x0,
2136 { &hf_icmpv6_checksum,
2137 { "Checksum", "icmpv6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2139 { &hf_icmpv6_checksum_bad,
2140 { "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2142 { &hf_icmpv6_haad_ha_addrs,
2143 { "Home Agent Addresses", "icmpv6.haad.ha_addrs",
2144 FT_IPv6, BASE_HEX, NULL, 0x0,
2146 { &hf_icmpv6_ra_cur_hop_limit,
2147 { "Cur hop limit", "icmpv6.ra.cur_hop_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
2148 "Current hop limit", HFILL }},
2149 { &hf_icmpv6_ra_router_lifetime,
2150 { "Router lifetime", "icmpv6.ra.router_lifetime", FT_UINT16, BASE_DEC, NULL, 0x0,
2151 "Router lifetime (s)", HFILL }},
2152 { &hf_icmpv6_ra_reachable_time,
2153 { "Reachable time", "icmpv6.ra.reachable_time", FT_UINT32, BASE_DEC, NULL, 0x0,
2154 "Reachable time (ms)", HFILL }},
2155 { &hf_icmpv6_ra_retrans_timer,
2156 { "Retrans timer", "icmpv6.ra.retrans_timer", FT_UINT32, BASE_DEC, NULL, 0x0,
2157 "Retrans timer (ms)", HFILL }},
2158 { &hf_icmpv6_option,
2159 { "ICMPv6 Option", "icmpv6.option", FT_NONE, BASE_NONE, NULL, 0x0,
2161 { &hf_icmpv6_option_type,
2162 { "Type", "icmpv6.option.type", FT_UINT8, BASE_DEC, VALS(option_vals), 0x0,
2163 "Options type", HFILL }},
2164 { &hf_icmpv6_option_length,
2165 { "Length", "icmpv6.option.length", FT_UINT8, BASE_DEC, NULL, 0x0,
2166 "Options length (in bytes)", HFILL }},
2167 { &hf_icmpv6_opt_cga_pad_len,
2168 { "Pad Length", "icmpv6.option.cga.pad_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2169 "Pad Length (in bytes)", HFILL }},
2170 { &hf_icmpv6_opt_cga,
2171 { "CGA", "icmpv6.option.cga", FT_BYTES, BASE_NONE, NULL, 0x0,
2173 { &hf_icmpv6_opt_rsa_key_hash,
2174 { "Key Hash", "icmpv6.option.rsa.key_hash", FT_BYTES, BASE_HEX, NULL, 0x0,
2175 "Key Hash", HFILL }},
2176 { &hf_icmpv6_opt_name_type,
2177 { "Name Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_name_type_vals), 0x0,
2178 "Name Type", HFILL }},
2179 { &hf_icmpv6_opt_name_x501,
2180 { "DER Encoded X.501 Name", "icmpv6.option.name_x501", FT_BYTES, BASE_HEX, NULL, 0x0,
2181 "DER Encoded X.501 Name", HFILL }},
2182 { &hf_icmpv6_opt_name_fqdn,
2183 { "FQDN", "icmpv6.option.name_type.fqdn", FT_STRING, BASE_NONE, NULL, 0x0,
2185 { &hf_icmpv6_opt_cert_type,
2186 { "Cert Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_cert_type_vals), 0x0,
2187 "Cert Type", HFILL }},
2188 { &hf_icmpv6_identifier,
2189 { "Identifier", "icmpv6.identifier", FT_UINT16, BASE_DEC, NULL, 0x0,
2190 "Identifier", HFILL }},
2191 { &hf_icmpv6_all_comp,
2192 { "All Components", "icmpv6.all_comp", FT_UINT16, BASE_DEC, NULL, 0x0,
2193 "All Components", HFILL }},
2195 { "Component", "icmpv6.comp", FT_UINT16, BASE_DEC, NULL, 0x0,
2196 "Component", HFILL }},
2197 { &hf_icmpv6_x509if_Name,
2198 { "Name", "icmpv6.x509_Name", FT_UINT32, BASE_DEC, VALS(x509if_Name_vals), 0,
2200 { &hf_icmpv6_x509af_Certificate,
2201 { "Certificate", "icmpv6_x509_Certificate", FT_NONE, BASE_NONE, NULL, 0,
2202 "Certificate", HFILL }},
2207 static gint *ett[] = {
2212 &ett_nodeinfo_subject4,
2213 &ett_nodeinfo_subject6,
2214 &ett_nodeinfo_node4,
2215 &ett_nodeinfo_node6,
2216 &ett_nodeinfo_nodebitmap,
2217 &ett_nodeinfo_nodedns,
2219 &ett_icmpv6opt_name,
2222 proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",
2223 "ICMPv6", "icmpv6");
2224 proto_register_field_array(proto_icmpv6, hf, array_length(hf));
2225 proto_register_subtree_array(ett, array_length(ett));
2227 register_dissector("icmpv6", dissect_icmpv6, proto_icmpv6);
2231 proto_reg_handoff_icmpv6(void)
2233 dissector_handle_t icmpv6_handle;
2235 icmpv6_handle = create_dissector_handle(dissect_icmpv6, proto_icmpv6);
2236 dissector_add("ip.proto", IP_PROTO_ICMPV6, icmpv6_handle);
2239 * Get a handle for the IPv6 dissector.
2241 ipv6_handle = find_dissector("ipv6");
2242 data_handle = find_dissector("data");