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/asn1.h>
52 #include <epan/strutil.h>
54 #include "packet-ber.h"
55 #include "packet-ipv6.h"
56 #include "packet-dns.h"
57 #include "packet-x509af.h"
58 #include "packet-x509if.h"
62 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
66 * See, under http://www.ietf.org/internet-drafts/
68 * draft-ietf-mobileip-ipv6-15.txt
72 * draft-ietf-ipngwg-icmp-name-lookups-08.txt
76 * draft-ietf-mobileip-hmipv6-05.txt
83 static int proto_icmpv6 = -1;
84 static int hf_icmpv6_type = -1;
85 static int hf_icmpv6_code = -1;
86 static int hf_icmpv6_checksum = -1;
87 static int hf_icmpv6_checksum_bad = -1;
88 static int hf_icmpv6_haad_ha_addrs = -1;
89 static int hf_icmpv6_ra_cur_hop_limit = -1;
90 static int hf_icmpv6_ra_router_lifetime = -1;
91 static int hf_icmpv6_ra_reachable_time = -1;
92 static int hf_icmpv6_ra_retrans_timer = -1;
94 static int hf_icmpv6_option = -1;
95 static int hf_icmpv6_option_type = -1;
96 static int hf_icmpv6_option_length = -1;
97 static int hf_icmpv6_opt_cga_pad_len = -1;
98 static int hf_icmpv6_opt_cga = -1;
99 static int hf_icmpv6_opt_cga_modifier = -1;
100 static int hf_icmpv6_opt_cga_subnet_prefix = -1;
101 static int hf_icmpv6_opt_cga_count = -1;
102 static int hf_icmpv6_opt_cga_ext_type = -1;
103 static int hf_icmpv6_opt_cga_ext_length = -1;
104 static int hf_icmpv6_opt_rsa_key_hash = -1;
105 static int hf_icmpv6_opt_name_type = -1;
106 static int hf_icmpv6_opt_name_x501 = -1;
107 static int hf_icmpv6_opt_name_fqdn = -1;
108 static int hf_icmpv6_opt_cert_type = -1;
109 static int hf_icmpv6_identifier = -1;
110 static int hf_icmpv6_all_comp = -1;
111 static int hf_icmpv6_comp = -1;
112 static int hf_icmpv6_x509if_Name = -1;
113 static int hf_icmpv6_x509af_Certificate = -1;
114 static int hf_icmpv6_recursive_dns_serv = -1;
117 static gint ett_icmpv6 = -1;
118 static gint ett_icmpv6opt = -1;
119 static gint ett_icmpv6flag = -1;
120 static gint ett_nodeinfo_flag = -1;
121 static gint ett_nodeinfo_subject4 = -1;
122 static gint ett_nodeinfo_subject6 = -1;
123 static gint ett_nodeinfo_node4 = -1;
124 static gint ett_nodeinfo_node6 = -1;
125 static gint ett_nodeinfo_nodebitmap = -1;
126 static gint ett_nodeinfo_nodedns = -1;
127 static gint ett_multicastRR = -1;
128 static gint ett_icmpv6opt_name = -1;
129 static gint ett_cga_param_name = -1;
131 static dissector_handle_t ipv6_handle;
132 static dissector_handle_t data_handle;
134 static const value_string icmpv6_type_str[] = {
135 { ICMP6_DST_UNREACH, "Unreachable" },
136 { ICMP6_PACKET_TOO_BIG, "Too big" },
137 { ICMP6_TIME_EXCEEDED, "Time exceeded" },
138 { ICMP6_PARAM_PROB, "Parameter problem" },
139 { ICMP6_ECHO_REQUEST, "Echo request" },
140 { ICMP6_ECHO_REPLY, "Echo reply" },
141 { ICMP6_MEMBERSHIP_QUERY, "Multicast listener query" },
142 { ICMP6_MEMBERSHIP_REPORT, "Multicast listener report" },
143 { ICMP6_MEMBERSHIP_REDUCTION, "Multicast listener done" },
144 { ND_ROUTER_SOLICIT, "Router solicitation" },
145 { ND_ROUTER_ADVERT, "Router advertisement" },
146 { ND_NEIGHBOR_SOLICIT, "Neighbor solicitation" },
147 { ND_NEIGHBOR_ADVERT, "Neighbor advertisement" },
148 { ND_REDIRECT, "Redirect" },
149 { ICMP6_ROUTER_RENUMBERING, "Router renumbering" },
150 { ICMP6_NI_QUERY, "Node information query" },
151 { ICMP6_NI_REPLY, "Node information reply" },
152 { ICMP6_IND_SOLICIT, "Inverse neighbor discovery solicitation" },
153 { ICMP6_IND_ADVERT, "Inverse neighbor discovery advertisement" },
154 { ICMP6_MLDV2_REPORT, "Multicast Listener Report Message v2" },
155 { ICMP6_MIP6_DHAAD_REQUEST, "Dynamic Home Agent Address Discovery Request" },
156 { ICMP6_MIP6_DHAAD_REPLY, "Dynamic Home Agent Address Discovery Reply" },
157 { ICMP6_MIP6_MPS, "Mobile Prefix Solicitation" },
158 { ICMP6_MIP6_MPA, "Mobile Prefix Advertisement" },
159 { ICMP6_CERT_PATH_SOL, "Certification Path Solicitation" },
160 { ICMP6_CERT_PATH_AD, "Certification Path Advertisement" },
161 { ICMP6_EXPERIMENTAL_MOBILITY, "Experimental Mobility" },
162 { ICMP6_MCAST_ROUTER_ADVERT, "Multicast Router Advertisement" },
163 { ICMP6_MCAST_ROUTER_SOLICIT, "Multicast Router Solicitation" },
164 { ICMP6_MCAST_ROUTER_TERM, "Multicast Router Termination" },
165 { ICMP6_FMIPV6_MESSAGES, "FMIPv6 Messages" },
169 static const value_string icmpv6_unreach_code_str[] = {
170 { ICMP6_DST_UNREACH_NOROUTE, "Route unreachable" },
171 { ICMP6_DST_UNREACH_ADMIN, "Administratively prohibited" },
172 { ICMP6_DST_UNREACH_NOTNEIGHBOR, "Not a neighbor" },
173 { ICMP6_DST_UNREACH_ADDR, "Address unreachable" },
174 { ICMP6_DST_UNREACH_NOPORT, "Port unreachable" },
178 static const value_string icmpv6_timeex_code_str[] = {
179 { ICMP6_TIME_EXCEED_TRANSIT, "In-transit" },
180 { ICMP6_TIME_EXCEED_REASSEMBLY, "Reassembly" },
184 static const value_string icmpv6_paramprob_code_str[] = {
185 { ICMP6_PARAMPROB_HEADER, "Header" },
186 { ICMP6_PARAMPROB_NEXTHEADER, "Next header" },
187 { ICMP6_PARAMPROB_OPTION, "Option" },
191 static const value_string icmpv6_router_renum_code_str[] = {
192 { ICMP6_ROUTER_RENUMBERING_COMMAND, "Command" },
193 { ICMP6_ROUTER_RENUMBERING_RESULT, "Result" },
194 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "Sequence number reset" },
198 static const value_string names_nodeinfo_qtype[] = {
199 { NI_QTYPE_NOOP, "NOOP" },
200 { NI_QTYPE_SUPTYPES, "Supported query types" },
201 { NI_QTYPE_DNSNAME, "DNS name" },
202 { NI_QTYPE_NODEADDR, "Node addresses" },
203 { NI_QTYPE_IPV4ADDR, "IPv4 node addresses" },
207 static const value_string names_rrenum_matchcode[] = {
208 { RPM_PCO_ADD, "Add" },
209 { RPM_PCO_CHANGE, "Change" },
210 { RPM_PCO_SETGLOBAL, "Set Global" },
214 static const value_string names_router_pref[] = {
215 { ND_RA_FLAG_RTPREF_HIGH, "High" },
216 { ND_RA_FLAG_RTPREF_MEDIUM, "Medium" },
217 { ND_RA_FLAG_RTPREF_LOW, "Low" },
218 { ND_RA_FLAG_RTPREF_RSV, "Reserved" },
222 static const value_string names_fmip6_prrtadv_code[] = {
223 { FMIP6_PRRTADV_MNTUP, "MN should use AP-ID, AR-info tuple" },
224 { FMIP6_PRRTADV_NI_HOVER, "Network Initiated Handover trigger" },
225 { FMIP6_PRRTADV_NORTINFO, "No new router information" },
226 { FMIP6_PRRTADV_LIMRTINFO, "Limited new router information" },
227 { FMIP6_PRRTADV_UNSOL, "Unsolicited" },
231 static const value_string names_fmip6_hi_code[] = {
232 { FMIP6_HI_PCOA, "FBU sent from previous link" },
233 { FMIP6_HI_NOTPCOA, "FBU sent from new link" },
237 static const value_string names_fmip6_hack_code[] = {
238 { FMIP6_HACK_VALID, "Handover Accepted, NCoA valid" },
239 { FMIP6_HACK_INVALID, "Handover Accepted, NCoA not valid" },
240 { FMIP6_HACK_INUSE, "Handover Accepted, NCoA in use" },
241 { FMIP6_HACK_ASSIGNED, "Handover Accepted, NCoA assigned" },
242 { FMIP6_HACK_NOTASSIGNED, "Handover Accepted, NCoA not assigned" },
243 { FMIP6_HACK_NOTACCEPTED, "Handover Not Accepted, reason unspecified" },
244 { FMIP6_HACK_PROHIBITED, "Administratively prohibited" },
245 { FMIP6_HACK_INSUFFICIENT, "Insufficient resources" },
249 static const value_string names_fmip6_ip_addr_opt_code[] = {
250 { FMIP6_OPT_IP_ADDRESS_OPTCODE_PCOA, "Old Care-of Address" },
251 { FMIP6_OPT_IP_ADDRESS_OPTCODE_NCOA, "New Care-of Address" },
252 { FMIP6_OPT_IP_ADDRESS_OPTCODE_NAR, "NAR's IP address" },
256 static const value_string names_fmip6_lla_opt_code[] = {
257 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_WILDCARD, "Wildcard" },
258 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAP, "Link-layer Address of the New Access Point" },
259 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_MN, "Link-layer Address of the MN" },
260 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAR, "Link-layer Address of the NAR" },
261 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_SRC, "Link-layer Address of the source" },
262 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_CURROUTER, "The AP belongs to the current interface of the router" },
263 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOPREFIX, "No prefix information available" },
264 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOSUPPORT, "No fast handovers support available" },
268 static const value_string names_fmip6_naack_opt_status[] = {
269 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID, "New CoA is invalid" },
270 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID_NEW, "New CoA is invalid, use the supplied CoA" },
271 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_UNRECOGNIZED, "LLA is unrecognized" },
275 static const value_string fmip6_opt_type_str[] = {
276 { FMIP6_OPT_IP_ADDRESS, "IP Address" },
277 { FMIP6_OPT_NEW_ROUTER_PREFIX_INFO, "New Router Prefix Information" },
278 { FMIP6_OPT_LINK_LAYER_ADDRESS, "Link-layer Address" },
282 /* http://www.iana.org/assignments/icmpv6-parameters */
283 static const value_string option_vals[] = {
284 { ND_OPT_SOURCE_LINKADDR, "Source link-layer address" },
285 { ND_OPT_TARGET_LINKADDR, "Target link-layer address" },
286 { ND_OPT_PREFIX_INFORMATION, "Prefix information" },
287 { ND_OPT_REDIRECTED_HEADER, "Redirected header" },
288 { ND_OPT_MTU, "MTU" },
289 { ND_OPT_ADVINTERVAL, "Advertisement Interval" },
290 { ND_OPT_HOMEAGENT_INFO, "Home Agent Information" },
291 { ND_OPT_CGA, "CGA" }, /* [RFC3971] */
292 { ND_OPT_RSA, "RSA Signature" }, /* [RFC3971] */
293 { ND_OPT_TIMESTAMP, "Timestamp" }, /* [RFC3971] */
294 { ND_OPT_NONCE, "Nonce" }, /* [RFC3971] */
295 { ND_OPT_TRUST_ANCHOR, "Trust Anchor" }, /* [RFC3971] */
296 { 16, "Certificate" }, /* [RFC3971] */
297 { FMIP6_OPT_IP_ADDRESS, "IP Address Option" }, /* [RFC4068] */
298 { FMIP6_OPT_NEW_ROUTER_PREFIX_INFO, "New Router Prefix Information" }, /* [RFC4068] */
299 { FMIP6_OPT_LINK_LAYER_ADDRESS, "Link-layer Address" }, /* [RFC4068] */
300 { FMIP6_OPT_NEIGHBOR_ADV_ACK, "Neighbor Advertisement Acknowledgment" }, /* [RFC4068] */
301 { 21, "CARD Request" }, /* [RFC4065] */
302 { 22, "CARD Reply" }, /* [RFC4065] */
303 { 23, "MAP" }, /* [RFC4140] */
304 { ND_OPT_ROUTE_INFO, "Route Information" }, /* [RFC4191] */
305 { ND_OPT_RECURSIVE_DNS_SERVER, "Recursive DNS Server" }, /* [RFC5006] */
306 { 26, "RA Flags Extension" }, /* [RFC5075] */
307 { 27, "Handover Key Request" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
308 { 28, "Handover Key Reply" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
309 { ND_OPT_MAP, "HMIPv6 MAP option" },
310 /*29-252 Unassigned */
311 { 253, "RFC3692-style Experiment 1" }, /* [RFC4727] */
312 { 254, "RFC3692-style Experiment 2" }, /* [RFC4727] */
316 static const value_string icmpv6_option_name_type_vals[] = {
317 { 1, "DER Encoded X.501 Name" },
322 static const value_string icmpv6_option_cert_type_vals[] = {
323 { 1, "X.509v3 Certificate" },
328 dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
330 gboolean save_in_error_pkt;
333 /* Save the current value of the "we're inside an error packet"
334 flag, and set that flag; subdissectors may treat packets
335 that are the payload of error packets differently from
337 save_in_error_pkt = pinfo->in_error_pkt;
338 pinfo->in_error_pkt = TRUE;
340 next_tvb = tvb_new_subset_remaining(tvb, offset);
342 /* tiny sanity check */
343 if ((tvb_get_guint8(tvb, offset) & 0xf0) == 0x60) {
344 /* The contained packet is an IPv6 datagram; dissect it. */
345 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
347 call_dissector(data_handle,next_tvb, pinfo, tree);
349 /* Restore the "we're inside an error packet" flag. */
350 pinfo->in_error_pkt = save_in_error_pkt;
354 dissect_icmpv6ndopt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
356 proto_tree *icmp6opt_tree, *field_tree, *name_tree, *cga_tree;
357 proto_item *ti, *tf, *name_item, *cga_item;
358 struct nd_opt_hdr nd_opt_hdr, *opt;
360 const char *typename;
361 static const guint8 nd_redirect_reserved[6] = {0, 0, 0, 0, 0, 0};
362 guint8 nd_redirect_res[6];
364 guint8 padd_length = 0;
366 guint8 name_type = 0;
367 guint8 cert_type = 0;
377 if ((int)tvb_reported_length(tvb) <= offset)
378 return; /* No more options left */
381 tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
382 len = opt->nd_opt_len << 3;
384 /* !!! specify length */
385 ti = proto_tree_add_item(tree, hf_icmpv6_option, tvb, offset, len, FALSE);
386 icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
389 proto_tree_add_text(icmp6opt_tree, tvb,
390 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
391 "Invalid option length: %u",
393 return; /* we must not try to decode this */
396 typename = val_to_str(opt->nd_opt_type, option_vals, "Unknown");
398 /* Add option name to option root label */
399 proto_item_append_text(ti, " (%s)", typename);
402 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_option_type, tvb,
403 offset + offsetof(struct nd_opt_hdr, nd_opt_type), 1, FALSE);
405 proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_option_length, tvb,
406 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
407 opt->nd_opt_len << 3);
410 switch (opt->nd_opt_type) {
411 case ND_OPT_SOURCE_LINKADDR:
412 case ND_OPT_TARGET_LINKADDR:
416 p = offset + sizeof(*opt);
417 len_local = (opt->nd_opt_len << 3) - sizeof(*opt);
418 proto_tree_add_text(icmp6opt_tree, tvb,
419 offset + sizeof(*opt), len_local, "Link-layer address: %s",
420 bytestring_to_str(tvb_get_ptr(tvb, p, len_local), len_local, ':'));
423 case ND_OPT_PREFIX_INFORMATION:
425 struct nd_opt_prefix_info nd_opt_prefix_info, *pi;
428 pi = &nd_opt_prefix_info;
429 tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
430 proto_tree_add_text(icmp6opt_tree, tvb,
431 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix_len),
432 1, "Prefix length: %u", pi->nd_opt_pi_prefix_len);
434 flagoff = offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved);
435 tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1, "Flags: 0x%02x",
436 tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved)));
437 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
438 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
439 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
440 ND_OPT_PI_FLAG_ONLINK, 8, "Onlink", "Not onlink"));
441 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
442 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
443 ND_OPT_PI_FLAG_AUTO, 8, "Auto", "Not auto"));
444 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
445 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
446 ND_OPT_PI_FLAG_ROUTER, 8,
447 "Router Address", "Not router address"));
448 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
449 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
450 ND_OPT_PI_FLAG_SITEPREF, 8,
451 "Site prefix", "Not site prefix"));
452 if (pntohl(&pi->nd_opt_pi_valid_time) == 0xffffffff)
453 proto_tree_add_text(icmp6opt_tree, tvb,
454 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
455 4, "Valid lifetime: infinity");
457 proto_tree_add_text(icmp6opt_tree, tvb,
458 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
459 4, "Valid lifetime: %u",
460 pntohl(&pi->nd_opt_pi_valid_time));
461 if (pntohl(&pi->nd_opt_pi_preferred_time) == 0xffffffff)
462 proto_tree_add_text(icmp6opt_tree, tvb,
463 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
464 4, "Preferred lifetime: infinity");
466 proto_tree_add_text(icmp6opt_tree, tvb,
467 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
468 4, "Preferred lifetime: %u",
469 pntohl(&pi->nd_opt_pi_preferred_time));
470 proto_tree_add_text(icmp6opt_tree, tvb,
471 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix),
472 16, "Prefix: %s", ip6_to_str(&pi->nd_opt_pi_prefix));
475 case ND_OPT_REDIRECTED_HEADER:
476 tvb_memcpy(tvb, (guint8 *)&nd_redirect_res, offset + 2, 6);
477 if (memcmp(nd_redirect_res, nd_redirect_reserved, 6) == 0)
478 proto_tree_add_text(icmp6opt_tree, tvb,
479 offset + 2, 6, "Reserved: 0 (correct)");
481 proto_tree_add_text(icmp6opt_tree, tvb,
482 offset +2, 6, "Reserved: MUST be 0 (incorrect!)");
483 proto_tree_add_text(icmp6opt_tree, tvb,
484 offset + 8, (opt->nd_opt_len << 3) - 8, "Redirected packet");
485 dissect_contained_icmpv6(tvb, offset + 8, pinfo, icmp6opt_tree);
488 proto_tree_add_text(icmp6opt_tree, tvb,
489 offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu), 4,
490 "MTU: %u", tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu)));
492 case ND_OPT_ADVINTERVAL:
493 proto_tree_add_text(icmp6opt_tree, tvb,
494 offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint), 4,
495 "Advertisement Interval: %u",
496 tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint)));
498 case ND_OPT_HOMEAGENT_INFO: /* 8 */
500 struct nd_opt_ha_info pibuf, *pi;
503 tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
504 proto_tree_add_text(icmp6opt_tree, tvb,
505 offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_pref),
506 2, "Home Agent Preference: %d",
507 (gint16)pntohs(&pi->nd_opt_ha_info_ha_pref));
508 proto_tree_add_text(icmp6opt_tree, tvb,
509 offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_life),
510 2, "Home Agent Lifetime: %u",
511 pntohs(&pi->nd_opt_ha_info_ha_life));
514 case ND_OPT_CGA: /* 11 */ {
515 guint16 ext_data_len;
516 /* RFC 3971 5.1. CGA Option */
518 opt_offset = offset +2;
519 padd_length = tvb_get_guint8(tvb,opt_offset);
520 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
522 /* Reserved 8 bits */
523 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
525 /* CGA Parameters A variable-length field containing the CGA Parameters data
526 * structure described in Section 4 of
527 * "Cryptographically Generated Addresses (CGA)", RFC3972.
529 par_len = len-4-padd_length;
530 cga_item = proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga, tvb, opt_offset, par_len, FALSE);
531 par_len += opt_offset;
532 cga_tree = proto_item_add_subtree(cga_item, ett_cga_param_name);
533 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_modifier,tvb, opt_offset,16,FALSE);
535 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_subnet_prefix,tvb,opt_offset,8,FALSE);
537 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_count,tvb,opt_offset,1,FALSE);
539 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
540 opt_offset = dissect_x509af_SubjectPublicKeyInfo(FALSE, tvb, opt_offset, &asn1_ctx, cga_tree, -1);
541 /* Process RFC 4581*/
542 while (opt_offset < par_len) {
543 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_type,tvb,opt_offset,2,FALSE);
545 ext_data_len = tvb_get_ntohs(tvb,opt_offset);
546 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_length,tvb,opt_offset,2,FALSE);
548 proto_tree_add_text(cga_tree,tvb,opt_offset,ext_data_len,"Ext Data");
549 opt_offset += ext_data_len;
553 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
556 case ND_OPT_RSA: /* 12 */
557 /*5.2. RSA Signature Option */
558 opt_offset = offset +2;
559 /* Reserved, A 16-bit field reserved for future use. */
560 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Reserved");
561 opt_offset = opt_offset + 2;
563 * A 128-bit field containing the most significant (leftmost) 128
564 * bits of a SHA-1 [14] hash of the public key used for constructing
567 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_rsa_key_hash, tvb, opt_offset, 16, FALSE);
568 opt_offset = opt_offset + 16;
569 /* Digital Signature */
571 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Digital Signature + Padding");
573 /* TODO: Calculate padding length and exlude from the signature */
575 case ND_OPT_TIMESTAMP: /* 13 */
576 opt_offset = offset +2;
577 /* Reserved A 48-bit field reserved for future use. */
578 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Reserved");
579 opt_offset = opt_offset + 6;
581 * A 64-bit unsigned integer field containing a timestamp. The value
582 * indicates the number of seconds since January 1, 1970, 00:00 UTC,
583 * by using a fixed point format. In this format, the integer number
584 * of seconds is contained in the first 48 bits of the field, and the
585 * remaining 16 bits indicate the number of 1/64K fractions of a
588 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Timestamp(number of seconds since January 1, 1970, 00:00 UTC)");
589 opt_offset = opt_offset + 6;
590 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Timestamp(1/64K fractions of a second)");
593 /* 5.3.2. Nonce Option */
594 opt_offset = offset +2;
595 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,len-2,"Nonce");
598 case ND_OPT_TRUST_ANCHOR:
599 opt_offset = offset +2;
601 name_type = tvb_get_guint8(tvb,opt_offset);
602 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_type, tvb, opt_offset, 1, FALSE);
605 padd_length = tvb_get_guint8(tvb,opt_offset);
606 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
608 par_len = len - 4 - padd_length;
611 /* DER Encoded X.501 Name */
612 name_item =proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_x501, tvb, opt_offset, par_len, FALSE);
613 name_tree = proto_item_add_subtree(name_item, ett_icmpv6opt_name);
614 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
615 dissect_x509if_Name(FALSE, tvb, opt_offset, &asn1_ctx, name_tree, hf_icmpv6_x509if_Name);
619 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_fqdn, tvb, opt_offset, par_len, FALSE);
622 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset, par_len,"Unknown name type");
625 opt_offset = opt_offset + par_len;
627 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
628 opt_offset = opt_offset + padd_length;
630 case ND_OPT_CERTIFICATE:
631 opt_offset = offset +2;
633 cert_type = tvb_get_guint8(tvb,opt_offset);
634 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cert_type, tvb, opt_offset, 1, FALSE);
637 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
642 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
643 opt_offset = dissect_x509af_Certificate(FALSE, tvb, opt_offset, &asn1_ctx, icmp6opt_tree, hf_icmpv6_x509af_Certificate);
644 par_len = len - (opt_offset - offset);
646 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Padding");
649 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Unknown Certificate + padding");
655 struct nd_opt_map_info mapbuf, *map;
659 tvb_memcpy(tvb, (guint8 *)map, offset, sizeof *map);
660 proto_tree_add_text(icmp6opt_tree, tvb,
661 offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
662 1, "Distance: %u", (map->nd_opt_map_dist_and_pref >> 4));
663 proto_tree_add_text(icmp6opt_tree, tvb,
664 offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
665 1, "Preference: %u", (map->nd_opt_map_dist_and_pref & 0x0F));
666 flagoff = offset + offsetof(struct nd_opt_map_info,
668 tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
670 tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_map_info,
672 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
673 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
674 decode_boolean_bitfield(map->nd_opt_map_flags,
675 ND_OPT_MAP_FLAG_R, 8, "R", "No R"));
676 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
677 decode_boolean_bitfield(map->nd_opt_map_flags,
678 ND_OPT_MAP_FLAG_M, 8, "M", "No M"));
679 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
680 decode_boolean_bitfield(map->nd_opt_map_flags,
681 ND_OPT_MAP_FLAG_I, 8, "I", "No I"));
682 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
683 decode_boolean_bitfield(map->nd_opt_map_flags,
684 ND_OPT_MAP_FLAG_T, 8, "T", "No T"));
685 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
686 decode_boolean_bitfield(map->nd_opt_map_flags,
687 ND_OPT_MAP_FLAG_P, 8, "P", "No P"));
688 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
689 decode_boolean_bitfield(map->nd_opt_map_flags,
690 ND_OPT_MAP_FLAG_V, 8, "V", "No V"));
691 proto_tree_add_text(icmp6opt_tree, tvb,
692 offset + offsetof(struct nd_opt_map_info, nd_opt_map_lifetime),
693 4, "Lifetime: %u", pntohl(&map->nd_opt_map_lifetime));
695 proto_tree_add_text(icmp6opt_tree, tvb,
696 offset + offsetof(struct nd_opt_map_info, nd_opt_map_address), 16,
698 "Address of MAP: %s (%s)",
699 get_hostname6(&map->nd_opt_map_address),
701 "Address of MAP: %s",
703 ip6_to_str(&map->nd_opt_map_address));
706 case ND_OPT_ROUTE_INFO:
708 struct nd_opt_route_info ribuf, *ri;
709 struct e_in6_addr in6;
711 guint32 lifetime_local;
714 tvb_memcpy(tvb, (guint8 *)ri, offset, sizeof *ri);
715 memset(&in6, 0, sizeof(in6));
716 switch (ri->nd_opt_rti_len) {
721 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 8);
724 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 16);
731 proto_tree_add_text(icmp6opt_tree, tvb,
732 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_prefixlen),
733 1, "Prefix length: %u", ri->nd_opt_rti_prefixlen);
734 tf = proto_tree_add_text(icmp6opt_tree, tvb,
735 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
736 1, "Flags: 0x%02x", ri->nd_opt_rti_flags);
737 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
738 proto_tree_add_text(field_tree, tvb,
739 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
741 decode_enumerated_bitfield(ri->nd_opt_rti_flags,
742 ND_RA_FLAG_RTPREF_MASK, 8, names_router_pref,
743 "Router preference: %s"));
744 lifetime_local = pntohl(&ri->nd_opt_rti_lifetime);
745 if (lifetime_local == 0xffffffff)
746 proto_tree_add_text(icmp6opt_tree, tvb,
747 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
748 sizeof(ri->nd_opt_rti_lifetime), "Lifetime: infinity");
750 proto_tree_add_text(icmp6opt_tree, tvb,
751 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
752 sizeof(ri->nd_opt_rti_lifetime), "Lifetime: %u", lifetime_local);
753 proto_tree_add_text(icmp6opt_tree, tvb,
754 offset + sizeof(*ri), l, "Prefix: %s", ip6_to_str(&in6));
756 proto_tree_add_text(icmp6opt_tree, tvb,
757 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
758 "Invalid option length: %u", opt->nd_opt_len);
763 case FMIP6_OPT_NEIGHBOR_ADV_ACK:
765 struct fmip6_opt_neighbor_advertisement_ack fmip6_opt_neighbor_advertisement_ack, *opt_naack;
766 struct e_in6_addr in6;
768 opt_naack = &fmip6_opt_neighbor_advertisement_ack;
769 tvb_memcpy(tvb, (guint8 *)opt_naack, offset, sizeof *opt_naack);
771 proto_tree_add_text(icmp6opt_tree, tvb,
772 offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_optcode),
773 1, "Option-Code: %u",
774 opt_naack->fmip6_opt_optcode);
776 proto_tree_add_text(icmp6opt_tree, tvb,
777 offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_status),
779 val_to_str(opt_naack->fmip6_opt_status, names_fmip6_naack_opt_status, "Unknown"));
781 if (opt_naack->fmip6_opt_len == 3){
782 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*opt_naack), 16);
783 proto_tree_add_text(icmp6opt_tree, tvb,
784 offset + sizeof(*opt_naack),
785 16, "New Care-of Address: %s",
791 case ND_OPT_RECURSIVE_DNS_SERVER:
793 opt_offset = offset + 2;
794 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,2 ,"Reserved");
795 opt_offset = opt_offset + 2;
796 /* A value of all one bits (0xffffffff) represents infinity. A value of
797 * zero means that the RDNSS address MUST no longer be used.
799 lifetime = tvb_get_ntohl(tvb, opt_offset);
800 if (lifetime == 0xffffffff){
801 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: infinity");
804 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: RDNSS address MUST no longer be used");
806 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: %u", lifetime);
809 opt_offset = opt_offset+4;
810 /* Addresses of IPv6 Recursive DNS Servers */
811 no_of_pars = opt->nd_opt_len - 1;
812 no_of_pars = no_of_pars >> 2;
814 for (i = 0; i <= no_of_pars; i++) {
815 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_recursive_dns_serv, tvb, opt_offset, 16, FALSE);
816 opt_offset = opt_offset+16;
823 offset += (opt->nd_opt_len << 3);
825 /* Set length of option tree */
826 proto_item_set_len(ti, opt->nd_opt_len << 3);
831 dissect_icmpv6fmip6opt(tvbuff_t *tvb, int offset, proto_tree *tree)
833 proto_tree *icmp6opt_tree;
835 struct fmip6_opt_hdr fmip6_opt_hdr, *opt;
837 const char *typename;
843 if ((int)tvb_reported_length(tvb) <= offset)
844 return; /* No more options left */
846 opt = &fmip6_opt_hdr;
847 tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
848 len = opt->fmip6_opt_len << 3;
850 /* !!! specify length */
851 ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
852 icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
855 proto_tree_add_text(icmp6opt_tree, tvb,
856 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
857 "Invalid option length: %u",
859 return; /* we must not try to decode this */
862 typename = val_to_str (opt->fmip6_opt_type, fmip6_opt_type_str, "Unknown");
864 proto_tree_add_text(icmp6opt_tree, tvb,
865 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_type), 1,
866 "Type: %u (%s)", opt->fmip6_opt_type, typename);
867 proto_tree_add_text(icmp6opt_tree, tvb,
868 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
869 "Length: %u bytes (%u)", opt->fmip6_opt_len << 3, opt->fmip6_opt_len);
872 switch (opt->fmip6_opt_type) {
873 case FMIP6_OPT_IP_ADDRESS:
875 struct fmip6_opt_ip_address fmip6_opt_ip_address, *opt_ip;
877 opt_ip = &fmip6_opt_ip_address;
878 tvb_memcpy(tvb, (guint8 *)opt_ip, offset, sizeof *opt_ip);
880 proto_tree_add_text(icmp6opt_tree, tvb,
881 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
882 val_to_str(opt->fmip6_opt_optcode, names_fmip6_ip_addr_opt_code, "Unknown"));
884 proto_tree_add_text(icmp6opt_tree, tvb,
885 offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_prefix_len),
886 1, "Prefix length: %u", opt_ip->fmip6_opt_prefix_len);
888 proto_tree_add_text(icmp6opt_tree, tvb,
889 offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_ip6_address),
890 16, "IPv6 Address: %s",
891 ip6_to_str(&opt_ip->fmip6_opt_ip6_address));
894 case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
896 struct fmip6_opt_new_router_prefix_info fmip6_opt_new_router_prefix_info, *opt_nr;
898 opt_nr = &fmip6_opt_new_router_prefix_info;
899 tvb_memcpy(tvb, (guint8 *)opt_nr, offset, sizeof *opt_nr);
901 proto_tree_add_text(icmp6opt_tree, tvb,
902 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %u",
903 opt->fmip6_opt_optcode);
905 proto_tree_add_text(icmp6opt_tree, tvb,
906 offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix_len),
907 1, "Prefix length: %u", opt_nr->fmip6_opt_prefix_len);
909 proto_tree_add_text(icmp6opt_tree, tvb,
910 offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix),
912 ip6_to_str(&opt_nr->fmip6_opt_prefix));
915 case FMIP6_OPT_LINK_LAYER_ADDRESS:
919 p = offset + sizeof(*opt);
920 proto_tree_add_text(icmp6opt_tree, tvb,
921 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
922 val_to_str(opt->fmip6_opt_optcode, names_fmip6_lla_opt_code, "Unknown"));
923 len_local = (opt->fmip6_opt_len << 3) - sizeof(*opt);
924 proto_tree_add_text(icmp6opt_tree, tvb,
925 offset + sizeof(*opt), len_local, "Link-layer address: %s",
926 bytestring_to_str(tvb_get_ptr(tvb, p, len_local), len_local, ':'));
931 offset += (opt->fmip6_opt_len << 3);
936 * draft-ietf-ipngwg-icmp-name-lookups-07.txt
937 * Note that the packet format was changed several times in the past.
941 bitrange0(guint32 v, int s, emem_strbuf_t *strbuf)
950 /* shift till we have 0x01 */
951 if ((v & 0x01) == 0) {
954 v >>= 4; off += 4; continue;
956 v >>= 3; off += 3; continue;
957 case 0x04: case 0x0c:
958 v >>= 2; off += 2; continue;
960 v >>= 1; off += 1; continue;
964 /* we have 0x01 with us */
965 for (i = 0; i < 32 - off; i++) {
966 if ((v & (0x01 << i)) == 0)
970 ep_strbuf_append_printf(strbuf, ",%d", s + off);
972 ep_strbuf_append_printf(strbuf, ",%d-%d", s + off,
980 bitrange(tvbuff_t *tvb, int offset, int l, int s)
982 emem_strbuf_t *strbuf;
985 strbuf = ep_strbuf_new_label(NULL);
986 for (i = 0; i < l; i++)
987 bitrange0(tvb_get_ntohl(tvb, offset + i * 4), s + i * 4, strbuf);
989 return strbuf->str + 1; /* skip initial "," */
993 #define NI_FLAGS_SIZE 2
994 #define NI_FLAGS_OFFSET 6
995 #define NI_NONCE_SIZE 8
996 #define NI_NONCE_OFFSET 8
998 dissect_nodeinfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1000 proto_tree *field_tree;
1002 struct icmp6_nodeinfo icmp6_nodeinfo, *ni;
1007 const guchar *dname;
1010 ni = &icmp6_nodeinfo;
1011 tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
1013 flags = pntohs(&ni->ni_flags);
1014 tf = proto_tree_add_text(tree, tvb,
1015 offset + NI_FLAGS_OFFSET,
1016 NI_FLAGS_SIZE, "Flags: 0x%04x", flags);
1017 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_flag);
1018 switch (pntohs(&ni->ni_qtype)) {
1019 case NI_QTYPE_SUPTYPES:
1020 if (ni->ni_type == ICMP6_NI_QUERY) {
1021 proto_tree_add_text(field_tree, tvb,
1022 offset + NI_FLAGS_OFFSET,
1023 NI_FLAGS_SIZE, "%s",
1024 decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
1025 "Compressed reply supported",
1026 "No compressed reply support"));
1028 proto_tree_add_text(field_tree, tvb,
1029 offset + NI_FLAGS_OFFSET,
1030 NI_FLAGS_SIZE, "%s",
1031 decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
1032 "Compressed", "Not compressed"));
1035 case NI_QTYPE_DNSNAME:
1036 if (ni->ni_type == ICMP6_NI_REPLY) {
1037 proto_tree_add_text(field_tree, tvb,
1038 offset + NI_FLAGS_OFFSET,
1039 NI_FLAGS_SIZE, "%s",
1040 decode_boolean_bitfield(flags, NI_FQDN_FLAG_VALIDTTL, sizeof(flags) * 8,
1041 "Valid TTL field", "Meaningless TTL field"));
1044 case NI_QTYPE_NODEADDR:
1045 proto_tree_add_text(field_tree, tvb,
1046 offset + NI_FLAGS_OFFSET,
1047 NI_FLAGS_SIZE, "%s",
1048 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_GLOBAL, sizeof(flags) * 8,
1050 "Not global address"));
1051 proto_tree_add_text(field_tree, tvb,
1052 offset + NI_FLAGS_OFFSET,
1053 NI_FLAGS_SIZE, "%s",
1054 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_SITELOCAL, sizeof(flags) * 8,
1055 "Site-local address",
1056 "Not site-local address"));
1057 proto_tree_add_text(field_tree, tvb,
1058 offset + NI_FLAGS_OFFSET,
1059 NI_FLAGS_SIZE, "%s",
1060 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_LINKLOCAL, sizeof(flags) * 8,
1061 "Link-local address",
1062 "Not link-local address"));
1063 proto_tree_add_text(field_tree, tvb,
1064 offset + NI_FLAGS_OFFSET,
1065 NI_FLAGS_SIZE, "%s",
1066 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_COMPAT, sizeof(flags) * 8,
1067 "IPv4 compatible/mapped address",
1068 "Not IPv4 compatible/mapped address"));
1070 case NI_QTYPE_IPV4ADDR:
1071 proto_tree_add_text(field_tree, tvb,
1072 offset + NI_FLAGS_OFFSET,
1073 NI_FLAGS_SIZE, "%s",
1074 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_ALL, sizeof(flags) * 8,
1075 "All unicast address",
1076 "Unicast addresses on the queried interface"));
1077 proto_tree_add_text(field_tree, tvb,
1078 offset + NI_FLAGS_OFFSET,
1079 NI_FLAGS_SIZE, "%s",
1080 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_TRUNCATE, sizeof(flags) * 8,
1081 "Truncated", "Not truncated"));
1086 proto_tree_add_text(tree, tvb,
1087 offset + NI_NONCE_OFFSET,
1088 NI_NONCE_SIZE, "Nonce: 0x%08x%08x",
1089 pntohl(&ni->icmp6_ni_nonce[0]), pntohl(&ni->icmp6_ni_nonce[4]));
1091 /* offset for "the rest of data" */
1095 if (!tvb_bytes_exist(tvb, offset, sizeof(*ni)))
1097 if (ni->ni_type == ICMP6_NI_QUERY) {
1098 switch (ni->ni_code) {
1099 case ICMP6_NI_SUBJ_IPV6:
1100 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1101 n /= sizeof(struct e_in6_addr);
1102 tf = proto_tree_add_text(tree, tvb,
1103 offset + sizeof(*ni), -1, "IPv6 subject addresses");
1104 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject6);
1105 p = offset + sizeof *ni;
1106 for (i = 0; i < n; i++) {
1107 struct e_in6_addr e_in6_addr;
1108 tvb_get_ipv6(tvb, p, &e_in6_addr);
1109 proto_tree_add_text(field_tree, tvb,
1110 p, sizeof(struct e_in6_addr),
1111 "%s", ip6_to_str(&e_in6_addr));
1112 p += sizeof(struct e_in6_addr);
1114 off = tvb_length_remaining(tvb, offset);
1116 case ICMP6_NI_SUBJ_FQDN:
1117 /* XXX Fix data length */
1118 l = get_dns_name(tvb, offset + sizeof(*ni), 0,
1119 offset + sizeof(*ni), &dname);
1120 if (tvb_bytes_exist(tvb, offset + sizeof(*ni) + l, 1) &&
1121 tvb_get_guint8(tvb, offset + sizeof(*ni) + l) == 0) {
1123 proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
1124 "DNS label: %s (truncated)", dname);
1126 proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
1127 "DNS label: %s", dname);
1129 off = tvb_length_remaining(tvb, offset + sizeof(*ni) + l);
1131 case ICMP6_NI_SUBJ_IPV4:
1132 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1133 n /= sizeof(guint32);
1134 tf = proto_tree_add_text(tree, tvb,
1135 offset + sizeof(*ni), -1, "IPv4 subject addresses");
1136 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject4);
1137 p = offset + sizeof *ni;
1138 for (i = 0; i < n; i++) {
1139 ipaddr = tvb_get_ipv4(tvb, p);
1140 proto_tree_add_text(field_tree, tvb,
1141 p, sizeof(guint32), "%s", ip_to_str((guint8 *)&ipaddr));
1142 p += sizeof(guint32);
1144 off = tvb_length_remaining(tvb, offset);
1148 switch (pntohs(&ni->ni_qtype)) {
1151 case NI_QTYPE_SUPTYPES:
1152 p = offset + sizeof *ni;
1153 tf = proto_tree_add_text(tree, tvb,
1154 offset + sizeof(*ni), -1,
1155 "Supported type bitmap%s",
1156 (flags & 0x0001) ? ", compressed" : "");
1157 field_tree = proto_item_add_subtree(tf,
1158 ett_nodeinfo_nodebitmap);
1160 while (tvb_bytes_exist(tvb, p, sizeof(guint32))) { /* XXXX Check what? */
1161 if ((flags & 0x0001) == 0) {
1162 l = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1163 l /= sizeof(guint32);
1166 l = tvb_get_ntohs(tvb, p);
1167 i = tvb_get_ntohs(tvb, p + sizeof(guint16)); /*skip*/
1169 if (n + l * 32 > (1 << 16))
1171 if (n + (l + i) * 32 > (1 << 16))
1173 if ((flags & 0x0001) == 0) {
1174 proto_tree_add_text(field_tree, tvb, p,
1175 l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
1176 bitrange(tvb, p, l, n));
1179 proto_tree_add_text(field_tree, tvb, p,
1180 4 + l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
1181 bitrange(tvb, p + 4, l, n));
1184 n += l * 32 + i * 32;
1186 off = tvb_length_remaining(tvb, offset);
1188 case NI_QTYPE_DNSNAME:
1189 proto_tree_add_text(tree, tvb, offset + sizeof(*ni),
1190 sizeof(gint32), "TTL: %d", (gint32)tvb_get_ntohl(tvb, offset + sizeof *ni));
1191 tf = proto_tree_add_text(tree, tvb,
1192 offset + sizeof(*ni) + sizeof(guint32), -1,
1194 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
1195 j = offset + sizeof (*ni) + sizeof(guint32);
1196 while (j < tvb_reported_length(tvb)) {
1197 /* XXX Fix data length */
1198 l = get_dns_name(tvb, j, 0,
1199 offset + sizeof (*ni) + sizeof(guint32),
1201 if (tvb_bytes_exist(tvb, j + l, 1) &&
1202 tvb_get_guint8(tvb, j + l) == 0) {
1204 proto_tree_add_text(field_tree, tvb, j, l,
1205 "DNS label: %s (truncated)", dname);
1207 proto_tree_add_text(field_tree, tvb, j, l,
1208 "DNS label: %s", dname);
1212 off = tvb_length_remaining(tvb, offset);
1214 case NI_QTYPE_NODEADDR:
1215 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1216 n /= sizeof(gint32) + sizeof(struct e_in6_addr);
1217 tf = proto_tree_add_text(tree, tvb,
1218 offset + sizeof(*ni), -1, "IPv6 node addresses");
1219 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node6);
1220 p = offset + sizeof (*ni);
1221 for (i = 0; i < n; i++) {
1222 struct e_in6_addr e_in6_addr;
1224 ttl = (gint32)tvb_get_ntohl(tvb, p);
1225 tvb_get_ipv6(tvb, p + sizeof ttl, &e_in6_addr);
1226 proto_tree_add_text(field_tree, tvb,
1227 p, sizeof(struct e_in6_addr) + sizeof(gint32),
1228 "%s (TTL %d)", ip6_to_str(&e_in6_addr), ttl);
1229 p += sizeof(struct e_in6_addr) + sizeof(gint32);
1231 off = tvb_length_remaining(tvb, offset);
1233 case NI_QTYPE_IPV4ADDR:
1234 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1235 n /= sizeof(gint32) + sizeof(guint32);
1236 tf = proto_tree_add_text(tree, tvb,
1237 offset + sizeof(*ni), -1, "IPv4 node addresses");
1238 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node4);
1239 p = offset + sizeof *ni;
1240 for (i = 0; i < n; i++) {
1241 ipaddr = tvb_get_ipv4(tvb, sizeof(gint32) + p);
1242 proto_tree_add_text(field_tree, tvb,
1243 p, sizeof(guint32), "%s (TTL %d)",
1244 ip_to_str((guint8 *)&ipaddr), tvb_get_ntohl(tvb, p));
1245 p += sizeof(gint32) + sizeof(guint32);
1247 off = tvb_length_remaining(tvb, offset);
1253 /* the rest of data */
1254 call_dissector(data_handle,tvb_new_subset_remaining(tvb, offset + off), pinfo, tree);
1258 #define RR_SEQNUM_SIZE 4
1259 #define RR_SEQNUM_OFFSET 4
1260 #define RR_SEGNUM_SIZE 1
1261 #define RR_SEGNUM_OFFSET 8
1262 #define RR_FLAGS_SIZE 1
1263 #define RR_FLAGS_OFFSET 9
1265 dissect_rrenum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1267 proto_tree *field_tree, *opt_tree;
1269 struct icmp6_router_renum icmp6_router_renum, *rr;
1270 struct rr_pco_match rr_pco_match, *match;
1271 struct rr_pco_use rr_pco_use, *use;
1276 rr = &icmp6_router_renum;
1277 tvb_memcpy(tvb, (guint8 *)rr, offset, sizeof *rr);
1278 proto_tree_add_text(tree, tvb,
1279 offset + RR_SEQNUM_OFFSET, RR_SEQNUM_SIZE,
1280 "Sequence number: 0x%08x", pntohl(&rr->rr_seqnum));
1281 proto_tree_add_text(tree, tvb,
1282 offset + RR_SEGNUM_OFFSET, RR_SEGNUM_SIZE,
1283 "Segment number: 0x%02x", rr->rr_segnum);
1285 flagoff = offset + RR_FLAGS_OFFSET;
1286 flags = tvb_get_guint8(tvb, flagoff);
1287 tf = proto_tree_add_text(tree, tvb, flagoff, RR_FLAGS_SIZE,
1288 "Flags: 0x%02x", flags);
1289 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1290 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1291 decode_boolean_bitfield(flags, 0x80, 8,
1292 "Test command", "Not test command"));
1293 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1294 decode_boolean_bitfield(flags, 0x40, 8,
1295 "Result requested", "Result not requested"));
1296 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1297 decode_boolean_bitfield(flags, 0x20, 8,
1298 "All interfaces", "Not all interfaces"));
1299 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1300 decode_boolean_bitfield(flags, 0x10, 8,
1301 "Site specific", "Not site specific"));
1302 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1303 decode_boolean_bitfield(flags, 0x08, 8,
1304 "Processed previously", "Complete result"));
1306 proto_tree_add_text(tree, tvb,
1307 offset + offsetof(struct icmp6_router_renum, rr_maxdelay), 2,
1308 "Max delay: 0x%04x", pntohs(&rr->rr_maxdelay));
1309 call_dissector(data_handle,tvb_new_subset_remaining(tvb, offset + RR_SIZE), pinfo, tree); /*XXX*/
1311 if (rr->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
1312 off = offset + RR_SIZE;
1313 match = &rr_pco_match;
1314 tvb_memcpy(tvb, (guint8 *)match, off, sizeof *match);
1315 tf = proto_tree_add_text(tree, tvb, off, sizeof(*match),
1316 "Match-Prefix: %s/%u (%u-%u)", ip6_to_str(&match->rpm_prefix),
1317 match->rpm_matchlen, match->rpm_minlen, match->rpm_maxlen);
1318 opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
1319 proto_tree_add_text(opt_tree, tvb,
1320 off + offsetof(struct rr_pco_match, rpm_code),
1321 sizeof(match->rpm_code), "OpCode: %s (%u)",
1322 val_to_str(match->rpm_code, names_rrenum_matchcode, "Unknown"),
1324 proto_tree_add_text(opt_tree, tvb,
1325 off + offsetof(struct rr_pco_match, rpm_len),
1326 sizeof(match->rpm_len), "OpLength: %u (%u octets)",
1327 match->rpm_len, match->rpm_len * 8);
1328 proto_tree_add_text(opt_tree, tvb,
1329 off + offsetof(struct rr_pco_match, rpm_ordinal),
1330 sizeof(match->rpm_ordinal), "Ordinal: %u", match->rpm_ordinal);
1331 proto_tree_add_text(opt_tree, tvb,
1332 off + offsetof(struct rr_pco_match, rpm_matchlen),
1333 sizeof(match->rpm_matchlen), "MatchLen: %u", match->rpm_matchlen);
1334 proto_tree_add_text(opt_tree, tvb,
1335 off + offsetof(struct rr_pco_match, rpm_minlen),
1336 sizeof(match->rpm_minlen), "MinLen: %u", match->rpm_minlen);
1337 proto_tree_add_text(opt_tree, tvb,
1338 off + offsetof(struct rr_pco_match, rpm_maxlen),
1339 sizeof(match->rpm_maxlen), "MaxLen: %u", match->rpm_maxlen);
1340 proto_tree_add_text(opt_tree, tvb,
1341 off + offsetof(struct rr_pco_match, rpm_prefix),
1342 sizeof(match->rpm_prefix), "MatchPrefix: %s",
1343 ip6_to_str(&match->rpm_prefix));
1345 off += sizeof(*match);
1347 for (l = match->rpm_len * 8 - sizeof(*match);
1348 l >= sizeof(*use); l -= sizeof(*use), off += sizeof(*use)) {
1349 tvb_memcpy(tvb, (guint8 *)use, off, sizeof *use);
1350 tf = proto_tree_add_text(tree, tvb, off, sizeof(*use),
1351 "Use-Prefix: %s/%u (keep %u)", ip6_to_str(&use->rpu_prefix),
1352 use->rpu_uselen, use->rpu_keeplen);
1353 opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
1354 proto_tree_add_text(opt_tree, tvb,
1355 off + offsetof(struct rr_pco_use, rpu_uselen),
1356 sizeof(use->rpu_uselen), "UseLen: %u", use->rpu_uselen);
1357 proto_tree_add_text(opt_tree, tvb,
1358 off + offsetof(struct rr_pco_use, rpu_keeplen),
1359 sizeof(use->rpu_keeplen), "KeepLen: %u", use->rpu_keeplen);
1360 tf = proto_tree_add_text(opt_tree, tvb,
1361 flagoff = off + offsetof(struct rr_pco_use, rpu_ramask),
1362 sizeof(use->rpu_ramask), "FlagMask: 0x%x", use->rpu_ramask);
1363 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1364 flags = tvb_get_guint8(tvb, flagoff);
1365 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1366 decode_boolean_bitfield(flags,
1367 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
1368 "Onlink", "Not onlink"));
1369 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1370 decode_boolean_bitfield(flags,
1371 ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8,
1372 "Auto", "Not auto"));
1373 tf = proto_tree_add_text(opt_tree, tvb,
1374 flagoff = off + offsetof(struct rr_pco_use, rpu_raflags),
1375 sizeof(use->rpu_raflags), "RAFlags: 0x%x", use->rpu_raflags);
1376 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1377 flags = tvb_get_guint8(tvb, flagoff);
1378 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1379 decode_boolean_bitfield(flags,
1380 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
1381 "Onlink", "Not onlink"));
1382 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1383 decode_boolean_bitfield(flags,
1384 ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8, "Auto", "Not auto"));
1385 if (pntohl(&use->rpu_vltime) == 0xffffffff)
1386 proto_tree_add_text(opt_tree, tvb,
1387 off + offsetof(struct rr_pco_use, rpu_vltime),
1388 sizeof(use->rpu_vltime), "Valid Lifetime: infinity");
1390 proto_tree_add_text(opt_tree, tvb,
1391 off + offsetof(struct rr_pco_use, rpu_vltime),
1392 sizeof(use->rpu_vltime), "Valid Lifetime: %u",
1393 pntohl(&use->rpu_vltime));
1394 if (pntohl(&use->rpu_pltime) == 0xffffffff)
1395 proto_tree_add_text(opt_tree, tvb,
1396 off + offsetof(struct rr_pco_use, rpu_pltime),
1397 sizeof(use->rpu_pltime), "Preferred Lifetime: infinity");
1399 proto_tree_add_text(opt_tree, tvb,
1400 off + offsetof(struct rr_pco_use, rpu_pltime),
1401 sizeof(use->rpu_pltime), "Preferred Lifetime: %u",
1402 pntohl(&use->rpu_pltime));
1403 tf = proto_tree_add_text(opt_tree, tvb,
1404 flagoff = off + offsetof(struct rr_pco_use, rpu_flags),
1405 sizeof(use->rpu_flags), "Flags: 0x%08x",
1406 pntohl(&use->rpu_flags));
1407 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1408 flags = tvb_get_guint8(tvb, flagoff);
1409 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1410 decode_boolean_bitfield(flags,
1411 ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, 32,
1412 "Decrement valid lifetime", "No decrement valid lifetime"));
1413 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1414 decode_boolean_bitfield(flags,
1415 ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, 32,
1416 "Decrement preferred lifetime",
1417 "No decrement preferred lifetime"));
1418 proto_tree_add_text(opt_tree, tvb,
1419 off + offsetof(struct rr_pco_use, rpu_prefix),
1420 sizeof(use->rpu_prefix), "UsePrefix: %s",
1421 ip6_to_str(&use->rpu_prefix));
1428 * See I-D draft-vida-mld-v2-08
1430 static const value_string mldrv2ModesNames[] = {
1433 { 3, "Changed to include" },
1434 { 4, "Changed to exclude" },
1435 { 5, "Allow new sources" },
1436 { 6, "Block old sources" },
1441 dissect_mldrv2( tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree )
1443 proto_tree *sub_tree;
1446 guint8 recordType, auxDataLen;
1447 guint32 sourceNb, recordSize, localOffset;
1448 struct e_in6_addr addr;
1450 for( ; count; count--, offset += recordSize ) {
1451 localOffset = offset;
1452 recordType = tvb_get_guint8( tvb, localOffset );
1454 auxDataLen = tvb_get_guint8( tvb, localOffset );
1456 sourceNb = tvb_get_ntohs( tvb, localOffset );
1458 recordSize = 4 + 16 + (16 * sourceNb) + (auxDataLen * 4);
1460 tvb_get_ipv6(tvb, localOffset, &addr);
1461 tf = proto_tree_add_text( tree, tvb, offset, recordSize,
1463 "%s: %s (%s)", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
1464 get_hostname6(&addr), ip6_to_str(&addr)
1466 "%s: %s", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
1470 sub_tree = proto_item_add_subtree(tf, ett_multicastRR);
1472 proto_tree_add_text( sub_tree, tvb, offset, 1, "Mode: %s",
1473 val_to_str(recordType, mldrv2ModesNames,"Unknown mode") );
1474 proto_tree_add_text( sub_tree, tvb, offset+1, 1, "Aux data len: %u", auxDataLen * 4);
1475 proto_tree_add_text( sub_tree, tvb, localOffset, 16, "Multicast Address: %s", ip6_to_str(&addr) );
1478 for( ; sourceNb; sourceNb--, localOffset += 16 ) {
1479 tvb_get_ipv6(tvb, localOffset, &addr);
1480 proto_tree_add_text( sub_tree, tvb, localOffset, 16,
1482 "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr) );
1484 "Source Address: %s", ip6_to_str(&addr) );
1491 dissect_mldqv2(tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree)
1493 struct e_in6_addr addr;
1495 for ( ; count; count--, offset += 16) {
1496 tvb_get_ipv6(tvb, offset, &addr);
1497 proto_tree_add_text(tree, tvb, offset, 16,
1498 "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr));
1503 dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1505 proto_tree *icmp6_tree, *field_tree;
1506 proto_item *ti, *hidden_item, *tf = NULL;
1507 struct icmp6_hdr icmp6_hdr, *dp;
1508 struct icmp6_nodeinfo *ni = NULL;
1509 const char *codename, *typename;
1510 const char *colcodename, *coltypename;
1512 guint length, reported_length;
1515 guint16 cksum, computed_cksum;
1519 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMPv6");
1520 col_clear(pinfo->cinfo, COL_INFO);
1523 tvb_memcpy(tvb, (guint8 *)&icmp6_hdr, offset, sizeof icmp6_hdr);
1525 typename = coltypename = val_to_str (dp->icmp6_type, icmpv6_type_str, "Unknown");
1526 codename = colcodename = NULL;
1529 switch (dp->icmp6_type) {
1530 case ICMP6_DST_UNREACH:
1531 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_unreach_code_str, "Unknown");
1533 case ICMP6_TIME_EXCEEDED:
1534 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_timeex_code_str, "Unknown");
1536 case ICMP6_PARAM_PROB:
1537 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_paramprob_code_str, "Unknown");
1539 case ND_ROUTER_SOLICIT:
1540 len = sizeof(struct nd_router_solicit);
1542 case ND_ROUTER_ADVERT:
1543 len = sizeof(struct nd_router_advert);
1545 case ND_NEIGHBOR_SOLICIT:
1546 len = sizeof(struct nd_neighbor_solicit);
1548 case ND_NEIGHBOR_ADVERT:
1549 len = sizeof(struct nd_neighbor_advert);
1552 len = sizeof(struct nd_redirect);
1554 case ICMP6_ROUTER_RENUMBERING:
1555 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_router_renum_code_str, "Unknown");
1556 len = sizeof(struct icmp6_router_renum);
1558 case ICMP6_NI_QUERY:
1559 case ICMP6_NI_REPLY:
1560 ni = (struct icmp6_nodeinfo *)dp;
1561 if (ni->ni_type == ICMP6_NI_QUERY) {
1562 switch (ni->ni_code) {
1563 case ICMP6_NI_SUBJ_IPV6:
1564 codename = "Query subject = IPv6 addresses";
1566 case ICMP6_NI_SUBJ_FQDN:
1567 if (tvb_bytes_exist(tvb, offset, sizeof(*ni)))
1568 codename = "Query subject = DNS name";
1570 codename = "Query subject = empty";
1572 case ICMP6_NI_SUBJ_IPV4:
1573 codename = "Query subject = IPv4 addresses";
1576 codename = "Unknown";
1580 switch (ni->ni_code) {
1581 case ICMP6_NI_SUCCESS:
1582 codename = "Successful";
1584 case ICMP6_NI_REFUSED:
1585 codename = "Refused";
1587 case ICMP6_NI_UNKNOWN:
1588 codename = "Unknown query type";
1591 codename = "Unknown";
1595 colcodename = val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype, "Unknown");
1596 len = sizeof(struct icmp6_nodeinfo);
1598 case ICMP6_MIP6_DHAAD_REQUEST:
1599 case ICMP6_MIP6_DHAAD_REPLY:
1600 case ICMP6_MIP6_MPS:
1601 case ICMP6_MIP6_MPA:
1602 case ICMP6_CERT_PATH_SOL:
1603 case ICMP6_CERT_PATH_AD:
1604 case ICMP6_MLDV2_REPORT:
1605 codename = "Should always be zero";
1607 case ICMP6_EXPERIMENTAL_MOBILITY:
1608 switch (dp->icmp6_data8[0]) {
1609 case FMIP6_SUBTYPE_RTSOLPR:
1610 typename = coltypename = "RtSolPr (ICMPv6 Experimental Mobility)";
1611 codename = "Should always be zero";
1613 case FMIP6_SUBTYPE_PRRTADV:
1614 typename = coltypename = "PrRtAdv (ICMPv6 Experimental Mobility)";
1615 codename = val_to_str(dp->icmp6_code, names_fmip6_prrtadv_code, "Unknown");
1617 case FMIP6_SUBTYPE_HI:
1618 typename = coltypename = "HI (ICMPv6 Experimental Mobility)";
1619 codename = val_to_str(dp->icmp6_code, names_fmip6_hi_code, "Unknown");
1621 case FMIP6_SUBTYPE_HACK:
1622 typename = coltypename = "HAck (ICMPv6 Experimental Mobility)";
1623 codename = val_to_str(dp->icmp6_code, names_fmip6_hack_code, "Unknown");
1626 codename = colcodename = "Unknown";
1631 codename = colcodename = "Unknown";
1635 if (check_col(pinfo->cinfo, COL_INFO)) {
1636 char typebuf[256], codebuf[256];
1639 if (pinfo->destport == 0x0dd8 && dp->icmp6_type == ICMP6_ECHO_REQUEST) {
1641 * 5.2.9. Direct IPv6 Connectivity Test
1643 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1644 col_clear(pinfo->cinfo, COL_PROTOCOL);
1645 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Teredo");
1647 col_add_str(pinfo->cinfo, COL_INFO, "Direct IPv6 Connectivity Test");
1649 if (coltypename && strcmp(coltypename, "Unknown") == 0) {
1650 g_snprintf(typebuf, sizeof(typebuf), "Unknown (0x%02x)",
1652 coltypename = typebuf;
1654 if (colcodename && strcmp(colcodename, "Unknown") == 0) {
1655 g_snprintf(codebuf, sizeof(codebuf), "Unknown (0x%02x)",
1657 colcodename = codebuf;
1660 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", coltypename, colcodename);
1662 col_add_str(pinfo->cinfo, COL_INFO, coltypename);
1668 /* !!! specify length */
1669 ti = proto_tree_add_item(tree, proto_icmpv6, tvb, offset, -1, FALSE);
1670 icmp6_tree = proto_item_add_subtree(ti, ett_icmpv6);
1672 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_type, tvb,
1673 offset + offsetof(struct icmp6_hdr, icmp6_type), 1,
1675 "Type: %u (%s)", dp->icmp6_type, typename);
1677 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
1678 offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
1680 "Code: %u (%s)", dp->icmp6_code, codename);
1682 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
1683 offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
1685 "Code: %u", dp->icmp6_code);
1687 cksum = (guint16)g_htons(dp->icmp6_cksum);
1688 length = tvb_length(tvb);
1689 reported_length = tvb_reported_length(tvb);
1690 if (!pinfo->fragmented && length >= reported_length) {
1691 /* The packet isn't part of a fragmented datagram and isn't
1692 truncated, so we can checksum it. */
1694 /* Set up the fields of the pseudo-header. */
1695 cksum_vec[0].ptr = pinfo->src.data;
1696 cksum_vec[0].len = pinfo->src.len;
1697 cksum_vec[1].ptr = pinfo->dst.data;
1698 cksum_vec[1].len = pinfo->dst.len;
1699 cksum_vec[2].ptr = (const guint8 *)&phdr;
1700 phdr[0] = g_htonl(tvb_reported_length(tvb));
1701 phdr[1] = g_htonl(IP_PROTO_ICMPV6);
1702 cksum_vec[2].len = 8;
1703 cksum_vec[3].len = tvb_reported_length(tvb);
1704 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, cksum_vec[3].len);
1705 computed_cksum = in_cksum(cksum_vec, 4);
1706 if (computed_cksum == 0) {
1707 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
1709 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1711 "Checksum: 0x%04x [correct]", cksum);
1713 hidden_item = proto_tree_add_boolean(icmp6_tree, hf_icmpv6_checksum_bad,
1715 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1717 PROTO_ITEM_SET_HIDDEN(hidden_item);
1718 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
1720 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1722 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1723 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1726 proto_tree_add_uint(icmp6_tree, hf_icmpv6_checksum, tvb,
1727 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1731 #define ICMP6_DATA_OFFSET 4
1732 #define ICMP6_SEQ_OFFSET 6
1734 switch (dp->icmp6_type) {
1735 case ICMP6_DST_UNREACH:
1736 case ICMP6_TIME_EXCEEDED:
1737 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1740 case ICMP6_PACKET_TOO_BIG:
1741 proto_tree_add_text(icmp6_tree, tvb,
1742 offset + ICMP6_DATA_OFFSET, 4,
1743 "MTU: %u", pntohl(&dp->icmp6_mtu));
1744 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1747 case ICMP6_PARAM_PROB:
1748 proto_tree_add_text(icmp6_tree, tvb,
1749 offset + ICMP6_DATA_OFFSET, 4,
1750 "Problem pointer: 0x%04x", pntohl(&dp->icmp6_pptr));
1751 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1754 case ICMP6_ECHO_REQUEST:
1755 case ICMP6_ECHO_REPLY:
1756 proto_tree_add_text(icmp6_tree, tvb,
1757 offset + ICMP6_DATA_OFFSET, 2,
1758 "ID: 0x%04x", (guint16)g_ntohs(dp->icmp6_id));
1759 proto_tree_add_text(icmp6_tree, tvb,
1760 offset + ICMP6_SEQ_OFFSET, 2,
1761 "Sequence: 0x%04x", (guint16)g_ntohs(dp->icmp6_seq));
1763 if (pinfo->destport == 0x0dd8 && dp->icmp6_type == ICMP6_ECHO_REQUEST) {
1765 * 5.2.9. Direct IPv6 Connectivity Test
1767 proto_tree_add_text(icmp6_tree, tvb, offset + ICMP6_SEQ_OFFSET + 2, 4,
1768 "Nonce: 0x%08x", tvb_get_ntohl(tvb, offset + ICMP6_SEQ_OFFSET + 2));
1770 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
1771 call_dissector(data_handle,next_tvb, pinfo, icmp6_tree);
1774 case ICMP6_MEMBERSHIP_QUERY:
1775 case ICMP6_MEMBERSHIP_REPORT:
1776 case ICMP6_MEMBERSHIP_REDUCTION:
1777 #define MLDV2_MINLEN 28
1778 #define MLDV1_MINLEN 24
1779 if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) {
1780 if (length >= MLDV2_MINLEN) {
1786 mrc = g_ntohs(dp->icmp6_maxdelay);
1787 flag = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16);
1788 qqi = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16 + 1);
1789 nsrcs = tvb_get_ntohs(tvb, offset + sizeof(*dp) + 16 + 2);
1792 mrc = ((mrc & 0x0fff) | 0x1000) <<
1793 (((mrc & 0x7000) >> 12) + 3);
1794 proto_tree_add_text(icmp6_tree, tvb,
1795 offset + ICMP6_DATA_OFFSET, 2,
1796 "Maximum response delay[ms]: %u", mrc);
1798 proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp),
1799 16, "Multicast Address: %s",
1800 ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb,
1801 offset + sizeof *dp, sizeof (struct e_in6_addr)))));
1803 proto_tree_add_text(icmp6_tree, tvb,
1804 offset + sizeof(*dp) + 16, 1, "S Flag: %s",
1805 flag & 0x08 ? "ON" : "OFF");
1806 proto_tree_add_text(icmp6_tree, tvb,
1807 offset + sizeof(*dp) + 16, 1, "Robustness: %d",
1810 qqi = ((qqi & 0x0f) | 0x10) << (((qqi & 0x70) >> 4) + 3);
1811 proto_tree_add_text(icmp6_tree, tvb,
1812 offset + sizeof(*dp) + 17, 1, "QQI: %d", qqi);
1814 dissect_mldqv2(tvb, offset + sizeof(*dp) + 20, nsrcs,
1817 } else if (length > MLDV1_MINLEN) {
1818 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
1819 call_dissector(data_handle,next_tvb, pinfo, tree);
1822 /* MLDv1 Query -> FALLTHOUGH */
1826 proto_tree_add_text(icmp6_tree, tvb,
1827 offset + ICMP6_DATA_OFFSET, 2,
1828 "Maximum response delay: %u",
1829 (guint16)g_ntohs(dp->icmp6_maxdelay));
1830 proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp), 16,
1831 "Multicast Address: %s",
1832 ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb, offset + sizeof *dp, sizeof (struct e_in6_addr)))));
1834 case ND_ROUTER_SOLICIT:
1835 dissect_icmpv6ndopt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
1837 case ICMP6_MLDV2_REPORT: {
1840 nbRecords = tvb_get_ntohs( tvb, offset+4+2 );
1841 dissect_mldrv2( tvb, offset+4+2+2, nbRecords, icmp6_tree );
1844 #define ND_RA_CURHOPLIMIT_OFFSET 4
1845 #define ND_RA_FLAGS_RESERVED_OFFSET 5
1846 #define ND_RA_ROUTER_LIFETIME_OFFSET 6
1847 case ND_ROUTER_ADVERT:
1849 struct nd_router_advert nd_router_advert, *ra;
1853 ra = &nd_router_advert;
1854 tvb_memcpy(tvb, (guint8 *)ra, offset, sizeof *ra);
1856 /* Current hop limit */
1857 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_cur_hop_limit, tvb,
1858 offset + ND_RA_CURHOPLIMIT_OFFSET,
1859 1, ra->nd_ra_curhoplimit);
1862 flagoff = offset + ND_RA_FLAGS_RESERVED_OFFSET;
1863 ra_flags = tvb_get_guint8(tvb, flagoff);
1864 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", ra_flags);
1865 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1867 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1868 decode_boolean_bitfield(ra_flags,
1869 ND_RA_FLAG_MANAGED, 8, "Managed", "Not managed"));
1870 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1871 decode_boolean_bitfield(ra_flags,
1872 ND_RA_FLAG_OTHER, 8, "Other", "Not other"));
1873 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1874 decode_boolean_bitfield(ra_flags,
1875 ND_RA_FLAG_HOME_AGENT, 8,
1876 "Home Agent", "Not Home Agent"));
1877 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1878 decode_enumerated_bitfield(ra_flags, ND_RA_FLAG_RTPREF_MASK, 8,
1879 names_router_pref, "Router preference: %s"));
1881 /* Router lifetime */
1882 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_router_lifetime, tvb,
1883 offset + ND_RA_ROUTER_LIFETIME_OFFSET,
1884 2, (guint16)g_ntohs(ra->nd_ra_router_lifetime));
1886 /* Reachable time */
1887 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_reachable_time, tvb,
1888 offset + offsetof(struct nd_router_advert, nd_ra_reachable), 4,
1889 pntohl(&ra->nd_ra_reachable));
1892 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_retrans_timer, tvb,
1893 offset + offsetof(struct nd_router_advert, nd_ra_retransmit), 4,
1894 pntohl(&ra->nd_ra_retransmit));
1896 dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
1899 case ND_NEIGHBOR_SOLICIT:
1901 struct nd_neighbor_solicit nd_neighbor_solicit, *ns;
1903 ns = &nd_neighbor_solicit;
1904 tvb_memcpy(tvb, (guint8 *)ns, offset, sizeof *ns);
1905 proto_tree_add_text(icmp6_tree, tvb,
1906 offset + offsetof(struct nd_neighbor_solicit, nd_ns_target), 16,
1909 get_hostname6(&ns->nd_ns_target),
1913 ip6_to_str(&ns->nd_ns_target));
1915 dissect_icmpv6ndopt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
1918 #define ND_NA_FLAGS_RESERVED_OFFSET 4
1919 case ND_NEIGHBOR_ADVERT:
1921 int flagoff, targetoff;
1923 struct e_in6_addr na_target;
1925 flagoff = offset + ND_NA_FLAGS_RESERVED_OFFSET;
1926 na_flags = tvb_get_ntohl(tvb, flagoff);
1928 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 4, "Flags: 0x%08x", na_flags);
1929 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1930 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1931 decode_boolean_bitfield(na_flags,
1932 ND_NA_FLAG_ROUTER, 32, "Router", "Not router"));
1933 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1934 decode_boolean_bitfield(na_flags,
1935 ND_NA_FLAG_SOLICITED, 32, "Solicited", "Not adverted"));
1936 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1937 decode_boolean_bitfield(na_flags,
1938 ND_NA_FLAG_OVERRIDE, 32, "Override", "Not override"));
1940 targetoff = offset + offsetof(struct nd_neighbor_advert, nd_na_target);
1941 tvb_memcpy(tvb, (guint8 *)&na_target, targetoff, sizeof na_target);
1942 proto_tree_add_text(icmp6_tree, tvb, targetoff, 16,
1945 get_hostname6(&na_target),
1949 ip6_to_str(&na_target));
1951 dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
1956 struct nd_redirect nd_redirect, *rd;
1959 tvb_memcpy(tvb, (guint8 *)rd, offset, sizeof *rd);
1960 proto_tree_add_text(icmp6_tree, tvb,
1961 offset + offsetof(struct nd_redirect, nd_rd_target), 16,
1964 get_hostname6(&rd->nd_rd_target),
1968 ip6_to_str(&rd->nd_rd_target));
1970 proto_tree_add_text(icmp6_tree, tvb,
1971 offset + offsetof(struct nd_redirect, nd_rd_dst), 16,
1973 "Destination: %s (%s)",
1974 get_hostname6(&rd->nd_rd_dst),
1978 ip6_to_str(&rd->nd_rd_dst));
1980 dissect_icmpv6ndopt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
1983 case ICMP6_ROUTER_RENUMBERING:
1984 dissect_rrenum(tvb, offset, pinfo, icmp6_tree);
1986 #define NI_QTYPE_OFFSET 4
1987 case ICMP6_NI_QUERY:
1988 case ICMP6_NI_REPLY:
1989 ni = (struct icmp6_nodeinfo *)dp;
1990 proto_tree_add_text(icmp6_tree, tvb,
1991 offset + NI_QTYPE_OFFSET,
1992 sizeof(ni->ni_qtype),
1993 "Query type: 0x%04x (%s)", pntohs(&ni->ni_qtype),
1994 val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
1996 dissect_nodeinfo(tvb, offset, pinfo, icmp6_tree);
1998 case ICMP6_MIP6_DHAAD_REQUEST:
1999 proto_tree_add_text(icmp6_tree, tvb,
2000 offset + 4, 2, "Identifier: %d (0x%02x)",
2001 tvb_get_ntohs(tvb, offset + 4),
2002 tvb_get_ntohs(tvb, offset + 4));
2003 proto_tree_add_text(icmp6_tree, tvb,
2004 offset + 6, 2, "Reserved: %d",
2005 tvb_get_ntohs(tvb, offset + 6));
2007 case ICMP6_MIP6_DHAAD_REPLY:
2008 proto_tree_add_text(icmp6_tree, tvb,
2009 offset + 4, 2, "Identifier: %d (0x%02x)",
2010 tvb_get_ntohs(tvb, offset + 4),
2011 tvb_get_ntohs(tvb, offset + 4));
2012 proto_tree_add_text(icmp6_tree, tvb,
2013 offset + 6, 2, "Reserved: %d",
2014 tvb_get_ntohs(tvb, offset + 6));
2015 /* Show all Home Agent Addresses */
2018 int ha_num = (length - 8)/16;
2020 for (i = 0; i < ha_num; i++) {
2022 proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_haad_ha_addrs,
2023 tvb, offset + 8 + suboffset, 16,
2024 tvb_get_ptr(tvb, offset + 8 + suboffset, 16));
2028 case ICMP6_MIP6_MPS:
2029 proto_tree_add_text(icmp6_tree, tvb,
2030 offset + 4, 2, "Identifier: %d (0x%02x)",
2031 tvb_get_ntohs(tvb, offset + 4),
2032 tvb_get_ntohs(tvb, offset + 4));
2033 proto_tree_add_text(icmp6_tree, tvb,
2034 offset + 6, 2, "Reserved: %d",
2035 tvb_get_ntohs(tvb, offset + 6));
2037 case ICMP6_MIP6_MPA:
2038 proto_tree_add_text(icmp6_tree, tvb,
2039 offset + 4, 2, "Identifier: %d (0x%02x)",
2040 tvb_get_ntohs(tvb, offset + 4),
2041 tvb_get_ntohs(tvb, offset + 4));
2042 proto_tree_add_text(icmp6_tree, tvb,
2043 offset + 6, 1, "%s",
2044 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
2046 "Managed Address Configuration",
2047 "No Managed Address Configuration"));
2048 proto_tree_add_text(icmp6_tree, tvb,
2049 offset + 6, 1, "%s",
2050 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
2052 "Other Stateful Configuration",
2053 "No Other Stateful Configuration"));
2054 proto_tree_add_text(icmp6_tree, tvb,
2055 offset + 7, 1, "Reserved: %d",
2056 tvb_get_guint8(tvb, offset + 7));
2057 /* Show all options */
2058 dissect_icmpv6ndopt(tvb, offset + 8, pinfo, icmp6_tree);
2060 case ICMP6_EXPERIMENTAL_MOBILITY:
2061 switch (dp->icmp6_data8[0]) {
2062 case FMIP6_SUBTYPE_RTSOLPR:
2064 struct fmip6_rtsolpr *rtsolpr;
2065 rtsolpr = (struct fmip6_rtsolpr*) dp;
2066 proto_tree_add_text(icmp6_tree, tvb,
2068 "Subtype: Router Solicitation for Proxy Advertisement");
2069 proto_tree_add_text(icmp6_tree, tvb,
2071 "Identifier: %d", pntohs(&rtsolpr->fmip6_rtsolpr_id));
2072 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2075 case FMIP6_SUBTYPE_PRRTADV:
2077 struct fmip6_prrtadv *prrtadv;
2078 prrtadv = (struct fmip6_prrtadv*) dp;
2079 proto_tree_add_text(icmp6_tree, tvb,
2081 "Subtype: Proxy Router Advertisement");
2082 proto_tree_add_text(icmp6_tree, tvb,
2084 "Identifier: %d", pntohs(&prrtadv->fmip6_prrtadv_id));
2085 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2088 case FMIP6_SUBTYPE_HI:
2090 struct fmip6_hi *hi;
2093 hi = (struct fmip6_hi*) dp;
2094 proto_tree_add_text(icmp6_tree, tvb,
2096 "Subtype: Handover Initiate");
2098 flagoff = offset + 5;
2099 hi_flags = tvb_get_guint8(tvb, flagoff);
2100 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", hi_flags);
2101 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
2102 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
2103 decode_boolean_bitfield(hi_flags,
2104 FMIP_HI_FLAG_ASSIGNED, 8, "Assigned", "Not assigned"));
2105 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
2106 decode_boolean_bitfield(hi_flags,
2107 FMIP_HI_FLAG_BUFFER, 8, "Buffered", "Not buffered"));
2108 proto_tree_add_text(icmp6_tree, tvb,
2110 "Identifier: %d", pntohs(&hi->fmip6_hi_id));
2111 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2114 case FMIP6_SUBTYPE_HACK:
2116 struct fmip6_hack *hack;
2117 hack = (struct fmip6_hack*) dp;
2118 proto_tree_add_text(icmp6_tree, tvb,
2120 "Subtype: Handover Acknowledge");
2121 proto_tree_add_text(icmp6_tree, tvb,
2123 "Identifier: %d", pntohs(&hack->fmip6_hack_id));
2124 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2129 case ICMP6_CERT_PATH_SOL:
2130 /*RFC 3971 6.4.1. Certification Path Solicitation Message Format */
2132 proto_tree_add_text(icmp6_tree, tvb, offset, -1,
2133 "Certification Path Solicitation Message");
2134 /* Identifier A 16-bit unsigned integer field */
2135 proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset,
2138 /* Component A 16-bit unsigned integer field,
2139 * 65,535 if the sender seeks to retrieve all certificates.
2140 * Otherwise, set to the identifier that the receiver wants.
2142 proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2,
2145 dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
2147 case ICMP6_CERT_PATH_AD:
2148 /*RFC 3971 6.4.2. Certification Path Advertisement Message Format */
2150 proto_tree_add_text(icmp6_tree, tvb, offset, -1,"Certification Path Advertisement Message");
2152 /* Identifier A 16-bit unsigned integer field */
2153 proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset, 2, FALSE);
2154 offset = offset + 2;
2155 /* All Components A 16-bit unsigned integer field*/
2156 proto_tree_add_item(icmp6_tree, hf_icmpv6_all_comp, tvb, offset, 2, FALSE);
2157 offset = offset + 2;
2159 /* Component A 16-bit unsigned integer field, used to inform the receiver
2160 * which certificate is being sent.
2162 proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2, FALSE);
2163 offset = offset + 2;
2166 proto_tree_add_text(icmp6_tree, tvb, offset, 2,"Reserved");
2167 offset = offset + 2;
2169 dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
2172 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
2173 call_dissector(data_handle,next_tvb, pinfo, tree);
2180 proto_register_icmpv6(void)
2182 static hf_register_info hf[] = {
2184 { "Type", "icmpv6.type", FT_UINT8, BASE_DEC, NULL, 0x0,
2187 { "Code", "icmpv6.code", FT_UINT8, BASE_DEC, NULL, 0x0,
2189 { &hf_icmpv6_checksum,
2190 { "Checksum", "icmpv6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2192 { &hf_icmpv6_checksum_bad,
2193 { "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2195 { &hf_icmpv6_haad_ha_addrs,
2196 { "Home Agent Addresses", "icmpv6.haad.ha_addrs", FT_IPv6, BASE_NONE, NULL, 0x0,
2198 { &hf_icmpv6_ra_cur_hop_limit,
2199 { "Cur hop limit", "icmpv6.ra.cur_hop_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
2200 "Current hop limit", HFILL }},
2201 { &hf_icmpv6_ra_router_lifetime,
2202 { "Router lifetime", "icmpv6.ra.router_lifetime", FT_UINT16, BASE_DEC, NULL, 0x0,
2203 "Router lifetime (s)", HFILL }},
2204 { &hf_icmpv6_ra_reachable_time,
2205 { "Reachable time", "icmpv6.ra.reachable_time", FT_UINT32, BASE_DEC, NULL, 0x0,
2206 "Reachable time (ms)", HFILL }},
2207 { &hf_icmpv6_ra_retrans_timer,
2208 { "Retrans timer", "icmpv6.ra.retrans_timer", FT_UINT32, BASE_DEC, NULL, 0x0,
2209 "Retrans timer (ms)", HFILL }},
2210 { &hf_icmpv6_option,
2211 { "ICMPv6 Option", "icmpv6.option", FT_NONE, BASE_NONE, NULL, 0x0,
2213 { &hf_icmpv6_option_type,
2214 { "Type", "icmpv6.option.type", FT_UINT8, BASE_DEC, VALS(option_vals), 0x0,
2215 "Options type", HFILL }},
2216 { &hf_icmpv6_option_length,
2217 { "Length", "icmpv6.option.length", FT_UINT8, BASE_DEC, NULL, 0x0,
2218 "Options length (in bytes)", HFILL }},
2219 { &hf_icmpv6_opt_cga_pad_len,
2220 { "Pad Length", "icmpv6.option.cga.pad_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2221 "Pad Length (in bytes)", HFILL }},
2222 { &hf_icmpv6_opt_cga,
2223 { "CGA", "icmpv6.option.cga", FT_BYTES, BASE_NONE, NULL, 0x0,
2225 { &hf_icmpv6_opt_cga_modifier,
2226 { "Modifier", "icmpv6.option.cga.modifier", FT_BYTES, BASE_NONE, NULL, 0x0,
2228 { &hf_icmpv6_opt_cga_subnet_prefix,
2229 { "Subnet Prefix", "icmpv6.option.cga.subnet_prefix", FT_BYTES, BASE_NONE, NULL, 0x0,
2231 { &hf_icmpv6_opt_cga_count,
2232 { "Count", "icmpv6.option.cga.count", FT_BYTES, BASE_NONE, NULL, 0x0,
2234 { &hf_icmpv6_opt_cga_ext_type,
2235 { "Ext Type", "icmpv6.option.cga.ext_type", FT_BYTES, BASE_NONE, NULL, 0x0,
2237 { &hf_icmpv6_opt_cga_ext_length,
2238 { "Ext Length", "icmpv6.option.cga.ext_length", FT_BYTES, BASE_NONE, NULL, 0x0,
2240 { &hf_icmpv6_opt_rsa_key_hash,
2241 { "Key Hash", "icmpv6.option.rsa.key_hash", FT_BYTES, BASE_NONE, NULL, 0x0,
2243 { &hf_icmpv6_opt_name_type,
2244 { "Name Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_name_type_vals), 0x0,
2246 { &hf_icmpv6_opt_name_x501,
2247 { "DER Encoded X.501 Name", "icmpv6.option.name_x501", FT_BYTES, BASE_NONE, NULL, 0x0,
2249 { &hf_icmpv6_opt_name_fqdn,
2250 { "FQDN", "icmpv6.option.name_type.fqdn", FT_STRING, BASE_NONE, NULL, 0x0,
2252 { &hf_icmpv6_opt_cert_type,
2253 { "Cert Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_cert_type_vals), 0x0,
2255 { &hf_icmpv6_identifier,
2256 { "Identifier", "icmpv6.identifier", FT_UINT16, BASE_DEC, NULL, 0x0,
2258 { &hf_icmpv6_all_comp,
2259 { "All Components", "icmpv6.all_comp", FT_UINT16, BASE_DEC, NULL, 0x0,
2262 { "Component", "icmpv6.comp", FT_UINT16, BASE_DEC, NULL, 0x0,
2264 { &hf_icmpv6_x509if_Name,
2265 { "Name", "icmpv6.x509_Name", FT_UINT32, BASE_DEC, VALS(x509if_Name_vals), 0x0,
2267 { &hf_icmpv6_x509af_Certificate,
2268 { "Certificate", "icmpv6.x509_Certificate", FT_NONE, BASE_NONE, NULL, 0x0,
2270 { &hf_icmpv6_recursive_dns_serv,
2271 { "Recursive DNS Servers", "icmpv6.recursive_dns_serv", FT_IPv6, BASE_NONE, NULL, 0x0,
2275 static gint *ett[] = {
2280 &ett_nodeinfo_subject4,
2281 &ett_nodeinfo_subject6,
2282 &ett_nodeinfo_node4,
2283 &ett_nodeinfo_node6,
2284 &ett_nodeinfo_nodebitmap,
2285 &ett_nodeinfo_nodedns,
2287 &ett_icmpv6opt_name,
2291 proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",
2292 "ICMPv6", "icmpv6");
2293 proto_register_field_array(proto_icmpv6, hf, array_length(hf));
2294 proto_register_subtree_array(ett, array_length(ett));
2296 register_dissector("icmpv6", dissect_icmpv6, proto_icmpv6);
2300 proto_reg_handoff_icmpv6(void)
2302 dissector_handle_t icmpv6_handle;
2304 icmpv6_handle = create_dissector_handle(dissect_icmpv6, proto_icmpv6);
2305 dissector_add("ip.proto", IP_PROTO_ICMPV6, icmpv6_handle);
2308 * Get a handle for the IPv6 dissector.
2310 ipv6_handle = find_dissector("ipv6");
2311 data_handle = find_dissector("data");