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.
40 #include <epan/packet.h>
41 #include <epan/in_cksum.h>
42 #include <epan/addr_resolv.h>
43 #include <epan/ipproto.h>
44 #include <epan/asn1.h>
45 #include <epan/strutil.h>
47 #include "packet-ber.h"
48 #include "packet-ipv6.h"
49 #include "packet-dns.h"
50 #include "packet-x509af.h"
51 #include "packet-x509if.h"
55 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
59 * See, under http://www.ietf.org/internet-drafts/
61 * draft-ietf-mobileip-ipv6-15.txt
65 * draft-ietf-ipngwg-icmp-name-lookups-08.txt
69 * draft-ietf-mobileip-hmipv6-05.txt
76 static int proto_icmpv6 = -1;
77 static int hf_icmpv6_type = -1;
78 static int hf_icmpv6_code = -1;
79 static int hf_icmpv6_checksum = -1;
80 static int hf_icmpv6_checksum_bad = -1;
81 static int hf_icmpv6_haad_ha_addrs = -1;
82 static int hf_icmpv6_ra_cur_hop_limit = -1;
83 static int hf_icmpv6_ra_router_lifetime = -1;
84 static int hf_icmpv6_ra_reachable_time = -1;
85 static int hf_icmpv6_ra_retrans_timer = -1;
87 static int hf_icmpv6_option = -1;
88 static int hf_icmpv6_option_type = -1;
89 static int hf_icmpv6_option_length = -1;
90 static int hf_icmpv6_opt_cga_pad_len = -1;
91 static int hf_icmpv6_opt_cga = -1;
92 static int hf_icmpv6_opt_cga_modifier = -1;
93 static int hf_icmpv6_opt_cga_subnet_prefix = -1;
94 static int hf_icmpv6_opt_cga_count = -1;
95 static int hf_icmpv6_opt_cga_ext_type = -1;
96 static int hf_icmpv6_opt_cga_ext_length = -1;
97 static int hf_icmpv6_opt_rsa_key_hash = -1;
98 static int hf_icmpv6_opt_name_type = -1;
99 static int hf_icmpv6_opt_name_x501 = -1;
100 static int hf_icmpv6_opt_name_fqdn = -1;
101 static int hf_icmpv6_opt_cert_type = -1;
102 static int hf_icmpv6_identifier = -1;
103 static int hf_icmpv6_all_comp = -1;
104 static int hf_icmpv6_comp = -1;
105 static int hf_icmpv6_x509if_Name = -1;
106 static int hf_icmpv6_x509af_Certificate = -1;
107 static int hf_icmpv6_recursive_dns_serv = -1;
110 static gint ett_icmpv6 = -1;
111 static gint ett_icmpv6opt = -1;
112 static gint ett_icmpv6flag = -1;
113 static gint ett_nodeinfo_flag = -1;
114 static gint ett_nodeinfo_subject4 = -1;
115 static gint ett_nodeinfo_subject6 = -1;
116 static gint ett_nodeinfo_node4 = -1;
117 static gint ett_nodeinfo_node6 = -1;
118 static gint ett_nodeinfo_nodebitmap = -1;
119 static gint ett_nodeinfo_nodedns = -1;
120 static gint ett_multicastRR = -1;
121 static gint ett_icmpv6opt_name = -1;
122 static gint ett_cga_param_name = -1;
124 static dissector_handle_t ipv6_handle;
125 static dissector_handle_t data_handle;
127 static const value_string icmpv6_type_str[] = {
128 { ICMP6_DST_UNREACH, "Unreachable" },
129 { ICMP6_PACKET_TOO_BIG, "Too big" },
130 { ICMP6_TIME_EXCEEDED, "Time exceeded" },
131 { ICMP6_PARAM_PROB, "Parameter problem" },
132 { ICMP6_ECHO_REQUEST, "Echo request" },
133 { ICMP6_ECHO_REPLY, "Echo reply" },
134 { ICMP6_MEMBERSHIP_QUERY, "Multicast listener query" },
135 { ICMP6_MEMBERSHIP_REPORT, "Multicast listener report" },
136 { ICMP6_MEMBERSHIP_REDUCTION, "Multicast listener done" },
137 { ND_ROUTER_SOLICIT, "Router solicitation" },
138 { ND_ROUTER_ADVERT, "Router advertisement" },
139 { ND_NEIGHBOR_SOLICIT, "Neighbor solicitation" },
140 { ND_NEIGHBOR_ADVERT, "Neighbor advertisement" },
141 { ND_REDIRECT, "Redirect" },
142 { ICMP6_ROUTER_RENUMBERING, "Router renumbering" },
143 { ICMP6_NI_QUERY, "Node information query" },
144 { ICMP6_NI_REPLY, "Node information reply" },
145 { ICMP6_IND_SOLICIT, "Inverse neighbor discovery solicitation" },
146 { ICMP6_IND_ADVERT, "Inverse neighbor discovery advertisement" },
147 { ICMP6_MLDV2_REPORT, "Multicast Listener Report Message v2" },
148 { ICMP6_MIP6_DHAAD_REQUEST, "Dynamic Home Agent Address Discovery Request" },
149 { ICMP6_MIP6_DHAAD_REPLY, "Dynamic Home Agent Address Discovery Reply" },
150 { ICMP6_MIP6_MPS, "Mobile Prefix Solicitation" },
151 { ICMP6_MIP6_MPA, "Mobile Prefix Advertisement" },
152 { ICMP6_CERT_PATH_SOL, "Certification Path Solicitation" },
153 { ICMP6_CERT_PATH_AD, "Certification Path Advertisement" },
154 { ICMP6_EXPERIMENTAL_MOBILITY, "Experimental Mobility" },
155 { ICMP6_MCAST_ROUTER_ADVERT, "Multicast Router Advertisement" },
156 { ICMP6_MCAST_ROUTER_SOLICIT, "Multicast Router Solicitation" },
157 { ICMP6_MCAST_ROUTER_TERM, "Multicast Router Termination" },
158 { ICMP6_FMIPV6_MESSAGES, "FMIPv6 Messages" },
162 static const value_string icmpv6_unreach_code_str[] = {
163 { ICMP6_DST_UNREACH_NOROUTE, "Route unreachable" },
164 { ICMP6_DST_UNREACH_ADMIN, "Administratively prohibited" },
165 { ICMP6_DST_UNREACH_NOTNEIGHBOR, "Not a neighbor" },
166 { ICMP6_DST_UNREACH_ADDR, "Address unreachable" },
167 { ICMP6_DST_UNREACH_NOPORT, "Port unreachable" },
171 static const value_string icmpv6_timeex_code_str[] = {
172 { ICMP6_TIME_EXCEED_TRANSIT, "In-transit" },
173 { ICMP6_TIME_EXCEED_REASSEMBLY, "Reassembly" },
177 static const value_string icmpv6_paramprob_code_str[] = {
178 { ICMP6_PARAMPROB_HEADER, "Header" },
179 { ICMP6_PARAMPROB_NEXTHEADER, "Next header" },
180 { ICMP6_PARAMPROB_OPTION, "Option" },
184 static const value_string icmpv6_router_renum_code_str[] = {
185 { ICMP6_ROUTER_RENUMBERING_COMMAND, "Command" },
186 { ICMP6_ROUTER_RENUMBERING_RESULT, "Result" },
187 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "Sequence number reset" },
191 static const value_string names_nodeinfo_qtype[] = {
192 { NI_QTYPE_NOOP, "NOOP" },
193 { NI_QTYPE_SUPTYPES, "Supported query types" },
194 { NI_QTYPE_DNSNAME, "DNS name" },
195 { NI_QTYPE_NODEADDR, "Node addresses" },
196 { NI_QTYPE_IPV4ADDR, "IPv4 node addresses" },
200 static const value_string names_rrenum_matchcode[] = {
201 { RPM_PCO_ADD, "Add" },
202 { RPM_PCO_CHANGE, "Change" },
203 { RPM_PCO_SETGLOBAL, "Set Global" },
207 static const value_string names_router_pref[] = {
208 { ND_RA_FLAG_RTPREF_HIGH, "High" },
209 { ND_RA_FLAG_RTPREF_MEDIUM, "Medium" },
210 { ND_RA_FLAG_RTPREF_LOW, "Low" },
211 { ND_RA_FLAG_RTPREF_RSV, "Reserved" },
215 static const value_string names_fmip6_prrtadv_code[] = {
216 { FMIP6_PRRTADV_MNTUP, "MN should use AP-ID, AR-info tuple" },
217 { FMIP6_PRRTADV_NI_HOVER, "Network Initiated Handover trigger" },
218 { FMIP6_PRRTADV_NORTINFO, "No new router information" },
219 { FMIP6_PRRTADV_LIMRTINFO, "Limited new router information" },
220 { FMIP6_PRRTADV_UNSOL, "Unsolicited" },
224 static const value_string names_fmip6_hi_code[] = {
225 { FMIP6_HI_PCOA, "FBU sent from previous link" },
226 { FMIP6_HI_NOTPCOA, "FBU sent from new link" },
230 static const value_string names_fmip6_hack_code[] = {
231 { FMIP6_HACK_VALID, "Handover Accepted, NCoA valid" },
232 { FMIP6_HACK_INVALID, "Handover Accepted, NCoA not valid" },
233 { FMIP6_HACK_INUSE, "Handover Accepted, NCoA in use" },
234 { FMIP6_HACK_ASSIGNED, "Handover Accepted, NCoA assigned" },
235 { FMIP6_HACK_NOTASSIGNED, "Handover Accepted, NCoA not assigned" },
236 { FMIP6_HACK_NOTACCEPTED, "Handover Not Accepted, reason unspecified" },
237 { FMIP6_HACK_PROHIBITED, "Administratively prohibited" },
238 { FMIP6_HACK_INSUFFICIENT, "Insufficient resources" },
242 static const value_string names_fmip6_ip_addr_opt_code[] = {
243 { FMIP6_OPT_IP_ADDRESS_OPTCODE_PCOA, "Old Care-of Address" },
244 { FMIP6_OPT_IP_ADDRESS_OPTCODE_NCOA, "New Care-of Address" },
245 { FMIP6_OPT_IP_ADDRESS_OPTCODE_NAR, "NAR's IP address" },
249 static const value_string names_fmip6_lla_opt_code[] = {
250 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_WILDCARD, "Wildcard" },
251 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAP, "Link-layer Address of the New Access Point" },
252 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_MN, "Link-layer Address of the MN" },
253 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAR, "Link-layer Address of the NAR" },
254 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_SRC, "Link-layer Address of the source" },
255 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_CURROUTER, "The AP belongs to the current interface of the router" },
256 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOPREFIX, "No prefix information available" },
257 { FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOSUPPORT, "No fast handovers support available" },
261 static const value_string names_fmip6_naack_opt_status[] = {
262 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID, "New CoA is invalid" },
263 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID_NEW, "New CoA is invalid, use the supplied CoA" },
264 { FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_UNRECOGNIZED, "LLA is unrecognized" },
268 static const value_string fmip6_opt_type_str[] = {
269 { FMIP6_OPT_IP_ADDRESS, "IP Address" },
270 { FMIP6_OPT_NEW_ROUTER_PREFIX_INFO, "New Router Prefix Information" },
271 { FMIP6_OPT_LINK_LAYER_ADDRESS, "Link-layer Address" },
275 /* http://www.iana.org/assignments/icmpv6-parameters */
276 static const value_string option_vals[] = {
277 { ND_OPT_SOURCE_LINKADDR, "Source link-layer address" },
278 { ND_OPT_TARGET_LINKADDR, "Target link-layer address" },
279 { ND_OPT_PREFIX_INFORMATION, "Prefix information" },
280 { ND_OPT_REDIRECTED_HEADER, "Redirected header" },
281 { ND_OPT_MTU, "MTU" },
282 { ND_OPT_ADVINTERVAL, "Advertisement Interval" },
283 { ND_OPT_HOMEAGENT_INFO, "Home Agent Information" },
284 { ND_OPT_CGA, "CGA" }, /* [RFC3971] */
285 { ND_OPT_RSA, "RSA Signature" }, /* [RFC3971] */
286 { ND_OPT_TIMESTAMP, "Timestamp" }, /* [RFC3971] */
287 { ND_OPT_NONCE, "Nonce" }, /* [RFC3971] */
288 { ND_OPT_TRUST_ANCHOR, "Trust Anchor" }, /* [RFC3971] */
289 { 16, "Certificate" }, /* [RFC3971] */
290 { FMIP6_OPT_IP_ADDRESS, "IP Address Option" }, /* [RFC4068] */
291 { FMIP6_OPT_NEW_ROUTER_PREFIX_INFO, "New Router Prefix Information" }, /* [RFC4068] */
292 { FMIP6_OPT_LINK_LAYER_ADDRESS, "Link-layer Address" }, /* [RFC4068] */
293 { FMIP6_OPT_NEIGHBOR_ADV_ACK, "Neighbor Advertisement Acknowledgment" }, /* [RFC4068] */
294 { 21, "CARD Request" }, /* [RFC4065] */
295 { 22, "CARD Reply" }, /* [RFC4065] */
296 { 23, "MAP" }, /* [RFC4140] */
297 { ND_OPT_ROUTE_INFO, "Route Information" }, /* [RFC4191] */
298 { ND_OPT_RECURSIVE_DNS_SERVER, "Recursive DNS Server" }, /* [RFC5006] */
299 { 26, "RA Flags Extension" }, /* [RFC5075] */
300 { 27, "Handover Key Request" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
301 { 28, "Handover Key Reply" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
302 { ND_OPT_MAP, "HMIPv6 MAP option" },
303 /*29-252 Unassigned */
304 { 253, "RFC3692-style Experiment 1" }, /* [RFC4727] */
305 { 254, "RFC3692-style Experiment 2" }, /* [RFC4727] */
309 static const value_string icmpv6_option_name_type_vals[] = {
310 { 1, "DER Encoded X.501 Name" },
315 static const value_string icmpv6_option_cert_type_vals[] = {
316 { 1, "X.509v3 Certificate" },
321 dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
323 gboolean save_in_error_pkt;
326 /* Save the current value of the "we're inside an error packet"
327 flag, and set that flag; subdissectors may treat packets
328 that are the payload of error packets differently from
330 save_in_error_pkt = pinfo->in_error_pkt;
331 pinfo->in_error_pkt = TRUE;
333 next_tvb = tvb_new_subset_remaining(tvb, offset);
335 /* tiny sanity check */
336 if ((tvb_get_guint8(tvb, offset) & 0xf0) == 0x60) {
337 /* The contained packet is an IPv6 datagram; dissect it. */
338 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
340 call_dissector(data_handle,next_tvb, pinfo, tree);
342 /* Restore the "we're inside an error packet" flag. */
343 pinfo->in_error_pkt = save_in_error_pkt;
347 dissect_icmpv6ndopt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
349 proto_tree *icmp6opt_tree, *field_tree, *name_tree, *cga_tree;
350 proto_item *ti, *tf, *name_item, *cga_item;
351 struct nd_opt_hdr nd_opt_hdr, *opt;
353 const char *typename;
354 static const guint8 nd_redirect_reserved[6] = {0, 0, 0, 0, 0, 0};
355 guint8 nd_redirect_res[6];
357 guint8 padd_length = 0;
359 guint8 name_type = 0;
360 guint8 cert_type = 0;
370 if ((int)tvb_reported_length(tvb) <= offset)
371 return; /* No more options left */
374 tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
375 len = opt->nd_opt_len << 3;
377 /* !!! specify length */
378 ti = proto_tree_add_item(tree, hf_icmpv6_option, tvb, offset, len, FALSE);
379 icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
382 proto_tree_add_text(icmp6opt_tree, tvb,
383 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
384 "Invalid option length: %u",
386 return; /* we must not try to decode this */
389 typename = val_to_str(opt->nd_opt_type, option_vals, "Unknown");
391 /* Add option name to option root label */
392 proto_item_append_text(ti, " (%s)", typename);
395 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_option_type, tvb,
396 offset + offsetof(struct nd_opt_hdr, nd_opt_type), 1, FALSE);
398 proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_option_length, tvb,
399 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
400 opt->nd_opt_len << 3);
403 switch (opt->nd_opt_type) {
404 case ND_OPT_SOURCE_LINKADDR:
405 case ND_OPT_TARGET_LINKADDR:
409 p = offset + sizeof(*opt);
410 len_local = (opt->nd_opt_len << 3) - sizeof(*opt);
411 proto_tree_add_text(icmp6opt_tree, tvb,
412 offset + sizeof(*opt), len_local, "Link-layer address: %s",
413 bytestring_to_str(tvb_get_ptr(tvb, p, len_local), len_local, ':'));
416 case ND_OPT_PREFIX_INFORMATION:
418 struct nd_opt_prefix_info nd_opt_prefix_info, *pi;
421 pi = &nd_opt_prefix_info;
422 tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
423 proto_tree_add_text(icmp6opt_tree, tvb,
424 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix_len),
425 1, "Prefix length: %u", pi->nd_opt_pi_prefix_len);
427 flagoff = offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved);
428 tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1, "Flags: 0x%02x",
429 tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved)));
430 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
431 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
432 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
433 ND_OPT_PI_FLAG_ONLINK, 8, "Onlink", "Not onlink"));
434 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
435 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
436 ND_OPT_PI_FLAG_AUTO, 8, "Auto", "Not auto"));
437 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
438 decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
439 ND_OPT_PI_FLAG_ROUTER, 8,
440 "Router Address", "Not router address"));
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_SITEPREF, 8,
444 "Site prefix", "Not site prefix"));
445 if (pntohl(&pi->nd_opt_pi_valid_time) == 0xffffffff)
446 proto_tree_add_text(icmp6opt_tree, tvb,
447 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
448 4, "Valid lifetime: infinity");
450 proto_tree_add_text(icmp6opt_tree, tvb,
451 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
452 4, "Valid lifetime: %u",
453 pntohl(&pi->nd_opt_pi_valid_time));
454 if (pntohl(&pi->nd_opt_pi_preferred_time) == 0xffffffff)
455 proto_tree_add_text(icmp6opt_tree, tvb,
456 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
457 4, "Preferred lifetime: infinity");
459 proto_tree_add_text(icmp6opt_tree, tvb,
460 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
461 4, "Preferred lifetime: %u",
462 pntohl(&pi->nd_opt_pi_preferred_time));
463 proto_tree_add_text(icmp6opt_tree, tvb,
464 offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix),
465 16, "Prefix: %s", ip6_to_str(&pi->nd_opt_pi_prefix));
468 case ND_OPT_REDIRECTED_HEADER:
469 tvb_memcpy(tvb, (guint8 *)&nd_redirect_res, offset + 2, 6);
470 if (memcmp(nd_redirect_res, nd_redirect_reserved, 6) == 0)
471 proto_tree_add_text(icmp6opt_tree, tvb,
472 offset + 2, 6, "Reserved: 0 (correct)");
474 proto_tree_add_text(icmp6opt_tree, tvb,
475 offset +2, 6, "Reserved: MUST be 0 (incorrect!)");
476 proto_tree_add_text(icmp6opt_tree, tvb,
477 offset + 8, (opt->nd_opt_len << 3) - 8, "Redirected packet");
478 dissect_contained_icmpv6(tvb, offset + 8, pinfo, icmp6opt_tree);
481 proto_tree_add_text(icmp6opt_tree, tvb,
482 offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu), 4,
483 "MTU: %u", tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu)));
485 case ND_OPT_ADVINTERVAL:
486 proto_tree_add_text(icmp6opt_tree, tvb,
487 offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint), 4,
488 "Advertisement Interval: %u",
489 tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint)));
491 case ND_OPT_HOMEAGENT_INFO: /* 8 */
493 struct nd_opt_ha_info pibuf, *pi;
496 tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
497 proto_tree_add_text(icmp6opt_tree, tvb,
498 offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_pref),
499 2, "Home Agent Preference: %d",
500 (gint16)pntohs(&pi->nd_opt_ha_info_ha_pref));
501 proto_tree_add_text(icmp6opt_tree, tvb,
502 offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_life),
503 2, "Home Agent Lifetime: %u",
504 pntohs(&pi->nd_opt_ha_info_ha_life));
507 case ND_OPT_CGA: /* 11 */ {
508 guint16 ext_data_len;
509 /* RFC 3971 5.1. CGA Option */
511 opt_offset = offset +2;
512 padd_length = tvb_get_guint8(tvb,opt_offset);
513 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
515 /* Reserved 8 bits */
516 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
518 /* CGA Parameters A variable-length field containing the CGA Parameters data
519 * structure described in Section 4 of
520 * "Cryptographically Generated Addresses (CGA)", RFC3972.
522 par_len = len-4-padd_length;
523 cga_item = proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga, tvb, opt_offset, par_len, FALSE);
524 par_len += opt_offset;
525 cga_tree = proto_item_add_subtree(cga_item, ett_cga_param_name);
526 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_modifier,tvb, opt_offset,16,FALSE);
528 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_subnet_prefix,tvb,opt_offset,8,FALSE);
530 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_count,tvb,opt_offset,1,FALSE);
532 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
533 opt_offset = dissect_x509af_SubjectPublicKeyInfo(FALSE, tvb, opt_offset, &asn1_ctx, cga_tree, -1);
534 /* Process RFC 4581*/
535 while (opt_offset < par_len) {
536 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_type,tvb,opt_offset,2,FALSE);
538 ext_data_len = tvb_get_ntohs(tvb,opt_offset);
539 proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_length,tvb,opt_offset,2,FALSE);
541 proto_tree_add_text(cga_tree,tvb,opt_offset,ext_data_len,"Ext Data");
542 opt_offset += ext_data_len;
546 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
549 case ND_OPT_RSA: /* 12 */
550 /*5.2. RSA Signature Option */
551 opt_offset = offset +2;
552 /* Reserved, A 16-bit field reserved for future use. */
553 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Reserved");
554 opt_offset = opt_offset + 2;
556 * A 128-bit field containing the most significant (leftmost) 128
557 * bits of a SHA-1 [14] hash of the public key used for constructing
560 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_rsa_key_hash, tvb, opt_offset, 16, FALSE);
561 opt_offset = opt_offset + 16;
562 /* Digital Signature */
564 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Digital Signature + Padding");
566 /* TODO: Calculate padding length and exlude from the signature */
568 case ND_OPT_TIMESTAMP: /* 13 */
569 opt_offset = offset +2;
570 /* Reserved A 48-bit field reserved for future use. */
571 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Reserved");
572 opt_offset = opt_offset + 6;
574 * A 64-bit unsigned integer field containing a timestamp. The value
575 * indicates the number of seconds since January 1, 1970, 00:00 UTC,
576 * by using a fixed point format. In this format, the integer number
577 * of seconds is contained in the first 48 bits of the field, and the
578 * remaining 16 bits indicate the number of 1/64K fractions of a
581 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Timestamp(number of seconds since January 1, 1970, 00:00 UTC)");
582 opt_offset = opt_offset + 6;
583 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Timestamp(1/64K fractions of a second)");
586 /* 5.3.2. Nonce Option */
587 opt_offset = offset +2;
588 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,len-2,"Nonce");
591 case ND_OPT_TRUST_ANCHOR:
592 opt_offset = offset +2;
594 name_type = tvb_get_guint8(tvb,opt_offset);
595 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_type, tvb, opt_offset, 1, FALSE);
598 padd_length = tvb_get_guint8(tvb,opt_offset);
599 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
601 par_len = len - 4 - padd_length;
604 /* DER Encoded X.501 Name */
605 name_item =proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_x501, tvb, opt_offset, par_len, FALSE);
606 name_tree = proto_item_add_subtree(name_item, ett_icmpv6opt_name);
607 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
608 dissect_x509if_Name(FALSE, tvb, opt_offset, &asn1_ctx, name_tree, hf_icmpv6_x509if_Name);
612 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_fqdn, tvb, opt_offset, par_len, FALSE);
615 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset, par_len,"Unknown name type");
618 opt_offset = opt_offset + par_len;
620 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
621 opt_offset = opt_offset + padd_length;
623 case ND_OPT_CERTIFICATE:
624 opt_offset = offset +2;
626 cert_type = tvb_get_guint8(tvb,opt_offset);
627 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cert_type, tvb, opt_offset, 1, FALSE);
630 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
635 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
636 opt_offset = dissect_x509af_Certificate(FALSE, tvb, opt_offset, &asn1_ctx, icmp6opt_tree, hf_icmpv6_x509af_Certificate);
637 par_len = len - (opt_offset - offset);
639 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Padding");
642 proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Unknown Certificate + padding");
647 struct nd_opt_map_info mapbuf, *map;
651 tvb_memcpy(tvb, (guint8 *)map, offset, sizeof *map);
652 proto_tree_add_text(icmp6opt_tree, tvb,
653 offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
654 1, "Distance: %u", (map->nd_opt_map_dist_and_pref >> 4));
655 proto_tree_add_text(icmp6opt_tree, tvb,
656 offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
657 1, "Preference: %u", (map->nd_opt_map_dist_and_pref & 0x0F));
658 flagoff = offset + offsetof(struct nd_opt_map_info,
660 tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
662 tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_map_info,
664 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
665 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
666 decode_boolean_bitfield(map->nd_opt_map_flags,
667 ND_OPT_MAP_FLAG_R, 8, "R", "No R"));
668 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
669 decode_boolean_bitfield(map->nd_opt_map_flags,
670 ND_OPT_MAP_FLAG_M, 8, "M", "No M"));
671 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
672 decode_boolean_bitfield(map->nd_opt_map_flags,
673 ND_OPT_MAP_FLAG_I, 8, "I", "No I"));
674 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
675 decode_boolean_bitfield(map->nd_opt_map_flags,
676 ND_OPT_MAP_FLAG_T, 8, "T", "No T"));
677 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
678 decode_boolean_bitfield(map->nd_opt_map_flags,
679 ND_OPT_MAP_FLAG_P, 8, "P", "No P"));
680 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
681 decode_boolean_bitfield(map->nd_opt_map_flags,
682 ND_OPT_MAP_FLAG_V, 8, "V", "No V"));
683 proto_tree_add_text(icmp6opt_tree, tvb,
684 offset + offsetof(struct nd_opt_map_info, nd_opt_map_lifetime),
685 4, "Lifetime: %u", pntohl(&map->nd_opt_map_lifetime));
687 proto_tree_add_text(icmp6opt_tree, tvb,
688 offset + offsetof(struct nd_opt_map_info, nd_opt_map_address), 16,
690 "Address of MAP: %s (%s)",
691 get_hostname6(&map->nd_opt_map_address),
693 "Address of MAP: %s",
695 ip6_to_str(&map->nd_opt_map_address));
698 case ND_OPT_ROUTE_INFO:
700 struct nd_opt_route_info ribuf, *ri;
701 struct e_in6_addr in6;
703 guint32 lifetime_local;
706 tvb_memcpy(tvb, (guint8 *)ri, offset, sizeof *ri);
707 memset(&in6, 0, sizeof(in6));
708 switch (ri->nd_opt_rti_len) {
713 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 8);
716 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 16);
723 proto_tree_add_text(icmp6opt_tree, tvb,
724 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_prefixlen),
725 1, "Prefix length: %u", ri->nd_opt_rti_prefixlen);
726 tf = proto_tree_add_text(icmp6opt_tree, tvb,
727 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
728 1, "Flags: 0x%02x", ri->nd_opt_rti_flags);
729 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
730 proto_tree_add_text(field_tree, tvb,
731 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
733 decode_enumerated_bitfield(ri->nd_opt_rti_flags,
734 ND_RA_FLAG_RTPREF_MASK, 8, names_router_pref,
735 "Router preference: %s"));
736 lifetime_local = pntohl(&ri->nd_opt_rti_lifetime);
737 if (lifetime_local == 0xffffffff)
738 proto_tree_add_text(icmp6opt_tree, tvb,
739 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
740 sizeof(ri->nd_opt_rti_lifetime), "Lifetime: infinity");
742 proto_tree_add_text(icmp6opt_tree, tvb,
743 offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
744 sizeof(ri->nd_opt_rti_lifetime), "Lifetime: %u", lifetime_local);
745 proto_tree_add_text(icmp6opt_tree, tvb,
746 offset + sizeof(*ri), l, "Prefix: %s", ip6_to_str(&in6));
748 proto_tree_add_text(icmp6opt_tree, tvb,
749 offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
750 "Invalid option length: %u", opt->nd_opt_len);
754 case FMIP6_OPT_NEIGHBOR_ADV_ACK:
756 struct fmip6_opt_neighbor_advertisement_ack fmip6_opt_neighbor_advertisement_ack, *opt_naack;
757 struct e_in6_addr in6;
759 opt_naack = &fmip6_opt_neighbor_advertisement_ack;
760 tvb_memcpy(tvb, (guint8 *)opt_naack, offset, sizeof *opt_naack);
762 proto_tree_add_text(icmp6opt_tree, tvb,
763 offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_optcode),
764 1, "Option-Code: %u",
765 opt_naack->fmip6_opt_optcode);
767 proto_tree_add_text(icmp6opt_tree, tvb,
768 offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_status),
770 val_to_str(opt_naack->fmip6_opt_status, names_fmip6_naack_opt_status, "Unknown"));
772 if (opt_naack->fmip6_opt_len == 3){
773 tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*opt_naack), 16);
774 proto_tree_add_text(icmp6opt_tree, tvb,
775 offset + sizeof(*opt_naack),
776 16, "New Care-of Address: %s",
782 case ND_OPT_RECURSIVE_DNS_SERVER:
784 opt_offset = offset + 2;
785 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,2 ,"Reserved");
786 opt_offset = opt_offset + 2;
787 /* A value of all one bits (0xffffffff) represents infinity. A value of
788 * zero means that the RDNSS address MUST no longer be used.
790 lifetime = tvb_get_ntohl(tvb, opt_offset);
791 if (lifetime == 0xffffffff){
792 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: infinity");
795 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: RDNSS address MUST no longer be used");
797 proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: %u", lifetime);
800 opt_offset = opt_offset+4;
801 /* Addresses of IPv6 Recursive DNS Servers */
802 no_of_pars = opt->nd_opt_len - 1;
803 no_of_pars = no_of_pars >> 2;
805 for (i = 0; i <= no_of_pars; i++) {
806 proto_tree_add_item(icmp6opt_tree, hf_icmpv6_recursive_dns_serv, tvb, opt_offset, 16, FALSE);
807 opt_offset = opt_offset+16;
810 } /* switch (opt->nd_opt_type) */
812 offset += (opt->nd_opt_len << 3);
814 /* Set length of option tree */
815 proto_item_set_len(ti, opt->nd_opt_len << 3);
820 dissect_icmpv6fmip6opt(tvbuff_t *tvb, int offset, proto_tree *tree)
822 proto_tree *icmp6opt_tree;
824 struct fmip6_opt_hdr fmip6_opt_hdr, *opt;
826 const char *typename;
832 if ((int)tvb_reported_length(tvb) <= offset)
833 return; /* No more options left */
835 opt = &fmip6_opt_hdr;
836 tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
837 len = opt->fmip6_opt_len << 3;
839 /* !!! specify length */
840 ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
841 icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
844 proto_tree_add_text(icmp6opt_tree, tvb,
845 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
846 "Invalid option length: %u",
848 return; /* we must not try to decode this */
851 typename = val_to_str (opt->fmip6_opt_type, fmip6_opt_type_str, "Unknown");
853 proto_tree_add_text(icmp6opt_tree, tvb,
854 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_type), 1,
855 "Type: %u (%s)", opt->fmip6_opt_type, typename);
856 proto_tree_add_text(icmp6opt_tree, tvb,
857 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
858 "Length: %u bytes (%u)", opt->fmip6_opt_len << 3, opt->fmip6_opt_len);
861 switch (opt->fmip6_opt_type) {
862 case FMIP6_OPT_IP_ADDRESS:
864 struct fmip6_opt_ip_address fmip6_opt_ip_address, *opt_ip;
866 opt_ip = &fmip6_opt_ip_address;
867 tvb_memcpy(tvb, (guint8 *)opt_ip, offset, sizeof *opt_ip);
869 proto_tree_add_text(icmp6opt_tree, tvb,
870 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
871 val_to_str(opt->fmip6_opt_optcode, names_fmip6_ip_addr_opt_code, "Unknown"));
873 proto_tree_add_text(icmp6opt_tree, tvb,
874 offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_prefix_len),
875 1, "Prefix length: %u", opt_ip->fmip6_opt_prefix_len);
877 proto_tree_add_text(icmp6opt_tree, tvb,
878 offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_ip6_address),
879 16, "IPv6 Address: %s",
880 ip6_to_str(&opt_ip->fmip6_opt_ip6_address));
883 case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
885 struct fmip6_opt_new_router_prefix_info fmip6_opt_new_router_prefix_info, *opt_nr;
887 opt_nr = &fmip6_opt_new_router_prefix_info;
888 tvb_memcpy(tvb, (guint8 *)opt_nr, offset, sizeof *opt_nr);
890 proto_tree_add_text(icmp6opt_tree, tvb,
891 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %u",
892 opt->fmip6_opt_optcode);
894 proto_tree_add_text(icmp6opt_tree, tvb,
895 offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix_len),
896 1, "Prefix length: %u", opt_nr->fmip6_opt_prefix_len);
898 proto_tree_add_text(icmp6opt_tree, tvb,
899 offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix),
901 ip6_to_str(&opt_nr->fmip6_opt_prefix));
904 case FMIP6_OPT_LINK_LAYER_ADDRESS:
908 p = offset + sizeof(*opt);
909 proto_tree_add_text(icmp6opt_tree, tvb,
910 offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
911 val_to_str(opt->fmip6_opt_optcode, names_fmip6_lla_opt_code, "Unknown"));
912 len_local = (opt->fmip6_opt_len << 3) - sizeof(*opt);
913 proto_tree_add_text(icmp6opt_tree, tvb,
914 offset + sizeof(*opt), len_local, "Link-layer address: %s",
915 bytestring_to_str(tvb_get_ptr(tvb, p, len_local), len_local, ':'));
918 } /* switch (opt->fmip6_opt_type) */
920 offset += (opt->fmip6_opt_len << 3);
925 * draft-ietf-ipngwg-icmp-name-lookups-07.txt
926 * Note that the packet format was changed several times in the past.
930 bitrange0(guint32 v, int s, emem_strbuf_t *strbuf)
939 /* shift till we have 0x01 */
940 if ((v & 0x01) == 0) {
943 v >>= 4; off += 4; continue;
945 v >>= 3; off += 3; continue;
946 case 0x04: case 0x0c:
947 v >>= 2; off += 2; continue;
949 v >>= 1; off += 1; continue;
953 /* we have 0x01 with us */
954 for (i = 0; i < 32 - off; i++) {
955 if ((v & (0x01 << i)) == 0)
959 ep_strbuf_append_printf(strbuf, ",%d", s + off);
961 ep_strbuf_append_printf(strbuf, ",%d-%d", s + off,
969 bitrange(tvbuff_t *tvb, int offset, int l, int s)
971 emem_strbuf_t *strbuf;
974 strbuf = ep_strbuf_new_label(NULL);
975 for (i = 0; i < l; i++)
976 bitrange0(tvb_get_ntohl(tvb, offset + i * 4), s + i * 4, strbuf);
978 return strbuf->str + 1; /* skip initial "," */
982 #define NI_FLAGS_SIZE 2
983 #define NI_FLAGS_OFFSET 6
984 #define NI_NONCE_SIZE 8
985 #define NI_NONCE_OFFSET 8
987 dissect_nodeinfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
989 proto_tree *field_tree;
991 struct icmp6_nodeinfo icmp6_nodeinfo, *ni;
999 ni = &icmp6_nodeinfo;
1000 tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
1002 flags = pntohs(&ni->ni_flags);
1003 tf = proto_tree_add_text(tree, tvb,
1004 offset + NI_FLAGS_OFFSET,
1005 NI_FLAGS_SIZE, "Flags: 0x%04x", flags);
1006 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_flag);
1007 switch (pntohs(&ni->ni_qtype)) {
1008 case NI_QTYPE_SUPTYPES:
1009 if (ni->ni_type == ICMP6_NI_QUERY) {
1010 proto_tree_add_text(field_tree, tvb,
1011 offset + NI_FLAGS_OFFSET,
1012 NI_FLAGS_SIZE, "%s",
1013 decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
1014 "Compressed reply supported",
1015 "No compressed reply support"));
1017 proto_tree_add_text(field_tree, tvb,
1018 offset + NI_FLAGS_OFFSET,
1019 NI_FLAGS_SIZE, "%s",
1020 decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
1021 "Compressed", "Not compressed"));
1024 case NI_QTYPE_DNSNAME:
1025 if (ni->ni_type == ICMP6_NI_REPLY) {
1026 proto_tree_add_text(field_tree, tvb,
1027 offset + NI_FLAGS_OFFSET,
1028 NI_FLAGS_SIZE, "%s",
1029 decode_boolean_bitfield(flags, NI_FQDN_FLAG_VALIDTTL, sizeof(flags) * 8,
1030 "Valid TTL field", "Meaningless TTL field"));
1033 case NI_QTYPE_NODEADDR:
1034 proto_tree_add_text(field_tree, tvb,
1035 offset + NI_FLAGS_OFFSET,
1036 NI_FLAGS_SIZE, "%s",
1037 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_GLOBAL, sizeof(flags) * 8,
1039 "Not global address"));
1040 proto_tree_add_text(field_tree, tvb,
1041 offset + NI_FLAGS_OFFSET,
1042 NI_FLAGS_SIZE, "%s",
1043 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_SITELOCAL, sizeof(flags) * 8,
1044 "Site-local address",
1045 "Not site-local address"));
1046 proto_tree_add_text(field_tree, tvb,
1047 offset + NI_FLAGS_OFFSET,
1048 NI_FLAGS_SIZE, "%s",
1049 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_LINKLOCAL, sizeof(flags) * 8,
1050 "Link-local address",
1051 "Not link-local address"));
1052 proto_tree_add_text(field_tree, tvb,
1053 offset + NI_FLAGS_OFFSET,
1054 NI_FLAGS_SIZE, "%s",
1055 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_COMPAT, sizeof(flags) * 8,
1056 "IPv4 compatible/mapped address",
1057 "Not IPv4 compatible/mapped address"));
1059 case NI_QTYPE_IPV4ADDR:
1060 proto_tree_add_text(field_tree, tvb,
1061 offset + NI_FLAGS_OFFSET,
1062 NI_FLAGS_SIZE, "%s",
1063 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_ALL, sizeof(flags) * 8,
1064 "All unicast address",
1065 "Unicast addresses on the queried interface"));
1066 proto_tree_add_text(field_tree, tvb,
1067 offset + NI_FLAGS_OFFSET,
1068 NI_FLAGS_SIZE, "%s",
1069 decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_TRUNCATE, sizeof(flags) * 8,
1070 "Truncated", "Not truncated"));
1072 } /* switch (pntohs(&ni->ni_qtype)) */
1075 proto_tree_add_text(tree, tvb,
1076 offset + NI_NONCE_OFFSET,
1077 NI_NONCE_SIZE, "Nonce: 0x%08x%08x",
1078 pntohl(&ni->icmp6_ni_nonce[0]), pntohl(&ni->icmp6_ni_nonce[4]));
1080 /* offset for "the rest of data" */
1084 if (!tvb_bytes_exist(tvb, offset, sizeof(*ni)))
1086 if (ni->ni_type == ICMP6_NI_QUERY) {
1087 switch (ni->ni_code) {
1088 case ICMP6_NI_SUBJ_IPV6:
1089 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1090 n /= sizeof(struct e_in6_addr);
1091 tf = proto_tree_add_text(tree, tvb,
1092 offset + sizeof(*ni), -1, "IPv6 subject addresses");
1093 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject6);
1094 p = offset + sizeof *ni;
1095 for (i = 0; i < n; i++) {
1096 struct e_in6_addr e_in6_addr;
1097 tvb_get_ipv6(tvb, p, &e_in6_addr);
1098 proto_tree_add_text(field_tree, tvb,
1099 p, sizeof(struct e_in6_addr),
1100 "%s", ip6_to_str(&e_in6_addr));
1101 p += sizeof(struct e_in6_addr);
1103 off = tvb_length_remaining(tvb, offset);
1105 case ICMP6_NI_SUBJ_FQDN:
1106 /* XXX Fix data length */
1107 l = get_dns_name(tvb, offset + sizeof(*ni), 0,
1108 offset + sizeof(*ni), &dname);
1109 if (tvb_bytes_exist(tvb, offset + sizeof(*ni) + l, 1) &&
1110 tvb_get_guint8(tvb, offset + sizeof(*ni) + l) == 0) {
1112 proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
1113 "DNS label: %s (truncated)", dname);
1115 proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
1116 "DNS label: %s", dname);
1118 off = tvb_length_remaining(tvb, offset + sizeof(*ni) + l);
1120 case ICMP6_NI_SUBJ_IPV4:
1121 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1122 n /= sizeof(guint32);
1123 tf = proto_tree_add_text(tree, tvb,
1124 offset + sizeof(*ni), -1, "IPv4 subject addresses");
1125 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject4);
1126 p = offset + sizeof *ni;
1127 for (i = 0; i < n; i++) {
1128 ipaddr = tvb_get_ipv4(tvb, p);
1129 proto_tree_add_text(field_tree, tvb,
1130 p, sizeof(guint32), "%s", ip_to_str((guint8 *)&ipaddr));
1131 p += sizeof(guint32);
1133 off = tvb_length_remaining(tvb, offset);
1135 } /* switch (ni->ni_code) */
1137 switch (pntohs(&ni->ni_qtype)) {
1140 case NI_QTYPE_SUPTYPES:
1141 p = offset + sizeof *ni;
1142 tf = proto_tree_add_text(tree, tvb,
1143 offset + sizeof(*ni), -1,
1144 "Supported type bitmap%s",
1145 (flags & 0x0001) ? ", compressed" : "");
1146 field_tree = proto_item_add_subtree(tf,
1147 ett_nodeinfo_nodebitmap);
1149 while (tvb_bytes_exist(tvb, p, sizeof(guint32))) { /* XXXX Check what? */
1150 if ((flags & 0x0001) == 0) {
1151 l = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1152 l /= sizeof(guint32);
1155 l = tvb_get_ntohs(tvb, p);
1156 i = tvb_get_ntohs(tvb, p + sizeof(guint16)); /*skip*/
1158 if (n + l * 32 > (1 << 16))
1160 if (n + (l + i) * 32 > (1 << 16))
1162 if ((flags & 0x0001) == 0) {
1163 proto_tree_add_text(field_tree, tvb, p,
1164 l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
1165 bitrange(tvb, p, l, n));
1168 proto_tree_add_text(field_tree, tvb, p,
1169 4 + l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
1170 bitrange(tvb, p + 4, l, n));
1173 n += l * 32 + i * 32;
1175 off = tvb_length_remaining(tvb, offset);
1177 case NI_QTYPE_DNSNAME:
1178 proto_tree_add_text(tree, tvb, offset + sizeof(*ni),
1179 sizeof(gint32), "TTL: %d", (gint32)tvb_get_ntohl(tvb, offset + sizeof *ni));
1180 tf = proto_tree_add_text(tree, tvb,
1181 offset + sizeof(*ni) + sizeof(guint32), -1,
1183 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
1184 j = offset + sizeof (*ni) + sizeof(guint32);
1185 while (j < tvb_reported_length(tvb)) {
1186 /* XXX Fix data length */
1187 l = get_dns_name(tvb, j, 0,
1188 offset + sizeof (*ni) + sizeof(guint32),
1190 if (tvb_bytes_exist(tvb, j + l, 1) &&
1191 tvb_get_guint8(tvb, j + l) == 0) {
1193 proto_tree_add_text(field_tree, tvb, j, l,
1194 "DNS label: %s (truncated)", dname);
1196 proto_tree_add_text(field_tree, tvb, j, l,
1197 "DNS label: %s", dname);
1201 off = tvb_length_remaining(tvb, offset);
1203 case NI_QTYPE_NODEADDR:
1204 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1205 n /= sizeof(gint32) + sizeof(struct e_in6_addr);
1206 tf = proto_tree_add_text(tree, tvb,
1207 offset + sizeof(*ni), -1, "IPv6 node addresses");
1208 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node6);
1209 p = offset + sizeof (*ni);
1210 for (i = 0; i < n; i++) {
1211 struct e_in6_addr e_in6_addr;
1213 ttl = (gint32)tvb_get_ntohl(tvb, p);
1214 tvb_get_ipv6(tvb, p + sizeof ttl, &e_in6_addr);
1215 proto_tree_add_text(field_tree, tvb,
1216 p, sizeof(struct e_in6_addr) + sizeof(gint32),
1217 "%s (TTL %d)", ip6_to_str(&e_in6_addr), ttl);
1218 p += sizeof(struct e_in6_addr) + sizeof(gint32);
1220 off = tvb_length_remaining(tvb, offset);
1222 case NI_QTYPE_IPV4ADDR:
1223 n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
1224 n /= sizeof(gint32) + sizeof(guint32);
1225 tf = proto_tree_add_text(tree, tvb,
1226 offset + sizeof(*ni), -1, "IPv4 node addresses");
1227 field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node4);
1228 p = offset + sizeof *ni;
1229 for (i = 0; i < n; i++) {
1230 ipaddr = tvb_get_ipv4(tvb, sizeof(gint32) + p);
1231 proto_tree_add_text(field_tree, tvb,
1232 p, sizeof(guint32), "%s (TTL %d)",
1233 ip_to_str((guint8 *)&ipaddr), tvb_get_ntohl(tvb, p));
1234 p += sizeof(gint32) + sizeof(guint32);
1236 off = tvb_length_remaining(tvb, offset);
1238 } /* switch (pntohs(&ni->ni_qtype)) */
1242 /* the rest of data */
1243 call_dissector(data_handle,tvb_new_subset_remaining(tvb, offset + off), pinfo, tree);
1247 #define RR_SEQNUM_SIZE 4
1248 #define RR_SEQNUM_OFFSET 4
1249 #define RR_SEGNUM_SIZE 1
1250 #define RR_SEGNUM_OFFSET 8
1251 #define RR_FLAGS_SIZE 1
1252 #define RR_FLAGS_OFFSET 9
1254 dissect_rrenum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1256 proto_tree *field_tree, *opt_tree;
1258 struct icmp6_router_renum icmp6_router_renum, *rr;
1259 struct rr_pco_match rr_pco_match, *match;
1260 struct rr_pco_use rr_pco_use, *use;
1265 rr = &icmp6_router_renum;
1266 tvb_memcpy(tvb, (guint8 *)rr, offset, sizeof *rr);
1267 proto_tree_add_text(tree, tvb,
1268 offset + RR_SEQNUM_OFFSET, RR_SEQNUM_SIZE,
1269 "Sequence number: 0x%08x", pntohl(&rr->rr_seqnum));
1270 proto_tree_add_text(tree, tvb,
1271 offset + RR_SEGNUM_OFFSET, RR_SEGNUM_SIZE,
1272 "Segment number: 0x%02x", rr->rr_segnum);
1274 flagoff = offset + RR_FLAGS_OFFSET;
1275 flags = tvb_get_guint8(tvb, flagoff);
1276 tf = proto_tree_add_text(tree, tvb, flagoff, RR_FLAGS_SIZE,
1277 "Flags: 0x%02x", flags);
1278 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1279 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1280 decode_boolean_bitfield(flags, 0x80, 8,
1281 "Test command", "Not test command"));
1282 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1283 decode_boolean_bitfield(flags, 0x40, 8,
1284 "Result requested", "Result not requested"));
1285 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1286 decode_boolean_bitfield(flags, 0x20, 8,
1287 "All interfaces", "Not all interfaces"));
1288 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1289 decode_boolean_bitfield(flags, 0x10, 8,
1290 "Site specific", "Not site specific"));
1291 proto_tree_add_text(field_tree, tvb, flagoff, RR_FLAGS_SIZE, "%s",
1292 decode_boolean_bitfield(flags, 0x08, 8,
1293 "Processed previously", "Complete result"));
1295 proto_tree_add_text(tree, tvb,
1296 offset + offsetof(struct icmp6_router_renum, rr_maxdelay), 2,
1297 "Max delay: 0x%04x", pntohs(&rr->rr_maxdelay));
1298 call_dissector(data_handle,tvb_new_subset_remaining(tvb, offset + RR_SIZE), pinfo, tree); /*XXX*/
1300 if (rr->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
1301 off = offset + RR_SIZE;
1302 match = &rr_pco_match;
1303 tvb_memcpy(tvb, (guint8 *)match, off, sizeof *match);
1304 tf = proto_tree_add_text(tree, tvb, off, sizeof(*match),
1305 "Match-Prefix: %s/%u (%u-%u)", ip6_to_str(&match->rpm_prefix),
1306 match->rpm_matchlen, match->rpm_minlen, match->rpm_maxlen);
1307 opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
1308 proto_tree_add_text(opt_tree, tvb,
1309 off + offsetof(struct rr_pco_match, rpm_code),
1310 sizeof(match->rpm_code), "OpCode: %s (%u)",
1311 val_to_str(match->rpm_code, names_rrenum_matchcode, "Unknown"),
1313 proto_tree_add_text(opt_tree, tvb,
1314 off + offsetof(struct rr_pco_match, rpm_len),
1315 sizeof(match->rpm_len), "OpLength: %u (%u octets)",
1316 match->rpm_len, match->rpm_len * 8);
1317 proto_tree_add_text(opt_tree, tvb,
1318 off + offsetof(struct rr_pco_match, rpm_ordinal),
1319 sizeof(match->rpm_ordinal), "Ordinal: %u", match->rpm_ordinal);
1320 proto_tree_add_text(opt_tree, tvb,
1321 off + offsetof(struct rr_pco_match, rpm_matchlen),
1322 sizeof(match->rpm_matchlen), "MatchLen: %u", match->rpm_matchlen);
1323 proto_tree_add_text(opt_tree, tvb,
1324 off + offsetof(struct rr_pco_match, rpm_minlen),
1325 sizeof(match->rpm_minlen), "MinLen: %u", match->rpm_minlen);
1326 proto_tree_add_text(opt_tree, tvb,
1327 off + offsetof(struct rr_pco_match, rpm_maxlen),
1328 sizeof(match->rpm_maxlen), "MaxLen: %u", match->rpm_maxlen);
1329 proto_tree_add_text(opt_tree, tvb,
1330 off + offsetof(struct rr_pco_match, rpm_prefix),
1331 sizeof(match->rpm_prefix), "MatchPrefix: %s",
1332 ip6_to_str(&match->rpm_prefix));
1334 off += sizeof(*match);
1336 for (l = match->rpm_len * 8 - sizeof(*match);
1337 l >= sizeof(*use); l -= sizeof(*use), off += sizeof(*use)) {
1338 tvb_memcpy(tvb, (guint8 *)use, off, sizeof *use);
1339 tf = proto_tree_add_text(tree, tvb, off, sizeof(*use),
1340 "Use-Prefix: %s/%u (keep %u)", ip6_to_str(&use->rpu_prefix),
1341 use->rpu_uselen, use->rpu_keeplen);
1342 opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
1343 proto_tree_add_text(opt_tree, tvb,
1344 off + offsetof(struct rr_pco_use, rpu_uselen),
1345 sizeof(use->rpu_uselen), "UseLen: %u", use->rpu_uselen);
1346 proto_tree_add_text(opt_tree, tvb,
1347 off + offsetof(struct rr_pco_use, rpu_keeplen),
1348 sizeof(use->rpu_keeplen), "KeepLen: %u", use->rpu_keeplen);
1349 tf = proto_tree_add_text(opt_tree, tvb,
1350 flagoff = off + offsetof(struct rr_pco_use, rpu_ramask),
1351 sizeof(use->rpu_ramask), "FlagMask: 0x%x", use->rpu_ramask);
1352 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1353 flags = tvb_get_guint8(tvb, flagoff);
1354 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1355 decode_boolean_bitfield(flags,
1356 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
1357 "Onlink", "Not onlink"));
1358 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1359 decode_boolean_bitfield(flags,
1360 ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8,
1361 "Auto", "Not auto"));
1362 tf = proto_tree_add_text(opt_tree, tvb,
1363 flagoff = off + offsetof(struct rr_pco_use, rpu_raflags),
1364 sizeof(use->rpu_raflags), "RAFlags: 0x%x", use->rpu_raflags);
1365 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1366 flags = tvb_get_guint8(tvb, flagoff);
1367 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1368 decode_boolean_bitfield(flags,
1369 ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
1370 "Onlink", "Not onlink"));
1371 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1372 decode_boolean_bitfield(flags,
1373 ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8, "Auto", "Not auto"));
1374 if (pntohl(&use->rpu_vltime) == 0xffffffff)
1375 proto_tree_add_text(opt_tree, tvb,
1376 off + offsetof(struct rr_pco_use, rpu_vltime),
1377 sizeof(use->rpu_vltime), "Valid Lifetime: infinity");
1379 proto_tree_add_text(opt_tree, tvb,
1380 off + offsetof(struct rr_pco_use, rpu_vltime),
1381 sizeof(use->rpu_vltime), "Valid Lifetime: %u",
1382 pntohl(&use->rpu_vltime));
1383 if (pntohl(&use->rpu_pltime) == 0xffffffff)
1384 proto_tree_add_text(opt_tree, tvb,
1385 off + offsetof(struct rr_pco_use, rpu_pltime),
1386 sizeof(use->rpu_pltime), "Preferred Lifetime: infinity");
1388 proto_tree_add_text(opt_tree, tvb,
1389 off + offsetof(struct rr_pco_use, rpu_pltime),
1390 sizeof(use->rpu_pltime), "Preferred Lifetime: %u",
1391 pntohl(&use->rpu_pltime));
1392 tf = proto_tree_add_text(opt_tree, tvb,
1393 flagoff = off + offsetof(struct rr_pco_use, rpu_flags),
1394 sizeof(use->rpu_flags), "Flags: 0x%08x",
1395 pntohl(&use->rpu_flags));
1396 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1397 flags = tvb_get_guint8(tvb, flagoff);
1398 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1399 decode_boolean_bitfield(flags,
1400 ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, 32,
1401 "Decrement valid lifetime", "No decrement valid lifetime"));
1402 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1403 decode_boolean_bitfield(flags,
1404 ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, 32,
1405 "Decrement preferred lifetime",
1406 "No decrement preferred lifetime"));
1407 proto_tree_add_text(opt_tree, tvb,
1408 off + offsetof(struct rr_pco_use, rpu_prefix),
1409 sizeof(use->rpu_prefix), "UsePrefix: %s",
1410 ip6_to_str(&use->rpu_prefix));
1417 * See I-D draft-vida-mld-v2-08
1419 static const value_string mldrv2ModesNames[] = {
1422 { 3, "Changed to include" },
1423 { 4, "Changed to exclude" },
1424 { 5, "Allow new sources" },
1425 { 6, "Block old sources" },
1430 dissect_mldrv2( tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree )
1432 proto_tree *sub_tree;
1435 guint8 recordType, auxDataLen;
1436 guint32 sourceNb, recordSize, localOffset;
1437 struct e_in6_addr addr;
1439 for( ; count; count--, offset += recordSize ) {
1440 localOffset = offset;
1441 recordType = tvb_get_guint8( tvb, localOffset );
1443 auxDataLen = tvb_get_guint8( tvb, localOffset );
1445 sourceNb = tvb_get_ntohs( tvb, localOffset );
1447 recordSize = 4 + 16 + (16 * sourceNb) + (auxDataLen * 4);
1449 tvb_get_ipv6(tvb, localOffset, &addr);
1450 tf = proto_tree_add_text( tree, tvb, offset, recordSize,
1452 "%s: %s (%s)", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
1453 get_hostname6(&addr), ip6_to_str(&addr)
1455 "%s: %s", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
1459 sub_tree = proto_item_add_subtree(tf, ett_multicastRR);
1461 proto_tree_add_text( sub_tree, tvb, offset, 1, "Mode: %s (%u)",
1462 val_to_str(recordType, mldrv2ModesNames,"Unknown mode"), recordType );
1463 proto_tree_add_text( sub_tree, tvb, offset+1, 1, "Aux data len: %u", auxDataLen * 4);
1464 proto_tree_add_text( sub_tree, tvb, offset+2, 2, "Number of Sources: %u", sourceNb);
1465 proto_tree_add_text( sub_tree, tvb, localOffset, 16, "Multicast Address: %s", ip6_to_str(&addr) );
1468 for( ; sourceNb; sourceNb--, localOffset += 16 ) {
1469 tvb_get_ipv6(tvb, localOffset, &addr);
1470 proto_tree_add_text( sub_tree, tvb, localOffset, 16,
1472 "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr)
1474 "Source Address: %s", ip6_to_str(&addr)
1482 dissect_mldqv2(tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree)
1484 struct e_in6_addr addr;
1486 for ( ; count; count--, offset += 16) {
1487 tvb_get_ipv6(tvb, offset, &addr);
1488 proto_tree_add_text(tree, tvb, offset, 16,
1489 "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr));
1494 dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1496 proto_tree *icmp6_tree, *field_tree;
1497 proto_item *ti, *hidden_item, *tf = NULL;
1498 struct icmp6_hdr icmp6_hdr, *dp;
1499 const char *codename, *typename;
1500 const char *colcodename, *coltypename;
1502 guint length, reported_length;
1505 guint16 cksum, computed_cksum;
1509 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMPv6");
1510 col_clear(pinfo->cinfo, COL_INFO);
1513 tvb_memcpy(tvb, (guint8 *)&icmp6_hdr, offset, sizeof icmp6_hdr);
1515 typename = coltypename = val_to_str (dp->icmp6_type, icmpv6_type_str, "Unknown");
1516 codename = colcodename = NULL;
1519 switch (dp->icmp6_type) {
1520 case ICMP6_DST_UNREACH:
1521 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_unreach_code_str, "Unknown");
1523 case ICMP6_TIME_EXCEEDED:
1524 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_timeex_code_str, "Unknown");
1526 case ICMP6_PARAM_PROB:
1527 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_paramprob_code_str, "Unknown");
1529 case ND_ROUTER_SOLICIT:
1530 len = sizeof(struct nd_router_solicit);
1532 case ND_ROUTER_ADVERT:
1533 len = sizeof(struct nd_router_advert);
1535 case ND_NEIGHBOR_SOLICIT:
1536 len = sizeof(struct nd_neighbor_solicit);
1538 case ND_NEIGHBOR_ADVERT:
1539 len = sizeof(struct nd_neighbor_advert);
1542 len = sizeof(struct nd_redirect);
1544 case ICMP6_ROUTER_RENUMBERING:
1545 codename = colcodename = val_to_str (dp->icmp6_code, icmpv6_router_renum_code_str, "Unknown");
1546 len = sizeof(struct icmp6_router_renum);
1548 case ICMP6_NI_QUERY:
1549 case ICMP6_NI_REPLY:
1551 struct icmp6_nodeinfo icmp6_nodeinfo, *ni;
1553 ni = &icmp6_nodeinfo;
1554 tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
1556 if (ni->ni_type == ICMP6_NI_QUERY) {
1557 switch (ni->ni_code) {
1558 case ICMP6_NI_SUBJ_IPV6:
1559 codename = "Query subject = IPv6 addresses";
1561 case ICMP6_NI_SUBJ_FQDN:
1562 if (tvb_bytes_exist(tvb, offset, sizeof(*ni)))
1563 codename = "Query subject = DNS name";
1565 codename = "Query subject = empty";
1567 case ICMP6_NI_SUBJ_IPV4:
1568 codename = "Query subject = IPv4 addresses";
1571 codename = "Unknown";
1575 switch (ni->ni_code) {
1576 case ICMP6_NI_SUCCESS:
1577 codename = "Successful";
1579 case ICMP6_NI_REFUSED:
1580 codename = "Refused";
1582 case ICMP6_NI_UNKNOWN:
1583 codename = "Unknown query type";
1586 codename = "Unknown";
1590 colcodename = val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype, "Unknown");
1591 len = sizeof(struct icmp6_nodeinfo);
1594 case ICMP6_MIP6_DHAAD_REQUEST:
1595 case ICMP6_MIP6_DHAAD_REPLY:
1596 case ICMP6_MIP6_MPS:
1597 case ICMP6_MIP6_MPA:
1598 case ICMP6_CERT_PATH_SOL:
1599 case ICMP6_CERT_PATH_AD:
1600 case ICMP6_MLDV2_REPORT:
1601 codename = "Should always be zero";
1603 case ICMP6_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";
1609 case FMIP6_SUBTYPE_PRRTADV:
1610 typename = coltypename = "PrRtAdv (ICMPv6 Experimental Mobility)";
1611 codename = val_to_str(dp->icmp6_code, names_fmip6_prrtadv_code, "Unknown");
1613 case FMIP6_SUBTYPE_HI:
1614 typename = coltypename = "HI (ICMPv6 Experimental Mobility)";
1615 codename = val_to_str(dp->icmp6_code, names_fmip6_hi_code, "Unknown");
1617 case FMIP6_SUBTYPE_HACK:
1618 typename = coltypename = "HAck (ICMPv6 Experimental Mobility)";
1619 codename = val_to_str(dp->icmp6_code, names_fmip6_hack_code, "Unknown");
1622 codename = colcodename = "Unknown";
1624 } /* switch (dp->icmp6_data8[0]) */
1627 codename = colcodename = "Unknown";
1629 } /* switch (dp->icmp6_type) */
1631 if (check_col(pinfo->cinfo, COL_INFO)) {
1632 char typebuf[256], codebuf[256];
1635 if (pinfo->destport == 0x0dd8 && dp->icmp6_type == ICMP6_ECHO_REQUEST) {
1637 * 5.2.9. Direct IPv6 Connectivity Test
1639 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1640 col_clear(pinfo->cinfo, COL_PROTOCOL);
1641 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Teredo");
1643 col_set_str(pinfo->cinfo, COL_INFO, "Direct IPv6 Connectivity Test");
1645 if (coltypename && strcmp(coltypename, "Unknown") == 0) {
1646 g_snprintf(typebuf, sizeof(typebuf), "Unknown (0x%02x)",
1648 coltypename = typebuf;
1650 if (colcodename && strcmp(colcodename, "Unknown") == 0) {
1651 g_snprintf(codebuf, sizeof(codebuf), "Unknown (0x%02x)",
1653 colcodename = codebuf;
1656 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", coltypename, colcodename);
1658 col_add_str(pinfo->cinfo, COL_INFO, coltypename);
1664 /* !!! specify length */
1665 ti = proto_tree_add_item(tree, proto_icmpv6, tvb, offset, -1, FALSE);
1666 icmp6_tree = proto_item_add_subtree(ti, ett_icmpv6);
1668 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_type, tvb,
1669 offset + offsetof(struct icmp6_hdr, icmp6_type), 1,
1671 "Type: %u (%s)", dp->icmp6_type, typename);
1673 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
1674 offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
1676 "Code: %u (%s)", dp->icmp6_code, codename);
1678 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
1679 offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
1681 "Code: %u", dp->icmp6_code);
1683 cksum = (guint16)g_htons(dp->icmp6_cksum);
1684 length = tvb_length(tvb);
1685 reported_length = tvb_reported_length(tvb);
1686 if (!pinfo->fragmented && length >= reported_length) {
1687 /* The packet isn't part of a fragmented datagram and isn't
1688 truncated, so we can checksum it. */
1690 /* Set up the fields of the pseudo-header. */
1691 cksum_vec[0].ptr = pinfo->src.data;
1692 cksum_vec[0].len = pinfo->src.len;
1693 cksum_vec[1].ptr = pinfo->dst.data;
1694 cksum_vec[1].len = pinfo->dst.len;
1695 cksum_vec[2].ptr = (const guint8 *)&phdr;
1696 phdr[0] = g_htonl(tvb_reported_length(tvb));
1697 phdr[1] = g_htonl(IP_PROTO_ICMPV6);
1698 cksum_vec[2].len = 8;
1699 cksum_vec[3].len = tvb_reported_length(tvb);
1700 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, cksum_vec[3].len);
1701 computed_cksum = in_cksum(cksum_vec, 4);
1702 if (computed_cksum == 0) {
1703 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
1705 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1707 "Checksum: 0x%04x [correct]", cksum);
1709 hidden_item = proto_tree_add_boolean(icmp6_tree, hf_icmpv6_checksum_bad,
1711 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1713 PROTO_ITEM_SET_HIDDEN(hidden_item);
1714 proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
1716 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1718 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1719 cksum, in_cksum_shouldbe(cksum, computed_cksum));
1722 proto_tree_add_uint(icmp6_tree, hf_icmpv6_checksum, tvb,
1723 offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
1727 #define ICMP6_DATA_OFFSET 4
1728 #define ICMP6_SEQ_OFFSET 6
1730 switch (dp->icmp6_type) {
1731 case ICMP6_DST_UNREACH:
1732 case ICMP6_TIME_EXCEEDED:
1733 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1736 case ICMP6_PACKET_TOO_BIG:
1737 proto_tree_add_text(icmp6_tree, tvb,
1738 offset + ICMP6_DATA_OFFSET, 4,
1739 "MTU: %u", pntohl(&dp->icmp6_mtu));
1740 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1743 case ICMP6_PARAM_PROB:
1744 proto_tree_add_text(icmp6_tree, tvb,
1745 offset + ICMP6_DATA_OFFSET, 4,
1746 "Problem pointer: 0x%04x", pntohl(&dp->icmp6_pptr));
1747 dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
1750 case ICMP6_ECHO_REQUEST:
1751 case ICMP6_ECHO_REPLY:
1752 proto_tree_add_text(icmp6_tree, tvb,
1753 offset + ICMP6_DATA_OFFSET, 2,
1754 "ID: 0x%04x", (guint16)g_ntohs(dp->icmp6_id));
1755 proto_tree_add_text(icmp6_tree, tvb,
1756 offset + ICMP6_SEQ_OFFSET, 2,
1757 "Sequence: 0x%04x", (guint16)g_ntohs(dp->icmp6_seq));
1759 if (pinfo->destport == 0x0dd8 && dp->icmp6_type == ICMP6_ECHO_REQUEST) {
1761 * 5.2.9. Direct IPv6 Connectivity Test
1763 proto_tree_add_text(icmp6_tree, tvb, offset + ICMP6_SEQ_OFFSET + 2, 4,
1764 "Nonce: 0x%08x", tvb_get_ntohl(tvb, offset + ICMP6_SEQ_OFFSET + 2));
1766 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
1767 call_dissector(data_handle,next_tvb, pinfo, icmp6_tree);
1770 case ICMP6_MEMBERSHIP_QUERY:
1771 case ICMP6_MEMBERSHIP_REPORT:
1772 case ICMP6_MEMBERSHIP_REDUCTION:
1773 #define MLDV2_MINLEN 28
1774 #define MLDV1_MINLEN 24
1775 if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) {
1776 if (length >= MLDV2_MINLEN) {
1782 mrc = g_ntohs(dp->icmp6_maxdelay);
1783 flag = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16);
1784 qqi = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16 + 1);
1785 nsrcs = tvb_get_ntohs(tvb, offset + sizeof(*dp) + 16 + 2);
1788 mrc = ((mrc & 0x0fff) | 0x1000) <<
1789 (((mrc & 0x7000) >> 12) + 3);
1790 proto_tree_add_text(icmp6_tree, tvb,
1791 offset + ICMP6_DATA_OFFSET, 2,
1792 "Maximum response delay[ms]: %u", mrc);
1794 proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp),
1795 16, "Multicast Address: %s",
1796 ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb,
1797 offset + sizeof *dp, sizeof (struct e_in6_addr)))));
1799 proto_tree_add_text(icmp6_tree, tvb,
1800 offset + sizeof(*dp) + 16, 1, "S Flag: %s",
1801 flag & 0x08 ? "ON" : "OFF");
1802 proto_tree_add_text(icmp6_tree, tvb,
1803 offset + sizeof(*dp) + 16, 1, "Robustness: %d",
1806 qqi = ((qqi & 0x0f) | 0x10) << (((qqi & 0x70) >> 4) + 3);
1807 proto_tree_add_text(icmp6_tree, tvb,
1808 offset + sizeof(*dp) + 17, 1, "QQI: %d", qqi);
1810 dissect_mldqv2(tvb, offset + sizeof(*dp) + 20, nsrcs,
1813 } else if (length > MLDV1_MINLEN) {
1814 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
1815 call_dissector(data_handle,next_tvb, pinfo, tree);
1818 /* MLDv1 Query -> FALLTHOUGH */
1819 } /* if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) */
1822 proto_tree_add_text(icmp6_tree, tvb,
1823 offset + ICMP6_DATA_OFFSET, 2,
1824 "Maximum response delay: %u",
1825 (guint16)g_ntohs(dp->icmp6_maxdelay));
1826 proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp), 16,
1827 "Multicast Address: %s",
1828 ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb, offset + sizeof *dp, sizeof (struct e_in6_addr)))));
1830 case ND_ROUTER_SOLICIT:
1831 dissect_icmpv6ndopt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
1833 case ICMP6_MLDV2_REPORT:
1837 nbRecords = tvb_get_ntohs( tvb, offset+4+2 );
1838 proto_tree_add_text( icmp6_tree, tvb, offset+4+2, 2, "Number of records: %u", nbRecords );
1839 dissect_mldrv2( tvb, offset+4+2+2, nbRecords, icmp6_tree );
1842 #define ND_RA_CURHOPLIMIT_OFFSET 4
1843 #define ND_RA_FLAGS_RESERVED_OFFSET 5
1844 #define ND_RA_ROUTER_LIFETIME_OFFSET 6
1845 case ND_ROUTER_ADVERT:
1847 struct nd_router_advert nd_router_advert, *ra;
1851 ra = &nd_router_advert;
1852 tvb_memcpy(tvb, (guint8 *)ra, offset, sizeof *ra);
1854 /* Current hop limit */
1855 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_cur_hop_limit, tvb,
1856 offset + ND_RA_CURHOPLIMIT_OFFSET,
1857 1, ra->nd_ra_curhoplimit);
1860 flagoff = offset + ND_RA_FLAGS_RESERVED_OFFSET;
1861 ra_flags = tvb_get_guint8(tvb, flagoff);
1862 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", ra_flags);
1863 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1865 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1866 decode_boolean_bitfield(ra_flags,
1867 ND_RA_FLAG_MANAGED, 8, "Managed", "Not managed"));
1868 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1869 decode_boolean_bitfield(ra_flags,
1870 ND_RA_FLAG_OTHER, 8, "Other", "Not other"));
1871 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1872 decode_boolean_bitfield(ra_flags,
1873 ND_RA_FLAG_HOME_AGENT, 8,
1874 "Home Agent", "Not Home Agent"));
1875 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1876 decode_enumerated_bitfield(ra_flags, ND_RA_FLAG_RTPREF_MASK, 8,
1877 names_router_pref, "Router preference: %s"));
1878 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
1879 decode_boolean_bitfield(ra_flags,
1880 ND_RA_FLAG_ND_PROXY, 8,
1881 "Proxied", "Not Proxied"));
1883 /* Router lifetime */
1884 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_router_lifetime, tvb,
1885 offset + ND_RA_ROUTER_LIFETIME_OFFSET,
1886 2, (guint16)g_ntohs(ra->nd_ra_router_lifetime));
1888 /* Reachable time */
1889 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_reachable_time, tvb,
1890 offset + offsetof(struct nd_router_advert, nd_ra_reachable), 4,
1891 pntohl(&ra->nd_ra_reachable));
1894 proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_retrans_timer, tvb,
1895 offset + offsetof(struct nd_router_advert, nd_ra_retransmit), 4,
1896 pntohl(&ra->nd_ra_retransmit));
1898 dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
1901 case ND_NEIGHBOR_SOLICIT:
1903 struct nd_neighbor_solicit nd_neighbor_solicit, *ns;
1905 ns = &nd_neighbor_solicit;
1906 tvb_memcpy(tvb, (guint8 *)ns, offset, sizeof *ns);
1907 proto_tree_add_text(icmp6_tree, tvb,
1908 offset + offsetof(struct nd_neighbor_solicit, nd_ns_target), 16,
1911 get_hostname6(&ns->nd_ns_target),
1915 ip6_to_str(&ns->nd_ns_target));
1917 dissect_icmpv6ndopt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
1920 #define ND_NA_FLAGS_RESERVED_OFFSET 4
1921 case ND_NEIGHBOR_ADVERT:
1923 int flagoff, targetoff;
1925 struct e_in6_addr na_target;
1927 flagoff = offset + ND_NA_FLAGS_RESERVED_OFFSET;
1928 na_flags = tvb_get_ntohl(tvb, flagoff);
1930 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 4, "Flags: 0x%08x", na_flags);
1931 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
1932 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1933 decode_boolean_bitfield(na_flags,
1934 ND_NA_FLAG_ROUTER, 32, "Router", "Not router"));
1935 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1936 decode_boolean_bitfield(na_flags,
1937 ND_NA_FLAG_SOLICITED, 32, "Solicited", "Not adverted"));
1938 proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
1939 decode_boolean_bitfield(na_flags,
1940 ND_NA_FLAG_OVERRIDE, 32, "Override", "Not override"));
1942 targetoff = offset + offsetof(struct nd_neighbor_advert, nd_na_target);
1943 tvb_memcpy(tvb, (guint8 *)&na_target, targetoff, sizeof na_target);
1944 proto_tree_add_text(icmp6_tree, tvb, targetoff, 16,
1947 get_hostname6(&na_target),
1951 ip6_to_str(&na_target));
1953 dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
1958 struct nd_redirect nd_redirect, *rd;
1961 tvb_memcpy(tvb, (guint8 *)rd, offset, sizeof *rd);
1962 proto_tree_add_text(icmp6_tree, tvb,
1963 offset + offsetof(struct nd_redirect, nd_rd_target), 16,
1966 get_hostname6(&rd->nd_rd_target),
1970 ip6_to_str(&rd->nd_rd_target));
1972 proto_tree_add_text(icmp6_tree, tvb,
1973 offset + offsetof(struct nd_redirect, nd_rd_dst), 16,
1975 "Destination: %s (%s)",
1976 get_hostname6(&rd->nd_rd_dst),
1980 ip6_to_str(&rd->nd_rd_dst));
1982 dissect_icmpv6ndopt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
1985 case ICMP6_ROUTER_RENUMBERING:
1986 dissect_rrenum(tvb, offset, pinfo, icmp6_tree);
1988 #define NI_QTYPE_OFFSET 4
1989 case ICMP6_NI_QUERY:
1990 case ICMP6_NI_REPLY:
1992 struct icmp6_nodeinfo *ni = (struct icmp6_nodeinfo *)dp;
1993 proto_tree_add_text(icmp6_tree, tvb,
1994 offset + NI_QTYPE_OFFSET,
1995 sizeof(ni->ni_qtype),
1996 "Query type: 0x%04x (%s)", pntohs(&ni->ni_qtype),
1997 val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
1999 dissect_nodeinfo(tvb, offset, pinfo, icmp6_tree);
2002 case ICMP6_MIP6_DHAAD_REQUEST:
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,
2008 offset + 6, 2, "Reserved: %d",
2009 tvb_get_ntohs(tvb, offset + 6));
2011 case ICMP6_MIP6_DHAAD_REPLY:
2012 proto_tree_add_text(icmp6_tree, tvb,
2013 offset + 4, 2, "Identifier: %d (0x%02x)",
2014 tvb_get_ntohs(tvb, offset + 4),
2015 tvb_get_ntohs(tvb, offset + 4));
2016 proto_tree_add_text(icmp6_tree, tvb,
2017 offset + 6, 2, "Reserved: %d",
2018 tvb_get_ntohs(tvb, offset + 6));
2019 /* Show all Home Agent Addresses */
2022 int ha_num = (length - 8)/16;
2024 for (i = 0; i < ha_num; i++) {
2026 proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_haad_ha_addrs,
2027 tvb, offset + 8 + suboffset, 16,
2028 tvb_get_ptr(tvb, offset + 8 + suboffset, 16));
2032 case ICMP6_MIP6_MPS:
2033 proto_tree_add_text(icmp6_tree, tvb,
2034 offset + 4, 2, "Identifier: %d (0x%02x)",
2035 tvb_get_ntohs(tvb, offset + 4),
2036 tvb_get_ntohs(tvb, offset + 4));
2037 proto_tree_add_text(icmp6_tree, tvb,
2038 offset + 6, 2, "Reserved: %d",
2039 tvb_get_ntohs(tvb, offset + 6));
2041 case ICMP6_MIP6_MPA:
2042 proto_tree_add_text(icmp6_tree, tvb,
2043 offset + 4, 2, "Identifier: %d (0x%02x)",
2044 tvb_get_ntohs(tvb, offset + 4),
2045 tvb_get_ntohs(tvb, offset + 4));
2046 proto_tree_add_text(icmp6_tree, tvb,
2047 offset + 6, 1, "%s",
2048 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
2050 "Managed Address Configuration",
2051 "No Managed Address Configuration"));
2052 proto_tree_add_text(icmp6_tree, tvb,
2053 offset + 6, 1, "%s",
2054 decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
2056 "Other Stateful Configuration",
2057 "No Other Stateful Configuration"));
2058 proto_tree_add_text(icmp6_tree, tvb,
2059 offset + 7, 1, "Reserved: %d",
2060 tvb_get_guint8(tvb, offset + 7));
2061 /* Show all options */
2062 dissect_icmpv6ndopt(tvb, offset + 8, pinfo, icmp6_tree);
2064 case ICMP6_EXPERIMENTAL_MOBILITY:
2065 switch (dp->icmp6_data8[0]) {
2066 case FMIP6_SUBTYPE_RTSOLPR:
2068 struct fmip6_rtsolpr *rtsolpr;
2069 rtsolpr = (struct fmip6_rtsolpr*) dp;
2070 proto_tree_add_text(icmp6_tree, tvb,
2072 "Subtype: Router Solicitation for Proxy Advertisement");
2073 proto_tree_add_text(icmp6_tree, tvb,
2075 "Identifier: %d", pntohs(&rtsolpr->fmip6_rtsolpr_id));
2076 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2079 case FMIP6_SUBTYPE_PRRTADV:
2081 struct fmip6_prrtadv *prrtadv;
2082 prrtadv = (struct fmip6_prrtadv*) dp;
2083 proto_tree_add_text(icmp6_tree, tvb,
2085 "Subtype: Proxy Router Advertisement");
2086 proto_tree_add_text(icmp6_tree, tvb,
2088 "Identifier: %d", pntohs(&prrtadv->fmip6_prrtadv_id));
2089 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2092 case FMIP6_SUBTYPE_HI:
2094 struct fmip6_hi *hi;
2097 hi = (struct fmip6_hi*) dp;
2098 proto_tree_add_text(icmp6_tree, tvb,
2100 "Subtype: Handover Initiate");
2102 flagoff = offset + 5;
2103 hi_flags = tvb_get_guint8(tvb, flagoff);
2104 tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", hi_flags);
2105 field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
2106 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
2107 decode_boolean_bitfield(hi_flags,
2108 FMIP_HI_FLAG_ASSIGNED, 8, "Assigned", "Not assigned"));
2109 proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
2110 decode_boolean_bitfield(hi_flags,
2111 FMIP_HI_FLAG_BUFFER, 8, "Buffered", "Not buffered"));
2112 proto_tree_add_text(icmp6_tree, tvb,
2114 "Identifier: %d", pntohs(&hi->fmip6_hi_id));
2115 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2118 case FMIP6_SUBTYPE_HACK:
2120 struct fmip6_hack *hack;
2121 hack = (struct fmip6_hack*) dp;
2122 proto_tree_add_text(icmp6_tree, tvb,
2124 "Subtype: Handover Acknowledge");
2125 proto_tree_add_text(icmp6_tree, tvb,
2127 "Identifier: %d", pntohs(&hack->fmip6_hack_id));
2128 dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
2131 } /* switch (dp->icmp6_data8[0]) */
2133 case ICMP6_CERT_PATH_SOL:
2134 /*RFC 3971 6.4.1. Certification Path Solicitation Message Format */
2136 proto_tree_add_text(icmp6_tree, tvb, offset, -1,
2137 "Certification Path Solicitation Message");
2138 /* Identifier A 16-bit unsigned integer field */
2139 proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset,
2142 /* Component A 16-bit unsigned integer field,
2143 * 65,535 if the sender seeks to retrieve all certificates.
2144 * Otherwise, set to the identifier that the receiver wants.
2146 proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2,
2149 dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
2151 case ICMP6_CERT_PATH_AD:
2152 /*RFC 3971 6.4.2. Certification Path Advertisement Message Format */
2154 proto_tree_add_text(icmp6_tree, tvb, offset, -1,"Certification Path Advertisement Message");
2156 /* Identifier A 16-bit unsigned integer field */
2157 proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset, 2, FALSE);
2158 offset = offset + 2;
2159 /* All Components A 16-bit unsigned integer field*/
2160 proto_tree_add_item(icmp6_tree, hf_icmpv6_all_comp, tvb, offset, 2, FALSE);
2161 offset = offset + 2;
2163 /* Component A 16-bit unsigned integer field, used to inform the receiver
2164 * which certificate is being sent.
2166 proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2, FALSE);
2167 offset = offset + 2;
2170 proto_tree_add_text(icmp6_tree, tvb, offset, 2,"Reserved");
2171 offset = offset + 2;
2173 dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
2176 next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
2177 call_dissector(data_handle,next_tvb, pinfo, tree);
2179 } /* switch (dp->icmp6_type) */
2184 proto_register_icmpv6(void)
2186 static hf_register_info hf[] = {
2188 { "Type", "icmpv6.type", FT_UINT8, BASE_DEC, NULL, 0x0,
2191 { "Code", "icmpv6.code", FT_UINT8, BASE_DEC, NULL, 0x0,
2193 { &hf_icmpv6_checksum,
2194 { "Checksum", "icmpv6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
2196 { &hf_icmpv6_checksum_bad,
2197 { "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2199 { &hf_icmpv6_haad_ha_addrs,
2200 { "Home Agent Addresses", "icmpv6.haad.ha_addrs", FT_IPv6, BASE_NONE, NULL, 0x0,
2202 { &hf_icmpv6_ra_cur_hop_limit,
2203 { "Cur hop limit", "icmpv6.ra.cur_hop_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
2204 "Current hop limit", HFILL }},
2205 { &hf_icmpv6_ra_router_lifetime,
2206 { "Router lifetime", "icmpv6.ra.router_lifetime", FT_UINT16, BASE_DEC, NULL, 0x0,
2207 "Router lifetime (s)", HFILL }},
2208 { &hf_icmpv6_ra_reachable_time,
2209 { "Reachable time", "icmpv6.ra.reachable_time", FT_UINT32, BASE_DEC, NULL, 0x0,
2210 "Reachable time (ms)", HFILL }},
2211 { &hf_icmpv6_ra_retrans_timer,
2212 { "Retrans timer", "icmpv6.ra.retrans_timer", FT_UINT32, BASE_DEC, NULL, 0x0,
2213 "Retrans timer (ms)", HFILL }},
2214 { &hf_icmpv6_option,
2215 { "ICMPv6 Option", "icmpv6.option", FT_NONE, BASE_NONE, NULL, 0x0,
2217 { &hf_icmpv6_option_type,
2218 { "Type", "icmpv6.option.type", FT_UINT8, BASE_DEC, VALS(option_vals), 0x0,
2219 "Options type", HFILL }},
2220 { &hf_icmpv6_option_length,
2221 { "Length", "icmpv6.option.length", FT_UINT8, BASE_DEC, NULL, 0x0,
2222 "Options length (in bytes)", HFILL }},
2223 { &hf_icmpv6_opt_cga_pad_len,
2224 { "Pad Length", "icmpv6.option.cga.pad_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2225 "Pad Length (in bytes)", HFILL }},
2226 { &hf_icmpv6_opt_cga,
2227 { "CGA", "icmpv6.option.cga", FT_BYTES, BASE_NONE, NULL, 0x0,
2229 { &hf_icmpv6_opt_cga_modifier,
2230 { "Modifier", "icmpv6.option.cga.modifier", FT_BYTES, BASE_NONE, NULL, 0x0,
2232 { &hf_icmpv6_opt_cga_subnet_prefix,
2233 { "Subnet Prefix", "icmpv6.option.cga.subnet_prefix", FT_BYTES, BASE_NONE, NULL, 0x0,
2235 { &hf_icmpv6_opt_cga_count,
2236 { "Count", "icmpv6.option.cga.count", FT_BYTES, BASE_NONE, NULL, 0x0,
2238 { &hf_icmpv6_opt_cga_ext_type,
2239 { "Ext Type", "icmpv6.option.cga.ext_type", FT_BYTES, BASE_NONE, NULL, 0x0,
2241 { &hf_icmpv6_opt_cga_ext_length,
2242 { "Ext Length", "icmpv6.option.cga.ext_length", FT_BYTES, BASE_NONE, NULL, 0x0,
2244 { &hf_icmpv6_opt_rsa_key_hash,
2245 { "Key Hash", "icmpv6.option.rsa.key_hash", FT_BYTES, BASE_NONE, NULL, 0x0,
2247 { &hf_icmpv6_opt_name_type,
2248 { "Name Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_name_type_vals), 0x0,
2250 { &hf_icmpv6_opt_name_x501,
2251 { "DER Encoded X.501 Name", "icmpv6.option.name_x501", FT_BYTES, BASE_NONE, NULL, 0x0,
2253 { &hf_icmpv6_opt_name_fqdn,
2254 { "FQDN", "icmpv6.option.name_type.fqdn", FT_STRING, BASE_NONE, NULL, 0x0,
2256 { &hf_icmpv6_opt_cert_type,
2257 { "Cert Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_cert_type_vals), 0x0,
2259 { &hf_icmpv6_identifier,
2260 { "Identifier", "icmpv6.identifier", FT_UINT16, BASE_DEC, NULL, 0x0,
2262 { &hf_icmpv6_all_comp,
2263 { "All Components", "icmpv6.all_comp", FT_UINT16, BASE_DEC, NULL, 0x0,
2266 { "Component", "icmpv6.comp", FT_UINT16, BASE_DEC, NULL, 0x0,
2268 { &hf_icmpv6_x509if_Name,
2269 { "Name", "icmpv6.x509_Name", FT_UINT32, BASE_DEC, VALS(x509if_Name_vals), 0x0,
2271 { &hf_icmpv6_x509af_Certificate,
2272 { "Certificate", "icmpv6.x509_Certificate", FT_NONE, BASE_NONE, NULL, 0x0,
2274 { &hf_icmpv6_recursive_dns_serv,
2275 { "Recursive DNS Servers", "icmpv6.recursive_dns_serv", FT_IPv6, BASE_NONE, NULL, 0x0,
2279 static gint *ett[] = {
2284 &ett_nodeinfo_subject4,
2285 &ett_nodeinfo_subject6,
2286 &ett_nodeinfo_node4,
2287 &ett_nodeinfo_node6,
2288 &ett_nodeinfo_nodebitmap,
2289 &ett_nodeinfo_nodedns,
2291 &ett_icmpv6opt_name,
2295 proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",
2296 "ICMPv6", "icmpv6");
2297 proto_register_field_array(proto_icmpv6, hf, array_length(hf));
2298 proto_register_subtree_array(ett, array_length(ett));
2300 register_dissector("icmpv6", dissect_icmpv6, proto_icmpv6);
2304 proto_reg_handoff_icmpv6(void)
2306 dissector_handle_t icmpv6_handle;
2308 icmpv6_handle = create_dissector_handle(dissect_icmpv6, proto_icmpv6);
2309 dissector_add("ip.proto", IP_PROTO_ICMPV6, icmpv6_handle);
2312 * Get a handle for the IPv6 dissector.
2314 ipv6_handle = find_dissector("ipv6");
2315 data_handle = find_dissector("data");
2319 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2324 * indent-tabs-mode: nil
2327 * vi: set shiftwidth=4 tabstop=8 expandtab
2328 * :indentSize=4:tabSize=8:noTabs=true: