1999-03-29 02:21:34 +00:00
|
|
|
/* packet-icmpv6.c
|
2000-10-12 14:58:02 +00:00
|
|
|
* Routines for ICMPv6 packet disassembly
|
1999-03-29 02:21:34 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1999-03-29 02:21:34 +00:00
|
|
|
*
|
2006-05-21 04:49:01 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
1999-03-29 02:21:34 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2001-01-23 02:49:55 +00:00
|
|
|
* MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
|
2006-11-02 16:47:13 +00:00
|
|
|
* Copyright 2006, Nicolas DICHTEL - 6WIND - <nicolas.dichtel@6wind.com>
|
2000-10-12 14:58:02 +00:00
|
|
|
*
|
2001-09-04 21:04:52 +00:00
|
|
|
* HMIPv6 support added by Martti Kuparinen <martti.kuparinen@iki.fi>
|
|
|
|
*
|
2005-10-25 06:00:53 +00:00
|
|
|
* FMIPv6 support added by Martin Andre <andre@clarinet.u-strasbg.fr>
|
|
|
|
*
|
1999-03-29 02:21:34 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2000-10-12 14:58:02 +00:00
|
|
|
*
|
1999-03-29 02:21:34 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2000-10-12 14:58:02 +00:00
|
|
|
*
|
1999-03-29 02:21:34 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1999-03-29 02:21:34 +00:00
|
|
|
#include <unistd.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
|
|
|
|
1999-03-29 02:21:34 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2000-08-11 13:37:21 +00:00
|
|
|
#include <glib.h>
|
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2004-09-28 00:06:32 +00:00
|
|
|
#include <epan/in_cksum.h>
|
2004-08-06 19:57:49 +00:00
|
|
|
#include <epan/addr_resolv.h>
|
2004-09-29 00:52:45 +00:00
|
|
|
#include <epan/ipproto.h>
|
2008-02-25 22:17:24 +00:00
|
|
|
#include <epan/asn1.h>
|
2008-03-01 17:23:39 +00:00
|
|
|
#include <epan/strutil.h>
|
2008-02-25 22:17:24 +00:00
|
|
|
|
|
|
|
#include "packet-ber.h"
|
|
|
|
#include "packet-ipv6.h"
|
|
|
|
#include "packet-dns.h"
|
|
|
|
#include "packet-x509af.h"
|
|
|
|
#include "packet-x509if.h"
|
|
|
|
|
1999-03-29 02:21:34 +00:00
|
|
|
|
|
|
|
#ifndef offsetof
|
|
|
|
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
|
|
|
#endif
|
|
|
|
|
2002-01-11 09:19:54 +00:00
|
|
|
/*
|
|
|
|
* See, under http://www.ietf.org/internet-drafts/
|
|
|
|
*
|
|
|
|
* draft-ietf-mobileip-ipv6-15.txt
|
|
|
|
*
|
|
|
|
* and
|
|
|
|
*
|
|
|
|
* draft-ietf-ipngwg-icmp-name-lookups-08.txt
|
|
|
|
*
|
|
|
|
* and
|
|
|
|
*
|
|
|
|
* draft-ietf-mobileip-hmipv6-05.txt
|
2007-07-30 17:21:40 +00:00
|
|
|
*
|
2005-10-25 06:00:53 +00:00
|
|
|
* and
|
2007-07-30 17:21:40 +00:00
|
|
|
*
|
2005-10-25 06:00:53 +00:00
|
|
|
* rfc4068.txt
|
2002-01-11 09:19:54 +00:00
|
|
|
*/
|
|
|
|
|
1999-07-29 05:47:07 +00:00
|
|
|
static int proto_icmpv6 = -1;
|
1999-10-10 16:09:33 +00:00
|
|
|
static int hf_icmpv6_type = -1;
|
|
|
|
static int hf_icmpv6_code = -1;
|
|
|
|
static int hf_icmpv6_checksum = -1;
|
2001-02-28 19:33:49 +00:00
|
|
|
static int hf_icmpv6_checksum_bad = -1;
|
2004-01-29 03:59:04 +00:00
|
|
|
static int hf_icmpv6_haad_ha_addrs = -1;
|
2006-10-30 15:36:40 +00:00
|
|
|
static int hf_icmpv6_ra_cur_hop_limit = -1;
|
|
|
|
static int hf_icmpv6_ra_router_lifetime = -1;
|
|
|
|
static int hf_icmpv6_ra_reachable_time = -1;
|
|
|
|
static int hf_icmpv6_ra_retrans_timer = -1;
|
|
|
|
|
|
|
|
static int hf_icmpv6_option = -1;
|
|
|
|
static int hf_icmpv6_option_type = -1;
|
|
|
|
static int hf_icmpv6_option_length = -1;
|
2008-02-24 17:14:47 +00:00
|
|
|
static int hf_icmpv6_opt_cga_pad_len = -1;
|
|
|
|
static int hf_icmpv6_opt_cga = -1;
|
2008-11-05 10:59:20 +00:00
|
|
|
static int hf_icmpv6_opt_cga_modifier = -1;
|
|
|
|
static int hf_icmpv6_opt_cga_subnet_prefix = -1;
|
|
|
|
static int hf_icmpv6_opt_cga_count = -1;
|
|
|
|
static int hf_icmpv6_opt_cga_ext_type = -1;
|
|
|
|
static int hf_icmpv6_opt_cga_ext_length = -1;
|
2008-02-24 17:14:47 +00:00
|
|
|
static int hf_icmpv6_opt_rsa_key_hash = -1;
|
2008-02-24 21:04:42 +00:00
|
|
|
static int hf_icmpv6_opt_name_type = -1;
|
|
|
|
static int hf_icmpv6_opt_name_x501 = -1;
|
|
|
|
static int hf_icmpv6_opt_name_fqdn = -1;
|
|
|
|
static int hf_icmpv6_opt_cert_type = -1;
|
|
|
|
static int hf_icmpv6_identifier = -1;
|
|
|
|
static int hf_icmpv6_all_comp = -1;
|
|
|
|
static int hf_icmpv6_comp = -1;
|
2008-02-25 22:17:24 +00:00
|
|
|
static int hf_icmpv6_x509if_Name = -1;
|
|
|
|
static int hf_icmpv6_x509af_Certificate = -1;
|
2008-03-17 21:21:48 +00:00
|
|
|
static int hf_icmpv6_recursive_dns_serv = -1;
|
1999-07-29 05:47:07 +00:00
|
|
|
|
2008-11-05 10:59:20 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint ett_icmpv6 = -1;
|
|
|
|
static gint ett_icmpv6opt = -1;
|
|
|
|
static gint ett_icmpv6flag = -1;
|
2000-08-18 12:05:27 +00:00
|
|
|
static gint ett_nodeinfo_flag = -1;
|
|
|
|
static gint ett_nodeinfo_subject4 = -1;
|
|
|
|
static gint ett_nodeinfo_subject6 = -1;
|
|
|
|
static gint ett_nodeinfo_node4 = -1;
|
|
|
|
static gint ett_nodeinfo_node6 = -1;
|
2000-08-22 08:30:00 +00:00
|
|
|
static gint ett_nodeinfo_nodebitmap = -1;
|
|
|
|
static gint ett_nodeinfo_nodedns = -1;
|
2003-12-19 23:20:53 +00:00
|
|
|
static gint ett_multicastRR = -1;
|
2008-02-25 22:17:24 +00:00
|
|
|
static gint ett_icmpv6opt_name = -1;
|
2008-11-05 10:59:20 +00:00
|
|
|
static gint ett_cga_param_name = -1;
|
2000-08-18 12:05:27 +00:00
|
|
|
|
2001-04-23 03:56:57 +00:00
|
|
|
static dissector_handle_t ipv6_handle;
|
2001-11-25 22:51:14 +00:00
|
|
|
static dissector_handle_t data_handle;
|
2001-04-23 03:56:57 +00:00
|
|
|
|
2000-08-18 12:05:27 +00:00
|
|
|
static const value_string names_nodeinfo_qtype[] = {
|
|
|
|
{ NI_QTYPE_NOOP, "NOOP" },
|
|
|
|
{ NI_QTYPE_SUPTYPES, "Supported query types" },
|
|
|
|
{ NI_QTYPE_DNSNAME, "DNS name" },
|
|
|
|
{ NI_QTYPE_NODEADDR, "Node addresses" },
|
|
|
|
{ NI_QTYPE_IPV4ADDR, "IPv4 node addresses" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
1999-11-16 11:44:20 +00:00
|
|
|
|
2000-11-09 16:39:59 +00:00
|
|
|
static const value_string names_rrenum_matchcode[] = {
|
|
|
|
{ RPM_PCO_ADD, "Add" },
|
|
|
|
{ RPM_PCO_CHANGE, "Change" },
|
|
|
|
{ RPM_PCO_SETGLOBAL, "Set Global" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2001-06-01 23:53:49 +00:00
|
|
|
static const value_string names_router_pref[] = {
|
2002-08-28 21:04:11 +00:00
|
|
|
{ ND_RA_FLAG_RTPREF_HIGH, "High" },
|
|
|
|
{ ND_RA_FLAG_RTPREF_MEDIUM, "Medium" },
|
|
|
|
{ ND_RA_FLAG_RTPREF_LOW, "Low" },
|
|
|
|
{ ND_RA_FLAG_RTPREF_RSV, "Reserved" },
|
2005-08-28 02:24:01 +00:00
|
|
|
{ 0, NULL}
|
2001-06-01 23:53:49 +00:00
|
|
|
};
|
|
|
|
|
2005-10-25 06:00:53 +00:00
|
|
|
static const value_string names_fmip6_prrtadv_code[] = {
|
|
|
|
{ FMIP6_PRRTADV_MNTUP, "MN should use AP-ID, AR-info tuple" },
|
|
|
|
{ FMIP6_PRRTADV_NI_HOVER, "Network Initiated Handover trigger" },
|
|
|
|
{ FMIP6_PRRTADV_NORTINFO, "No new router information" },
|
|
|
|
{ FMIP6_PRRTADV_LIMRTINFO, "Limited new router information" },
|
|
|
|
{ FMIP6_PRRTADV_UNSOL, "Unsolicited" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string names_fmip6_hi_code[] = {
|
|
|
|
{ FMIP6_HI_PCOA, "FBU sent from previous link" },
|
|
|
|
{ FMIP6_HI_NOTPCOA, "FBU sent from new link" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string names_fmip6_hack_code[] = {
|
|
|
|
{ FMIP6_HACK_VALID, "Handover Accepted, NCoA valid" },
|
|
|
|
{ FMIP6_HACK_INVALID, "Handover Accepted, NCoA not valid" },
|
|
|
|
{ FMIP6_HACK_INUSE, "Handover Accepted, NCoA in use" },
|
|
|
|
{ FMIP6_HACK_ASSIGNED, "Handover Accepted, NCoA assigned" },
|
|
|
|
{ FMIP6_HACK_NOTASSIGNED, "Handover Accepted, NCoA not assigned" },
|
|
|
|
{ FMIP6_HACK_NOTACCEPTED, "Handover Not Accepted, reason unspecified" },
|
|
|
|
{ FMIP6_HACK_PROHIBITED, "Administratively prohibited" },
|
|
|
|
{ FMIP6_HACK_INSUFFICIENT, "Insufficient resources" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string names_fmip6_ip_addr_opt_code[] = {
|
|
|
|
{ FMIP6_OPT_IP_ADDRESS_OPTCODE_PCOA, "Old Care-of Address" },
|
|
|
|
{ FMIP6_OPT_IP_ADDRESS_OPTCODE_NCOA, "New Care-of Address" },
|
|
|
|
{ FMIP6_OPT_IP_ADDRESS_OPTCODE_NAR, "NAR's IP address" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string names_fmip6_lla_opt_code[] = {
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_WILDCARD, "Wildcard" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAP, "Link-layer Address of the New Access Point" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_MN, "Link-layer Address of the MN" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAR, "Link-layer Address of the NAR" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_SRC, "Link-layer Address of the source" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_CURROUTER, "The AP belongs to the current interface of the router" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOPREFIX, "No prefix information available" },
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOSUPPORT, "No fast handovers support available" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string names_fmip6_naack_opt_status[] = {
|
|
|
|
{ FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID, "New CoA is invalid" },
|
|
|
|
{ FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID_NEW, "New CoA is invalid, use the supplied CoA" },
|
|
|
|
{ FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_UNRECOGNIZED, "LLA is unrecognized" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2008-02-23 19:17:23 +00:00
|
|
|
/* http://www.iana.org/assignments/icmpv6-parameters */
|
2006-10-30 15:36:40 +00:00
|
|
|
static const value_string option_vals[] = {
|
2008-02-23 19:17:23 +00:00
|
|
|
{ ND_OPT_SOURCE_LINKADDR, "Source link-layer address" },
|
|
|
|
{ ND_OPT_TARGET_LINKADDR, "Target link-layer address" },
|
|
|
|
{ ND_OPT_PREFIX_INFORMATION, "Prefix information" },
|
|
|
|
{ ND_OPT_REDIRECTED_HEADER, "Redirected header" },
|
|
|
|
{ ND_OPT_MTU, "MTU" },
|
|
|
|
{ ND_OPT_ADVINTERVAL, "Advertisement Interval" },
|
|
|
|
{ ND_OPT_HOMEAGENT_INFO, "Home Agent Information" },
|
|
|
|
{ ND_OPT_CGA, "CGA" }, /* [RFC3971] */
|
|
|
|
{ ND_OPT_RSA, "RSA Signature" }, /* [RFC3971] */
|
2008-03-01 16:23:14 +00:00
|
|
|
{ ND_OPT_TIMESTAMP, "Timestamp" }, /* [RFC3971] */
|
2008-02-24 21:04:42 +00:00
|
|
|
{ ND_OPT_NONCE, "Nonce" }, /* [RFC3971] */
|
|
|
|
{ ND_OPT_TRUST_ANCHOR, "Trust Anchor" }, /* [RFC3971] */
|
2008-02-23 19:17:23 +00:00
|
|
|
{ 16, "Certificate" }, /* [RFC3971] */
|
2008-03-01 16:23:14 +00:00
|
|
|
{ FMIP6_OPT_IP_ADDRESS, "IP Address Option" }, /* [RFC4068] */
|
2008-02-23 19:17:23 +00:00
|
|
|
{ FMIP6_OPT_NEW_ROUTER_PREFIX_INFO, "New Router Prefix Information" }, /* [RFC4068] */
|
|
|
|
{ FMIP6_OPT_LINK_LAYER_ADDRESS, "Link-layer Address" }, /* [RFC4068] */
|
2008-03-01 16:23:14 +00:00
|
|
|
{ FMIP6_OPT_NEIGHBOR_ADV_ACK, "Neighbor Advertisement Acknowledgment" }, /* [RFC4068] */
|
2008-02-23 19:17:23 +00:00
|
|
|
{ 21, "CARD Request" }, /* [RFC4065] */
|
|
|
|
{ 22, "CARD Reply" }, /* [RFC4065] */
|
|
|
|
{ 23, "MAP" }, /* [RFC4140] */
|
2008-04-23 20:42:02 +00:00
|
|
|
{ ND_OPT_ROUTE_INFO, "Route Information" }, /* [RFC4191] */
|
2008-03-17 21:21:48 +00:00
|
|
|
{ ND_OPT_RECURSIVE_DNS_SERVER, "Recursive DNS Server" }, /* [RFC5006] */
|
2008-02-23 19:17:23 +00:00
|
|
|
{ 26, "RA Flags Extension" }, /* [RFC5075] */
|
|
|
|
{ 27, "Handover Key Request" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
|
|
|
|
{ 28, "Handover Key Reply" }, /* [RFC-ietf-mipshop-handover-key-03.txt] */
|
|
|
|
{ ND_OPT_MAP, "HMIPv6 MAP option" },
|
|
|
|
/*29-252 Unassigned */
|
|
|
|
{ 253, "RFC3692-style Experiment 1" }, /* [RFC4727] */
|
|
|
|
{ 254, "RFC3692-style Experiment 2" }, /* [RFC4727] */
|
2006-10-30 15:36:40 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2008-02-24 21:04:42 +00:00
|
|
|
static const value_string icmpv6_option_name_type_vals[] = {
|
|
|
|
{ 1, "DER Encoded X.501 Name" },
|
|
|
|
{ 2, "FQDN" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string icmpv6_option_cert_type_vals[] = {
|
|
|
|
{ 1, "X.509v3 Certificate" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2001-05-27 04:14:53 +00:00
|
|
|
static void
|
|
|
|
dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
Have a flag in the "packet_info" structure, which indicates whether the
stuff currently being dissected is part of a packet included in an error
packet (e.g., an ICMP Unreachable packet). Have the TCP dissector not
bother doing reassembly if the TCP segment is part of an error packet,
rather than an actual TCP transmission; other dissectors might want to
treat those packets specially as well.
Add to the "tcpinfo" structure a flag indicating whether the URG flag
was set, rather than having the zero or non-zero value of the urgent
pointer indicate that. (Yes, at least as I read RFC 793, a zero urgent
pointer value isn't useful, as it means "the stuff before this segment
is urgent", but it's certainly possible to put onto the wire a TCP
segment with URG set and a zero urgent pointer.)
Don't dissect the TCP header by grabbing the entire header with
"tvb_memcpy()" and then pulling stuff out of it - extract stuff with
individual tvbuff calls, and put stuff into the protocol tree and the
Info column as we extract it, so that we can dissect a partial header.
This lets us, for example, get the source and destination ports from the
TCP header of the part of a TCP segment included in a minimum-length
ICMPv4 error packet.
svn path=/trunk/; revision=3986
2001-10-01 08:29:37 +00:00
|
|
|
gboolean save_in_error_pkt;
|
2003-01-20 05:42:37 +00:00
|
|
|
tvbuff_t *next_tvb;
|
|
|
|
|
|
|
|
/* Save the current value of the "we're inside an error packet"
|
|
|
|
flag, and set that flag; subdissectors may treat packets
|
|
|
|
that are the payload of error packets differently from
|
|
|
|
"real" packets. */
|
|
|
|
save_in_error_pkt = pinfo->in_error_pkt;
|
|
|
|
pinfo->in_error_pkt = TRUE;
|
2001-05-27 04:14:53 +00:00
|
|
|
|
|
|
|
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
|
|
|
|
|
|
|
/* tiny sanity check */
|
|
|
|
if ((tvb_get_guint8(tvb, offset) & 0xf0) == 0x60) {
|
2003-01-20 05:42:37 +00:00
|
|
|
/* The contained packet is an IPv6 datagram; dissect it. */
|
|
|
|
call_dissector(ipv6_handle, next_tvb, pinfo, tree);
|
2001-05-27 04:14:53 +00:00
|
|
|
} else
|
2001-11-25 22:51:14 +00:00
|
|
|
call_dissector(data_handle,next_tvb, pinfo, tree);
|
2003-01-20 05:42:37 +00:00
|
|
|
|
|
|
|
/* Restore the "we're inside an error packet" flag. */
|
|
|
|
pinfo->in_error_pkt = save_in_error_pkt;
|
2001-05-27 04:14:53 +00:00
|
|
|
}
|
|
|
|
|
1999-03-29 02:21:34 +00:00
|
|
|
static void
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
|
1999-03-29 02:21:34 +00:00
|
|
|
{
|
2008-11-05 10:59:20 +00:00
|
|
|
proto_tree *icmp6opt_tree, *field_tree, *name_tree, *cga_tree;
|
|
|
|
proto_item *ti, *tf, *name_item, *cga_item;
|
2001-04-23 03:37:31 +00:00
|
|
|
struct nd_opt_hdr nd_opt_hdr, *opt;
|
1999-03-29 02:21:34 +00:00
|
|
|
int len;
|
2005-07-30 16:34:38 +00:00
|
|
|
const char *typename;
|
2003-04-28 19:24:48 +00:00
|
|
|
static const guint8 nd_redirect_reserved[6] = {0, 0, 0, 0, 0, 0};
|
|
|
|
guint8 nd_redirect_res[6];
|
2008-02-24 17:14:47 +00:00
|
|
|
int opt_offset;
|
|
|
|
guint8 padd_length = 0;
|
|
|
|
int par_len;
|
2008-02-24 21:04:42 +00:00
|
|
|
guint8 name_type = 0;
|
2008-02-25 22:17:24 +00:00
|
|
|
guint8 cert_type = 0;
|
|
|
|
asn1_ctx_t asn1_ctx;
|
2008-03-17 21:21:48 +00:00
|
|
|
guint32 lifetime;
|
|
|
|
guint32 no_of_pars;
|
|
|
|
guint32 i;
|
1999-03-29 02:21:34 +00:00
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return;
|
|
|
|
|
|
|
|
again:
|
2001-04-23 03:37:31 +00:00
|
|
|
if ((int)tvb_reported_length(tvb) <= offset)
|
2001-06-01 23:53:49 +00:00
|
|
|
return; /* No more options left */
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
opt = &nd_opt_hdr;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
|
1999-03-29 02:21:34 +00:00
|
|
|
len = opt->nd_opt_len << 3;
|
|
|
|
|
2001-06-02 06:10:08 +00:00
|
|
|
/* !!! specify length */
|
2006-10-30 15:36:40 +00:00
|
|
|
ti = proto_tree_add_item(tree, hf_icmpv6_option, tvb, offset, len, FALSE);
|
2001-06-02 06:10:08 +00:00
|
|
|
icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
|
|
|
|
|
2001-06-01 23:53:49 +00:00
|
|
|
if (len == 0) {
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
|
|
|
|
"Invalid option length: %u",
|
|
|
|
opt->nd_opt_len);
|
|
|
|
return; /* we must not try to decode this */
|
|
|
|
}
|
|
|
|
|
2006-10-30 15:36:40 +00:00
|
|
|
typename = val_to_str(opt->nd_opt_type, option_vals, "Unknown");
|
|
|
|
|
|
|
|
/* Add option name to option root label */
|
|
|
|
proto_item_append_text(ti, " (%s)", typename);
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2006-10-30 15:36:40 +00:00
|
|
|
/* Option type */
|
2008-03-01 16:23:14 +00:00
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_option_type, tvb,
|
2008-02-24 17:14:47 +00:00
|
|
|
offset + offsetof(struct nd_opt_hdr, nd_opt_type), 1, FALSE);
|
2006-10-30 15:36:40 +00:00
|
|
|
/* Option length */
|
|
|
|
proto_tree_add_uint(icmp6opt_tree, hf_icmpv6_option_length, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
|
2006-10-30 15:36:40 +00:00
|
|
|
opt->nd_opt_len << 3);
|
1999-03-29 02:21:34 +00:00
|
|
|
|
|
|
|
/* decode... */
|
|
|
|
switch (opt->nd_opt_type) {
|
|
|
|
case ND_OPT_SOURCE_LINKADDR:
|
|
|
|
case ND_OPT_TARGET_LINKADDR:
|
|
|
|
{
|
2008-06-28 21:09:57 +00:00
|
|
|
int len_local, p;
|
2004-02-25 09:31:07 +00:00
|
|
|
|
|
|
|
p = offset + sizeof(*opt);
|
2008-06-28 21:09:57 +00:00
|
|
|
len_local = (opt->nd_opt_len << 3) - sizeof(*opt);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2008-06-28 21:09:57 +00:00
|
|
|
offset + sizeof(*opt), len_local, "Link-layer address: %s",
|
|
|
|
bytestring_to_str(tvb_get_ptr(tvb, p, len_local), len_local, ':'));
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ND_OPT_PREFIX_INFORMATION:
|
|
|
|
{
|
2001-04-23 03:37:31 +00:00
|
|
|
struct nd_opt_prefix_info nd_opt_prefix_info, *pi;
|
1999-03-29 02:21:34 +00:00
|
|
|
int flagoff;
|
2001-04-23 03:37:31 +00:00
|
|
|
|
|
|
|
pi = &nd_opt_prefix_info;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix_len),
|
2001-04-23 03:37:31 +00:00
|
|
|
1, "Prefix length: %u", pi->nd_opt_pi_prefix_len);
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
flagoff = offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved);
|
|
|
|
tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1, "Flags: 0x%02x",
|
|
|
|
tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved)));
|
1999-11-16 11:44:20 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
|
2001-06-01 23:53:49 +00:00
|
|
|
ND_OPT_PI_FLAG_ONLINK, 8, "Onlink", "Not onlink"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
|
2001-06-01 23:53:49 +00:00
|
|
|
ND_OPT_PI_FLAG_AUTO, 8, "Auto", "Not auto"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
2001-01-23 02:49:55 +00:00
|
|
|
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
|
2001-06-01 23:53:49 +00:00
|
|
|
ND_OPT_PI_FLAG_ROUTER, 8,
|
|
|
|
"Router Address", "Not router address"));
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
|
|
|
|
ND_OPT_PI_FLAG_SITEPREF, 8,
|
|
|
|
"Site prefix", "Not site prefix"));
|
2006-11-02 16:47:13 +00:00
|
|
|
if (pntohl(&pi->nd_opt_pi_valid_time) == 0xffffffff)
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
|
|
|
|
4, "Valid lifetime: infinity");
|
|
|
|
else
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
|
|
|
|
4, "Valid lifetime: %u",
|
|
|
|
pntohl(&pi->nd_opt_pi_valid_time));
|
|
|
|
if (pntohl(&pi->nd_opt_pi_preferred_time) == 0xffffffff)
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
|
|
|
|
4, "Preferred lifetime: infinity");
|
|
|
|
else
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
|
|
|
|
4, "Preferred lifetime: %u",
|
|
|
|
pntohl(&pi->nd_opt_pi_preferred_time));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix),
|
|
|
|
16, "Prefix: %s", ip6_to_str(&pi->nd_opt_pi_prefix));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ND_OPT_REDIRECTED_HEADER:
|
2003-04-28 19:24:48 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)&nd_redirect_res, offset + 2, 6);
|
|
|
|
if (memcmp(nd_redirect_res, nd_redirect_reserved, 6) == 0)
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + 2, 6, "Reserved: 0 (correct)");
|
|
|
|
else
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2007-07-30 17:21:40 +00:00
|
|
|
offset +2, 6, "Reserved: MUST be 0 (incorrect!)");
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + 8, (opt->nd_opt_len << 3) - 8, "Redirected packet");
|
2001-05-27 04:14:53 +00:00
|
|
|
dissect_contained_icmpv6(tvb, offset + 8, pinfo, icmp6opt_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ND_OPT_MTU:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu), 4,
|
2001-04-23 03:37:31 +00:00
|
|
|
"MTU: %u", tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu)));
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
2001-06-01 23:53:49 +00:00
|
|
|
case ND_OPT_ADVINTERVAL:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2001-01-23 02:49:55 +00:00
|
|
|
offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint), 4,
|
2002-01-11 09:12:26 +00:00
|
|
|
"Advertisement Interval: %u",
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint)));
|
2001-01-23 02:49:55 +00:00
|
|
|
break;
|
2008-02-23 19:17:23 +00:00
|
|
|
case ND_OPT_HOMEAGENT_INFO: /* 8 */
|
2001-01-23 02:49:55 +00:00
|
|
|
{
|
2001-06-01 23:53:49 +00:00
|
|
|
struct nd_opt_ha_info pibuf, *pi;
|
|
|
|
|
|
|
|
pi = &pibuf;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2001-01-23 02:49:55 +00:00
|
|
|
offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_pref),
|
|
|
|
2, "Home Agent Preference: %d",
|
2002-01-11 09:12:26 +00:00
|
|
|
(gint16)pntohs(&pi->nd_opt_ha_info_ha_pref));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2001-01-23 02:49:55 +00:00
|
|
|
offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_life),
|
2002-01-11 09:12:26 +00:00
|
|
|
2, "Home Agent Lifetime: %u",
|
2001-01-23 02:49:55 +00:00
|
|
|
pntohs(&pi->nd_opt_ha_info_ha_life));
|
|
|
|
break;
|
|
|
|
}
|
2008-11-05 10:59:20 +00:00
|
|
|
case ND_OPT_CGA: /* 11 */ {
|
|
|
|
guint16 ext_data_len;
|
2008-02-24 17:14:47 +00:00
|
|
|
/* RFC 3971 5.1. CGA Option */
|
|
|
|
/* Pad Length */
|
|
|
|
opt_offset = offset +2;
|
|
|
|
padd_length = tvb_get_guint8(tvb,opt_offset);
|
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
|
|
|
|
opt_offset++;
|
|
|
|
/* Reserved 8 bits */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
|
|
|
|
opt_offset++;
|
|
|
|
/* CGA Parameters A variable-length field containing the CGA Parameters data
|
2008-03-01 16:23:14 +00:00
|
|
|
* structure described in Section 4 of
|
2008-02-24 17:14:47 +00:00
|
|
|
* "Cryptographically Generated Addresses (CGA)", RFC3972.
|
|
|
|
*/
|
|
|
|
par_len = len-4-padd_length;
|
2008-11-05 10:59:20 +00:00
|
|
|
cga_item = proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga, tvb, opt_offset, par_len, FALSE);
|
|
|
|
par_len += opt_offset;
|
|
|
|
cga_tree = proto_item_add_subtree(cga_item, ett_cga_param_name);
|
|
|
|
proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_modifier,tvb, opt_offset,16,FALSE);
|
|
|
|
opt_offset += 16;
|
|
|
|
proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_subnet_prefix,tvb,opt_offset,8,FALSE);
|
|
|
|
opt_offset += 8;
|
|
|
|
proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_count,tvb,opt_offset,1,FALSE);
|
|
|
|
opt_offset++;
|
|
|
|
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
|
|
|
opt_offset = dissect_x509af_SubjectPublicKeyInfo(FALSE, tvb, opt_offset, &asn1_ctx, cga_tree, -1);
|
|
|
|
/* Process RFC 4581*/
|
|
|
|
while (opt_offset < par_len) {
|
|
|
|
proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_type,tvb,opt_offset,2,FALSE);
|
|
|
|
opt_offset += 2;
|
|
|
|
ext_data_len = tvb_get_ntohs(tvb,opt_offset);
|
|
|
|
proto_tree_add_item(cga_tree,hf_icmpv6_opt_cga_ext_length,tvb,opt_offset,2,FALSE);
|
|
|
|
opt_offset += 2;
|
|
|
|
proto_tree_add_text(cga_tree,tvb,opt_offset,ext_data_len,"Ext Data");
|
|
|
|
opt_offset += ext_data_len;
|
|
|
|
}
|
|
|
|
|
2008-02-24 17:14:47 +00:00
|
|
|
/* Padding */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
|
|
|
|
break;
|
2008-11-05 10:59:20 +00:00
|
|
|
}
|
2008-03-01 16:23:14 +00:00
|
|
|
case ND_OPT_RSA: /* 12 */
|
2008-02-24 17:14:47 +00:00
|
|
|
/*5.2. RSA Signature Option */
|
|
|
|
opt_offset = offset +2;
|
|
|
|
/* Reserved, A 16-bit field reserved for future use. */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Reserved");
|
|
|
|
opt_offset = opt_offset + 2;
|
2008-03-01 16:23:14 +00:00
|
|
|
/* Key Hash
|
2008-02-24 17:14:47 +00:00
|
|
|
* A 128-bit field containing the most significant (leftmost) 128
|
|
|
|
* bits of a SHA-1 [14] hash of the public key used for constructing
|
|
|
|
* the signature.
|
|
|
|
*/
|
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_rsa_key_hash, tvb, opt_offset, 16, FALSE);
|
|
|
|
opt_offset = opt_offset + 16;
|
|
|
|
/* Digital Signature */
|
|
|
|
par_len = len - 20;
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Digital Signature + Padding");
|
|
|
|
/* Padding */
|
|
|
|
/* TODO: Calculate padding length and exlude from the signature */
|
|
|
|
break;
|
|
|
|
case ND_OPT_TIMESTAMP: /* 13 */
|
|
|
|
opt_offset = offset +2;
|
|
|
|
/* Reserved A 48-bit field reserved for future use. */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Reserved");
|
|
|
|
opt_offset = opt_offset + 6;
|
|
|
|
/* Timestamp
|
|
|
|
* A 64-bit unsigned integer field containing a timestamp. The value
|
|
|
|
* indicates the number of seconds since January 1, 1970, 00:00 UTC,
|
|
|
|
* by using a fixed point format. In this format, the integer number
|
|
|
|
* of seconds is contained in the first 48 bits of the field, and the
|
|
|
|
* remaining 16 bits indicate the number of 1/64K fractions of a
|
|
|
|
* second.
|
|
|
|
*/
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,6,"Timestamp(number of seconds since January 1, 1970, 00:00 UTC)");
|
|
|
|
opt_offset = opt_offset + 6;
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,2,"Timestamp(1/64K fractions of a second)");
|
|
|
|
break;
|
|
|
|
case ND_OPT_NONCE:
|
|
|
|
/* 5.3.2. Nonce Option */
|
|
|
|
opt_offset = offset +2;
|
2008-11-05 10:59:20 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,len-2,"Nonce");
|
2008-02-24 17:14:47 +00:00
|
|
|
/* Nonce */
|
2008-02-23 19:17:23 +00:00
|
|
|
break;
|
2008-02-24 21:04:42 +00:00
|
|
|
case ND_OPT_TRUST_ANCHOR:
|
|
|
|
opt_offset = offset +2;
|
|
|
|
/* Name Type */
|
|
|
|
name_type = tvb_get_guint8(tvb,opt_offset);
|
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_type, tvb, opt_offset, 1, FALSE);
|
|
|
|
opt_offset++;
|
|
|
|
/* Pad Length */
|
|
|
|
padd_length = tvb_get_guint8(tvb,opt_offset);
|
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cga_pad_len, tvb, opt_offset, 1, FALSE);
|
|
|
|
opt_offset++;
|
|
|
|
par_len = len - 4 - padd_length;
|
|
|
|
switch (name_type){
|
|
|
|
case 1:
|
|
|
|
/* DER Encoded X.501 Name */
|
2008-02-25 22:17:24 +00:00
|
|
|
name_item =proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_x501, tvb, opt_offset, par_len, FALSE);
|
|
|
|
name_tree = proto_item_add_subtree(name_item, ett_icmpv6opt_name);
|
|
|
|
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
|
|
|
dissect_x509if_Name(FALSE, tvb, opt_offset, &asn1_ctx, name_tree, hf_icmpv6_x509if_Name);
|
2008-02-24 21:04:42 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* FQDN */
|
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_name_fqdn, tvb, opt_offset, par_len, FALSE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset, par_len,"Unknown name type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
opt_offset = opt_offset + par_len;
|
|
|
|
/* Padding */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,padd_length,"Padding");
|
|
|
|
opt_offset = opt_offset + padd_length;
|
|
|
|
break;
|
|
|
|
case ND_OPT_CERTIFICATE:
|
|
|
|
opt_offset = offset +2;
|
|
|
|
/* Cert Type */
|
2008-02-25 22:17:24 +00:00
|
|
|
cert_type = tvb_get_guint8(tvb,opt_offset);
|
2008-02-24 21:04:42 +00:00
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_cert_type, tvb, opt_offset, 1, FALSE);
|
|
|
|
opt_offset++;
|
|
|
|
/* Reserved */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,1,"Reserved");
|
|
|
|
opt_offset++;
|
|
|
|
/* Certificate */
|
2008-03-01 16:23:14 +00:00
|
|
|
|
2008-02-25 22:17:24 +00:00
|
|
|
if(cert_type == 1){
|
2008-03-01 16:23:14 +00:00
|
|
|
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
2008-02-25 22:17:24 +00:00
|
|
|
opt_offset = dissect_x509af_Certificate(FALSE, tvb, opt_offset, &asn1_ctx, icmp6opt_tree, hf_icmpv6_x509af_Certificate);
|
|
|
|
par_len = len - (opt_offset - offset);
|
|
|
|
/* Padding */
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Padding");
|
|
|
|
}else{
|
|
|
|
par_len = len - 4;
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,opt_offset,par_len,"Unknown Certificate + padding");
|
|
|
|
}
|
2008-03-01 16:23:14 +00:00
|
|
|
|
2008-02-24 21:04:42 +00:00
|
|
|
break;
|
2001-09-04 21:04:52 +00:00
|
|
|
case ND_OPT_MAP:
|
|
|
|
{
|
|
|
|
struct nd_opt_map_info mapbuf, *map;
|
|
|
|
int flagoff;
|
|
|
|
|
|
|
|
map = &mapbuf;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)map, offset, sizeof *map);
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2002-01-15 20:11:10 +00:00
|
|
|
offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
|
|
|
|
1, "Distance: %u", (map->nd_opt_map_dist_and_pref >> 4));
|
2001-09-04 21:04:52 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2002-01-15 20:11:10 +00:00
|
|
|
offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
|
|
|
|
1, "Preference: %u", (map->nd_opt_map_dist_and_pref & 0x0F));
|
2001-09-04 21:04:52 +00:00
|
|
|
flagoff = offset + offsetof(struct nd_opt_map_info,
|
|
|
|
nd_opt_map_flags);
|
|
|
|
tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
|
|
|
|
"Flags: 0x%02x",
|
|
|
|
tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_map_info,
|
|
|
|
nd_opt_map_flags)));
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(map->nd_opt_map_flags,
|
2002-01-09 19:13:03 +00:00
|
|
|
ND_OPT_MAP_FLAG_R, 8, "R", "No R"));
|
2001-09-04 21:04:52 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(map->nd_opt_map_flags,
|
2002-01-09 19:13:03 +00:00
|
|
|
ND_OPT_MAP_FLAG_M, 8, "M", "No M"));
|
2001-09-04 21:04:52 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(map->nd_opt_map_flags,
|
2002-01-09 19:13:03 +00:00
|
|
|
ND_OPT_MAP_FLAG_I, 8, "I", "No I"));
|
2001-09-04 21:04:52 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(map->nd_opt_map_flags,
|
2002-01-09 19:13:03 +00:00
|
|
|
ND_OPT_MAP_FLAG_T, 8, "T", "No T"));
|
2001-09-04 21:04:52 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(map->nd_opt_map_flags,
|
2002-01-09 19:13:03 +00:00
|
|
|
ND_OPT_MAP_FLAG_P, 8, "P", "No P"));
|
2002-01-15 20:11:10 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(map->nd_opt_map_flags,
|
|
|
|
ND_OPT_MAP_FLAG_V, 8, "V", "No V"));
|
2001-09-04 21:04:52 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_map_info, nd_opt_map_lifetime),
|
2002-01-10 09:49:35 +00:00
|
|
|
4, "Lifetime: %u", pntohl(&map->nd_opt_map_lifetime));
|
2001-09-04 21:04:52 +00:00
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_map_info, nd_opt_map_address), 16,
|
|
|
|
#ifdef INET6
|
|
|
|
"Address of MAP: %s (%s)",
|
|
|
|
get_hostname6(&map->nd_opt_map_address),
|
|
|
|
#else
|
|
|
|
"Address of MAP: %s",
|
|
|
|
#endif
|
|
|
|
ip6_to_str(&map->nd_opt_map_address));
|
|
|
|
break;
|
|
|
|
}
|
2001-06-01 23:53:49 +00:00
|
|
|
case ND_OPT_ROUTE_INFO:
|
|
|
|
{
|
|
|
|
struct nd_opt_route_info ribuf, *ri;
|
|
|
|
struct e_in6_addr in6;
|
|
|
|
int l;
|
2008-06-28 21:09:57 +00:00
|
|
|
guint32 lifetime_local;
|
2001-06-01 23:53:49 +00:00
|
|
|
|
|
|
|
ri = &ribuf;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)ri, offset, sizeof *ri);
|
|
|
|
memset(&in6, 0, sizeof(in6));
|
|
|
|
switch (ri->nd_opt_rti_len) {
|
|
|
|
case 1:
|
|
|
|
l = 0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 8);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 16);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
l = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (l >= 0) {
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_route_info, nd_opt_rti_prefixlen),
|
|
|
|
1, "Prefix length: %u", ri->nd_opt_rti_prefixlen);
|
|
|
|
tf = proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
|
|
|
|
1, "Flags: 0x%02x", ri->nd_opt_rti_flags);
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
|
|
|
proto_tree_add_text(field_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
|
|
|
|
1, "%s",
|
|
|
|
decode_enumerated_bitfield(ri->nd_opt_rti_flags,
|
|
|
|
ND_RA_FLAG_RTPREF_MASK, 8, names_router_pref,
|
|
|
|
"Router preference: %s"));
|
2008-06-28 21:09:57 +00:00
|
|
|
lifetime_local = pntohl(&ri->nd_opt_rti_lifetime);
|
|
|
|
if (lifetime_local == 0xffffffff)
|
2001-06-01 23:53:49 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
|
|
|
|
sizeof(ri->nd_opt_rti_lifetime), "Lifetime: infinity");
|
|
|
|
else
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
|
2008-06-28 21:09:57 +00:00
|
|
|
sizeof(ri->nd_opt_rti_lifetime), "Lifetime: %u", lifetime_local);
|
2001-06-01 23:53:49 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + sizeof(*ri), l, "Prefix: %s", ip6_to_str(&in6));
|
|
|
|
} else {
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
|
|
|
|
"Invalid option length: %u", opt->nd_opt_len);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2005-10-25 06:00:53 +00:00
|
|
|
|
|
|
|
case FMIP6_OPT_NEIGHBOR_ADV_ACK:
|
2008-03-17 21:21:48 +00:00
|
|
|
{
|
|
|
|
struct fmip6_opt_neighbor_advertisement_ack fmip6_opt_neighbor_advertisement_ack, *opt_naack;
|
|
|
|
struct e_in6_addr in6;
|
2005-10-25 06:00:53 +00:00
|
|
|
|
2008-03-17 21:21:48 +00:00
|
|
|
opt_naack = &fmip6_opt_neighbor_advertisement_ack;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)opt_naack, offset, sizeof *opt_naack);
|
2005-10-25 06:00:53 +00:00
|
|
|
|
2008-03-17 21:21:48 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_optcode),
|
|
|
|
1, "Option-Code: %u",
|
|
|
|
opt_naack->fmip6_opt_optcode);
|
2005-10-25 06:00:53 +00:00
|
|
|
|
2008-03-17 21:21:48 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_status),
|
|
|
|
1, "Status: %s",
|
|
|
|
val_to_str(opt_naack->fmip6_opt_status, names_fmip6_naack_opt_status, "Unknown"));
|
2005-10-25 06:00:53 +00:00
|
|
|
|
2008-03-17 21:21:48 +00:00
|
|
|
if (opt_naack->fmip6_opt_len == 3){
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*opt_naack), 16);
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + sizeof(*opt_naack),
|
|
|
|
16, "New Care-of Address: %s",
|
|
|
|
ip6_to_str(&in6));
|
|
|
|
}
|
2005-10-25 06:00:53 +00:00
|
|
|
|
2008-03-17 21:21:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ND_OPT_RECURSIVE_DNS_SERVER:
|
|
|
|
|
|
|
|
opt_offset = offset + 2;
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,2 ,"Reserved");
|
|
|
|
opt_offset = opt_offset + 2;
|
|
|
|
/* A value of all one bits (0xffffffff) represents infinity. A value of
|
|
|
|
* zero means that the RDNSS address MUST no longer be used.
|
|
|
|
*/
|
|
|
|
lifetime = tvb_get_ntohl(tvb, opt_offset);
|
|
|
|
if (lifetime == 0xffffffff){
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: infinity");
|
|
|
|
}else{
|
|
|
|
if(lifetime==0){
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: RDNSS address MUST no longer be used");
|
|
|
|
}else{
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb, opt_offset ,4 ,"Lifetime: %u", lifetime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
opt_offset = opt_offset+4;
|
|
|
|
/* Addresses of IPv6 Recursive DNS Servers */
|
|
|
|
no_of_pars = opt->nd_opt_len - 1;
|
|
|
|
no_of_pars = no_of_pars >> 2;
|
|
|
|
|
|
|
|
for (i = 0; i <= no_of_pars; i++) {
|
|
|
|
proto_tree_add_item(icmp6opt_tree, hf_icmpv6_recursive_dns_serv, tvb, opt_offset, 16, FALSE);
|
|
|
|
opt_offset = opt_offset+16;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2000-10-12 14:58:02 +00:00
|
|
|
|
1999-03-29 02:21:34 +00:00
|
|
|
offset += (opt->nd_opt_len << 3);
|
2006-10-30 15:36:40 +00:00
|
|
|
|
|
|
|
/* Set length of option tree */
|
|
|
|
proto_item_set_len(ti, opt->nd_opt_len << 3);
|
1999-03-29 02:21:34 +00:00
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
|
2006-03-29 22:04:37 +00:00
|
|
|
static void
|
|
|
|
dissect_icmpv6fmip6opt(tvbuff_t *tvb, int offset, proto_tree *tree)
|
2005-10-25 06:00:53 +00:00
|
|
|
{
|
|
|
|
proto_tree *icmp6opt_tree;
|
|
|
|
proto_item *ti;
|
|
|
|
struct fmip6_opt_hdr fmip6_opt_hdr, *opt;
|
|
|
|
int len;
|
2008-06-25 09:12:35 +00:00
|
|
|
const char *typename;
|
2005-10-25 06:00:53 +00:00
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return;
|
|
|
|
|
|
|
|
again:
|
|
|
|
if ((int)tvb_reported_length(tvb) <= offset)
|
|
|
|
return; /* No more options left */
|
|
|
|
|
|
|
|
opt = &fmip6_opt_hdr;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
|
|
|
|
len = opt->fmip6_opt_len << 3;
|
|
|
|
|
|
|
|
/* !!! specify length */
|
|
|
|
ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
|
|
|
|
icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
|
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
|
|
|
|
"Invalid option length: %u",
|
|
|
|
opt->fmip6_opt_len);
|
|
|
|
return; /* we must not try to decode this */
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (opt->fmip6_opt_type) {
|
|
|
|
case FMIP6_OPT_IP_ADDRESS:
|
|
|
|
typename = "IP Address";
|
|
|
|
break;
|
|
|
|
case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
|
|
|
|
typename = "New Router Prefix Information";
|
|
|
|
break;
|
|
|
|
case FMIP6_OPT_LINK_LAYER_ADDRESS:
|
|
|
|
typename = "Link-layer Address";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
typename = "Unknown";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_type), 1,
|
|
|
|
"Type: %u (%s)", opt->fmip6_opt_type, typename);
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
|
|
|
|
"Length: %u bytes (%u)", opt->fmip6_opt_len << 3, opt->fmip6_opt_len);
|
|
|
|
|
|
|
|
/* decode... */
|
|
|
|
switch (opt->fmip6_opt_type) {
|
|
|
|
case FMIP6_OPT_IP_ADDRESS:
|
|
|
|
{
|
|
|
|
struct fmip6_opt_ip_address fmip6_opt_ip_address, *opt_ip;
|
|
|
|
|
|
|
|
opt_ip = &fmip6_opt_ip_address;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)opt_ip, offset, sizeof *opt_ip);
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
|
|
|
|
val_to_str(opt->fmip6_opt_optcode, names_fmip6_ip_addr_opt_code, "Unknown"));
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_prefix_len),
|
|
|
|
1, "Prefix length: %u", opt_ip->fmip6_opt_prefix_len);
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2007-07-30 17:21:40 +00:00
|
|
|
offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_ip6_address),
|
2005-10-25 06:00:53 +00:00
|
|
|
16, "IPv6 Address: %s",
|
|
|
|
ip6_to_str(&opt_ip->fmip6_opt_ip6_address));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
|
|
|
|
{
|
|
|
|
struct fmip6_opt_new_router_prefix_info fmip6_opt_new_router_prefix_info, *opt_nr;
|
|
|
|
|
|
|
|
opt_nr = &fmip6_opt_new_router_prefix_info;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)opt_nr, offset, sizeof *opt_nr);
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %u",
|
|
|
|
opt->fmip6_opt_optcode);
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix_len),
|
|
|
|
1, "Prefix length: %u", opt_nr->fmip6_opt_prefix_len);
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2007-07-30 17:21:40 +00:00
|
|
|
offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix),
|
2005-10-25 06:00:53 +00:00
|
|
|
16, "Prefix: %s",
|
|
|
|
ip6_to_str(&opt_nr->fmip6_opt_prefix));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMIP6_OPT_LINK_LAYER_ADDRESS:
|
|
|
|
{
|
2008-06-28 21:09:57 +00:00
|
|
|
int len_local, p;
|
2005-10-25 06:00:53 +00:00
|
|
|
|
|
|
|
p = offset + sizeof(*opt);
|
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
|
|
|
offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
|
|
|
|
val_to_str(opt->fmip6_opt_optcode, names_fmip6_lla_opt_code, "Unknown"));
|
2008-06-28 21:09:57 +00:00
|
|
|
len_local = (opt->fmip6_opt_len << 3) - sizeof(*opt);
|
2005-10-25 06:00:53 +00:00
|
|
|
proto_tree_add_text(icmp6opt_tree, tvb,
|
2008-06-28 21:09:57 +00:00
|
|
|
offset + sizeof(*opt), len_local, "Link-layer address: %s",
|
|
|
|
bytestring_to_str(tvb_get_ptr(tvb, p, len_local), len_local, ':'));
|
2005-10-25 06:00:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += (opt->fmip6_opt_len << 3);
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
|
2000-08-18 12:05:27 +00:00
|
|
|
/*
|
2001-04-23 03:37:31 +00:00
|
|
|
* draft-ietf-ipngwg-icmp-name-lookups-07.txt
|
2000-08-18 12:05:27 +00:00
|
|
|
* Note that the packet format was changed several times in the past.
|
|
|
|
*/
|
2000-08-22 08:30:00 +00:00
|
|
|
|
|
|
|
static const char *
|
2004-01-18 16:21:12 +00:00
|
|
|
bitrange0(guint32 v, int s, char *buf, int buflen)
|
2000-08-22 08:30:00 +00:00
|
|
|
{
|
2000-08-22 15:07:33 +00:00
|
|
|
guint32 v0;
|
2000-08-22 08:30:00 +00:00
|
|
|
char *p, *ep;
|
|
|
|
int off;
|
|
|
|
int i, l;
|
|
|
|
|
|
|
|
if (buflen < 1)
|
|
|
|
return NULL;
|
|
|
|
if (buflen == 1) {
|
|
|
|
buf[0] = '\0';
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
v0 = v;
|
|
|
|
p = buf;
|
|
|
|
ep = buf + buflen - 1;
|
|
|
|
memset(buf, 0, buflen);
|
|
|
|
off = 0;
|
|
|
|
while (off < 32) {
|
|
|
|
/* shift till we have 0x01 */
|
|
|
|
if ((v & 0x01) == 0) {
|
|
|
|
switch (v & 0x0f) {
|
|
|
|
case 0x00:
|
|
|
|
v >>= 4; off += 4; continue;
|
|
|
|
case 0x08:
|
|
|
|
v >>= 3; off += 3; continue;
|
|
|
|
case 0x04: case 0x0c:
|
|
|
|
v >>= 2; off += 2; continue;
|
|
|
|
default:
|
|
|
|
v >>= 1; off += 1; continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we have 0x01 with us */
|
|
|
|
for (i = 0; i < 32 - off; i++) {
|
|
|
|
if ((v & (0x01 << i)) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == 1)
|
2005-08-17 23:10:28 +00:00
|
|
|
l = g_snprintf(p, ep - p, ",%d", s + off);
|
2000-08-22 08:30:00 +00:00
|
|
|
else {
|
2005-08-17 23:10:28 +00:00
|
|
|
l = g_snprintf(p, ep - p, ",%d-%d", s + off,
|
2000-08-22 08:30:00 +00:00
|
|
|
s + off + i - 1);
|
|
|
|
}
|
2006-01-16 07:59:44 +00:00
|
|
|
if (l == -1 || l >= ep - p) {
|
2000-08-22 08:30:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
v >>= i; off += i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2001-04-23 03:37:31 +00:00
|
|
|
bitrange(tvbuff_t *tvb, int offset, int l, int s)
|
2000-08-22 08:30:00 +00:00
|
|
|
{
|
|
|
|
static char buf[1024];
|
|
|
|
char *q, *eq;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
q = buf;
|
|
|
|
eq = buf + sizeof(buf) - 1;
|
|
|
|
for (i = 0; i < l; i++) {
|
2001-04-23 03:37:31 +00:00
|
|
|
if (bitrange0(tvb_get_ntohl(tvb, offset + i * 4), s + i * 4, q, eq - q) == NULL) {
|
2000-08-22 08:30:00 +00:00
|
|
|
if (q != buf && q + 5 < buf + sizeof(buf))
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcpy(q, ",...", 5);
|
2000-08-22 08:30:00 +00:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf + 1;
|
|
|
|
}
|
|
|
|
|
2000-08-18 12:05:27 +00:00
|
|
|
static void
|
2001-04-23 03:37:31 +00:00
|
|
|
dissect_nodeinfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
|
2000-08-18 12:05:27 +00:00
|
|
|
{
|
|
|
|
proto_tree *field_tree;
|
2006-03-29 22:04:37 +00:00
|
|
|
proto_item *tf;
|
2001-04-23 03:37:31 +00:00
|
|
|
struct icmp6_nodeinfo icmp6_nodeinfo, *ni;
|
2000-08-18 12:05:27 +00:00
|
|
|
int off;
|
2001-04-27 01:27:37 +00:00
|
|
|
unsigned int j;
|
2001-04-23 03:37:31 +00:00
|
|
|
int i, n, l, p;
|
2000-08-18 12:05:27 +00:00
|
|
|
guint16 flags;
|
2007-04-23 10:59:26 +00:00
|
|
|
const char *dname;
|
2005-09-13 00:50:43 +00:00
|
|
|
guint32 ipaddr;
|
2000-08-18 12:05:27 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
ni = &icmp6_nodeinfo;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
|
2000-08-18 12:05:27 +00:00
|
|
|
/* flags */
|
|
|
|
flags = pntohs(&ni->ni_flags);
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "Flags: 0x%04x", flags);
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_flag);
|
|
|
|
switch (pntohs(&ni->ni_qtype)) {
|
|
|
|
case NI_QTYPE_SUPTYPES:
|
|
|
|
if (ni->ni_type == ICMP6_NI_QUERY) {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Compressed reply supported",
|
|
|
|
"No compressed reply support"));
|
|
|
|
} else {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Compressed", "Not compressed"));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_DNSNAME:
|
|
|
|
if (ni->ni_type == ICMP6_NI_REPLY) {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_FQDN_FLAG_VALIDTTL, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Valid TTL field", "Meaningless TTL field"));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NI_QTYPE_NODEADDR:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_GLOBAL, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Global address",
|
|
|
|
"Not global address"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_SITELOCAL, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Site-local address",
|
|
|
|
"Not site-local address"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_LINKLOCAL, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Link-local address",
|
|
|
|
"Not link-local address"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_COMPAT, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"IPv4 compatible/mapped address",
|
|
|
|
"Not IPv4 compatible/mapped address"));
|
|
|
|
/* fall through */
|
|
|
|
case NI_QTYPE_IPV4ADDR:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_ALL, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"All unicast address",
|
|
|
|
"Unicast addresses on the queried interface"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_flags),
|
|
|
|
sizeof(ni->ni_flags), "%s",
|
2000-11-11 10:23:43 +00:00
|
|
|
decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_TRUNCATE, sizeof(flags) * 8,
|
2000-08-18 12:05:27 +00:00
|
|
|
"Truncated", "Not truncated"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* nonce */
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, icmp6_ni_nonce[0]),
|
|
|
|
sizeof(ni->icmp6_ni_nonce), "Nonce: 0x%08x%08x",
|
|
|
|
pntohl(&ni->icmp6_ni_nonce[0]), pntohl(&ni->icmp6_ni_nonce[4]));
|
|
|
|
|
|
|
|
/* offset for "the rest of data" */
|
|
|
|
off = sizeof(*ni);
|
|
|
|
|
2000-08-22 08:30:00 +00:00
|
|
|
/* rest of data */
|
2001-04-23 03:37:31 +00:00
|
|
|
if (!tvb_bytes_exist(tvb, offset, sizeof(*ni)))
|
2000-08-22 08:30:00 +00:00
|
|
|
goto nodata;
|
2000-08-18 12:05:27 +00:00
|
|
|
if (ni->ni_type == ICMP6_NI_QUERY) {
|
|
|
|
switch (ni->ni_code) {
|
|
|
|
case ICMP6_NI_SUBJ_IPV6:
|
2002-01-24 09:20:54 +00:00
|
|
|
n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
|
2000-08-18 12:05:27 +00:00
|
|
|
n /= sizeof(struct e_in6_addr);
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset + sizeof(*ni), -1, "IPv6 subject addresses");
|
2000-08-18 12:05:27 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject6);
|
2001-04-23 03:37:31 +00:00
|
|
|
p = offset + sizeof *ni;
|
2000-08-18 12:05:27 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
2001-04-23 03:37:31 +00:00
|
|
|
struct e_in6_addr e_in6_addr;
|
2005-09-11 21:25:37 +00:00
|
|
|
tvb_get_ipv6(tvb, p, &e_in6_addr);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
|
|
|
p, sizeof(struct e_in6_addr),
|
|
|
|
"%s", ip6_to_str(&e_in6_addr));
|
2000-08-18 12:05:27 +00:00
|
|
|
p += sizeof(struct e_in6_addr);
|
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_NI_SUBJ_FQDN:
|
2008-08-11 12:00:27 +00:00
|
|
|
/* XXX Fix data length */
|
|
|
|
l = get_dns_name(tvb, offset + sizeof(*ni), 0,
|
2005-10-08 12:31:06 +00:00
|
|
|
offset + sizeof(*ni), &dname);
|
2001-04-23 03:37:31 +00:00
|
|
|
if (tvb_bytes_exist(tvb, offset + sizeof(*ni) + l, 1) &&
|
|
|
|
tvb_get_guint8(tvb, offset + sizeof(*ni) + l) == 0) {
|
2000-08-22 08:30:00 +00:00
|
|
|
l++;
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
|
2000-08-22 08:30:00 +00:00
|
|
|
"DNS label: %s (truncated)", dname);
|
|
|
|
} else {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
|
2000-08-22 08:30:00 +00:00
|
|
|
"DNS label: %s", dname);
|
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset + sizeof(*ni) + l);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_NI_SUBJ_IPV4:
|
2002-01-24 09:20:54 +00:00
|
|
|
n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
|
2000-08-18 12:05:27 +00:00
|
|
|
n /= sizeof(guint32);
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset + sizeof(*ni), -1, "IPv4 subject addresses");
|
2000-08-18 12:05:27 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject4);
|
2001-04-23 03:37:31 +00:00
|
|
|
p = offset + sizeof *ni;
|
2000-08-18 12:05:27 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
2005-09-13 00:50:43 +00:00
|
|
|
ipaddr = tvb_get_ipv4(tvb, p);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2005-09-13 00:50:43 +00:00
|
|
|
p, sizeof(guint32), "%s", ip_to_str((guint8 *)&ipaddr));
|
2000-08-18 12:05:27 +00:00
|
|
|
p += sizeof(guint32);
|
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (pntohs(&ni->ni_qtype)) {
|
|
|
|
case NI_QTYPE_NOOP:
|
2000-08-22 08:30:00 +00:00
|
|
|
break;
|
2000-08-18 12:05:27 +00:00
|
|
|
case NI_QTYPE_SUPTYPES:
|
2001-04-23 03:37:31 +00:00
|
|
|
p = offset + sizeof *ni;
|
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset + sizeof(*ni), -1,
|
2000-08-22 08:30:00 +00:00
|
|
|
"Supported type bitmap%s",
|
|
|
|
(flags & 0x0001) ? ", compressed" : "");
|
|
|
|
field_tree = proto_item_add_subtree(tf,
|
|
|
|
ett_nodeinfo_nodebitmap);
|
|
|
|
n = 0;
|
2001-04-23 03:37:31 +00:00
|
|
|
while (tvb_bytes_exist(tvb, p, sizeof(guint32))) { /* XXXX Check what? */
|
2000-08-22 08:30:00 +00:00
|
|
|
if ((flags & 0x0001) == 0) {
|
2002-01-24 09:20:54 +00:00
|
|
|
l = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
|
2000-08-22 08:30:00 +00:00
|
|
|
l /= sizeof(guint32);
|
|
|
|
i = 0;
|
|
|
|
} else {
|
2001-04-23 03:37:31 +00:00
|
|
|
l = tvb_get_ntohs(tvb, p);
|
|
|
|
i = tvb_get_ntohs(tvb, p + sizeof(guint16)); /*skip*/
|
2000-08-22 08:30:00 +00:00
|
|
|
}
|
|
|
|
if (n + l * 32 > (1 << 16))
|
|
|
|
break;
|
|
|
|
if (n + (l + i) * 32 > (1 << 16))
|
|
|
|
break;
|
|
|
|
if ((flags & 0x0001) == 0) {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, p,
|
2000-08-22 08:30:00 +00:00
|
|
|
l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
|
2001-04-23 03:37:31 +00:00
|
|
|
bitrange(tvb, p, l, n));
|
2000-08-22 08:30:00 +00:00
|
|
|
p += l * 4;
|
|
|
|
} else {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, p,
|
2000-08-22 08:30:00 +00:00
|
|
|
4 + l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
|
2001-04-23 03:37:31 +00:00
|
|
|
bitrange(tvb, p + 4, l, n));
|
2000-08-22 08:30:00 +00:00
|
|
|
p += (4 + l * 4);
|
|
|
|
}
|
|
|
|
n += l * 32 + i * 32;
|
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset);
|
2000-08-22 08:30:00 +00:00
|
|
|
break;
|
2000-08-18 12:05:27 +00:00
|
|
|
case NI_QTYPE_DNSNAME:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset + sizeof(*ni),
|
|
|
|
sizeof(gint32), "TTL: %d", (gint32)tvb_get_ntohl(tvb, offset + sizeof *ni));
|
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset + sizeof(*ni) + sizeof(guint32), -1,
|
2000-08-22 08:30:00 +00:00
|
|
|
"DNS labels");
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
|
2001-04-27 01:27:37 +00:00
|
|
|
j = offset + sizeof (*ni) + sizeof(guint32);
|
2002-01-24 09:20:54 +00:00
|
|
|
while (j < tvb_reported_length(tvb)) {
|
2008-08-11 12:00:27 +00:00
|
|
|
/* XXX Fix data length */
|
|
|
|
l = get_dns_name(tvb, j, 0,
|
2001-07-02 07:11:40 +00:00
|
|
|
offset + sizeof (*ni) + sizeof(guint32),
|
2005-10-08 12:31:06 +00:00
|
|
|
&dname);
|
2001-07-02 07:11:40 +00:00
|
|
|
if (tvb_bytes_exist(tvb, j + l, 1) &&
|
|
|
|
tvb_get_guint8(tvb, j + l) == 0) {
|
2000-08-22 08:30:00 +00:00
|
|
|
l++;
|
2001-04-27 01:27:37 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, j, l,
|
2000-08-22 08:30:00 +00:00
|
|
|
"DNS label: %s (truncated)", dname);
|
|
|
|
} else {
|
2001-04-27 01:27:37 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, j, l,
|
2000-08-22 08:30:00 +00:00
|
|
|
"DNS label: %s", dname);
|
|
|
|
}
|
2001-04-27 01:27:37 +00:00
|
|
|
j += l;
|
2000-08-22 08:30:00 +00:00
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
|
|
|
case NI_QTYPE_NODEADDR:
|
2002-01-24 09:20:54 +00:00
|
|
|
n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
|
2001-04-23 03:37:31 +00:00
|
|
|
n /= sizeof(gint32) + sizeof(struct e_in6_addr);
|
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset + sizeof(*ni), -1, "IPv6 node addresses");
|
2000-08-18 12:05:27 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node6);
|
2001-04-23 03:37:31 +00:00
|
|
|
p = offset + sizeof (*ni);
|
2000-08-18 12:05:27 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
2001-04-23 03:37:31 +00:00
|
|
|
struct e_in6_addr e_in6_addr;
|
|
|
|
gint32 ttl;
|
|
|
|
ttl = (gint32)tvb_get_ntohl(tvb, p);
|
2005-09-11 21:25:37 +00:00
|
|
|
tvb_get_ipv6(tvb, p + sizeof ttl, &e_in6_addr);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
|
|
|
p, sizeof(struct e_in6_addr) + sizeof(gint32),
|
|
|
|
"%s (TTL %d)", ip6_to_str(&e_in6_addr), ttl);
|
2000-08-29 14:17:12 +00:00
|
|
|
p += sizeof(struct e_in6_addr) + sizeof(gint32);
|
2000-08-18 12:05:27 +00:00
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
|
|
|
case NI_QTYPE_IPV4ADDR:
|
2002-01-24 09:20:54 +00:00
|
|
|
n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
|
2001-04-23 03:37:31 +00:00
|
|
|
n /= sizeof(gint32) + sizeof(guint32);
|
|
|
|
tf = proto_tree_add_text(tree, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset + sizeof(*ni), -1, "IPv4 node addresses");
|
2000-08-18 12:05:27 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node4);
|
2001-04-23 03:37:31 +00:00
|
|
|
p = offset + sizeof *ni;
|
2000-08-18 12:05:27 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
2005-09-13 00:50:43 +00:00
|
|
|
ipaddr = tvb_get_ipv4(tvb, sizeof(gint32) + p);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb,
|
2005-09-13 00:50:43 +00:00
|
|
|
p, sizeof(guint32), "%s (TTL %d)",
|
|
|
|
ip_to_str((guint8 *)&ipaddr), tvb_get_ntohl(tvb, p));
|
2001-04-23 03:37:31 +00:00
|
|
|
p += sizeof(gint32) + sizeof(guint32);
|
2000-08-18 12:05:27 +00:00
|
|
|
}
|
2001-04-23 03:37:31 +00:00
|
|
|
off = tvb_length_remaining(tvb, offset);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2000-08-22 08:30:00 +00:00
|
|
|
nodata:;
|
2000-08-18 12:05:27 +00:00
|
|
|
|
|
|
|
/* the rest of data */
|
2001-11-25 22:51:14 +00:00
|
|
|
call_dissector(data_handle,tvb_new_subset(tvb, offset + off, -1, -1), pinfo, tree);
|
2000-08-18 12:05:27 +00:00
|
|
|
}
|
|
|
|
|
2000-11-09 16:39:59 +00:00
|
|
|
static void
|
2001-04-23 03:37:31 +00:00
|
|
|
dissect_rrenum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
|
2000-11-09 16:39:59 +00:00
|
|
|
{
|
|
|
|
proto_tree *field_tree, *opt_tree;
|
2006-03-29 22:04:37 +00:00
|
|
|
proto_item *tf;
|
2001-04-23 03:37:31 +00:00
|
|
|
struct icmp6_router_renum icmp6_router_renum, *rr;
|
|
|
|
struct rr_pco_match rr_pco_match, *match;
|
|
|
|
struct rr_pco_use rr_pco_use, *use;
|
2001-04-27 01:27:37 +00:00
|
|
|
int flagoff, off;
|
|
|
|
unsigned int l;
|
2001-04-23 03:37:31 +00:00
|
|
|
guint8 flags;
|
2000-11-09 16:39:59 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
rr = &icmp6_router_renum;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)rr, offset, sizeof *rr);
|
|
|
|
proto_tree_add_text(tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
offset + offsetof(struct icmp6_router_renum, rr_seqnum), 4,
|
|
|
|
"Sequence number: 0x%08x", pntohl(&rr->rr_seqnum));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
offset + offsetof(struct icmp6_router_renum, rr_segnum), 1,
|
|
|
|
"Segment number: 0x%02x", rr->rr_segnum);
|
|
|
|
|
|
|
|
flagoff = offset + offsetof(struct icmp6_router_renum, rr_flags);
|
2001-04-23 03:37:31 +00:00
|
|
|
flags = tvb_get_guint8(tvb, flagoff);
|
|
|
|
tf = proto_tree_add_text(tree, tvb, flagoff, 1,
|
|
|
|
"Flags: 0x%02x", flags);
|
2000-11-09 16:39:59 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags, 0x80, 8,
|
2000-11-09 16:39:59 +00:00
|
|
|
"Test command", "Not test command"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags, 0x40, 8,
|
2000-11-09 16:39:59 +00:00
|
|
|
"Result requested", "Result not requested"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags, 0x20, 8,
|
2000-11-09 16:39:59 +00:00
|
|
|
"All interfaces", "Not all interfaces"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags, 0x10, 8,
|
2000-11-09 16:39:59 +00:00
|
|
|
"Site specific", "Not site specific"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags, 0x08, 8,
|
2000-11-09 16:39:59 +00:00
|
|
|
"Processed previously", "Complete result"));
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
offset + offsetof(struct icmp6_router_renum, rr_maxdelay), 2,
|
|
|
|
"Max delay: 0x%04x", pntohs(&rr->rr_maxdelay));
|
2001-11-25 22:51:14 +00:00
|
|
|
call_dissector(data_handle,tvb_new_subset(tvb, offset + sizeof(*rr), -1, -1), pinfo, tree); /*XXX*/
|
2000-11-09 16:39:59 +00:00
|
|
|
|
|
|
|
if (rr->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
|
|
|
|
off = offset + sizeof(*rr);
|
2001-04-23 03:37:31 +00:00
|
|
|
match = &rr_pco_match;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)match, off, sizeof *match);
|
|
|
|
tf = proto_tree_add_text(tree, tvb, off, sizeof(*match),
|
2000-11-09 16:39:59 +00:00
|
|
|
"Match-Prefix: %s/%u (%u-%u)", ip6_to_str(&match->rpm_prefix),
|
|
|
|
match->rpm_matchlen, match->rpm_minlen, match->rpm_maxlen);
|
|
|
|
opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_code),
|
2000-11-09 21:57:35 +00:00
|
|
|
sizeof(match->rpm_code), "OpCode: %s (%u)",
|
2002-08-28 21:04:11 +00:00
|
|
|
val_to_str(match->rpm_code, names_rrenum_matchcode, "Unknown"),
|
2000-11-09 16:39:59 +00:00
|
|
|
match->rpm_code);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_len),
|
|
|
|
sizeof(match->rpm_len), "OpLength: %u (%u octets)",
|
|
|
|
match->rpm_len, match->rpm_len * 8);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_ordinal),
|
|
|
|
sizeof(match->rpm_ordinal), "Ordinal: %u", match->rpm_ordinal);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_matchlen),
|
|
|
|
sizeof(match->rpm_matchlen), "MatchLen: %u", match->rpm_matchlen);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_minlen),
|
|
|
|
sizeof(match->rpm_minlen), "MinLen: %u", match->rpm_minlen);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_maxlen),
|
|
|
|
sizeof(match->rpm_maxlen), "MaxLen: %u", match->rpm_maxlen);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_match, rpm_prefix),
|
|
|
|
sizeof(match->rpm_prefix), "MatchPrefix: %s",
|
|
|
|
ip6_to_str(&match->rpm_prefix));
|
|
|
|
|
|
|
|
off += sizeof(*match);
|
2001-04-23 03:37:31 +00:00
|
|
|
use = &rr_pco_use;
|
2000-11-09 16:39:59 +00:00
|
|
|
for (l = match->rpm_len * 8 - sizeof(*match);
|
|
|
|
l >= sizeof(*use); l -= sizeof(*use), off += sizeof(*use)) {
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)use, off, sizeof *use);
|
|
|
|
tf = proto_tree_add_text(tree, tvb, off, sizeof(*use),
|
2000-11-09 16:39:59 +00:00
|
|
|
"Use-Prefix: %s/%u (keep %u)", ip6_to_str(&use->rpu_prefix),
|
|
|
|
use->rpu_uselen, use->rpu_keeplen);
|
|
|
|
opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_uselen),
|
|
|
|
sizeof(use->rpu_uselen), "UseLen: %u", use->rpu_uselen);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_keeplen),
|
|
|
|
sizeof(use->rpu_keeplen), "KeepLen: %u", use->rpu_keeplen);
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
flagoff = off + offsetof(struct rr_pco_use, rpu_ramask),
|
|
|
|
sizeof(use->rpu_ramask), "FlagMask: 0x%x", use->rpu_ramask);
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2001-04-23 03:37:31 +00:00
|
|
|
flags = tvb_get_guint8(tvb, flagoff);
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags,
|
2000-11-09 16:39:59 +00:00
|
|
|
ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
|
|
|
|
"Onlink", "Not onlink"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags,
|
2000-11-09 16:39:59 +00:00
|
|
|
ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8,
|
|
|
|
"Auto", "Not auto"));
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
flagoff = off + offsetof(struct rr_pco_use, rpu_raflags),
|
|
|
|
sizeof(use->rpu_raflags), "RAFlags: 0x%x", use->rpu_raflags);
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2001-04-23 03:37:31 +00:00
|
|
|
flags = tvb_get_guint8(tvb, flagoff);
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags,
|
2000-11-09 16:39:59 +00:00
|
|
|
ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
|
|
|
|
"Onlink", "Not onlink"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(flags,
|
2000-11-09 16:39:59 +00:00
|
|
|
ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8, "Auto", "Not auto"));
|
|
|
|
if (pntohl(&use->rpu_vltime) == 0xffffffff)
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_vltime),
|
|
|
|
sizeof(use->rpu_vltime), "Valid Lifetime: infinity");
|
|
|
|
else
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_vltime),
|
|
|
|
sizeof(use->rpu_vltime), "Valid Lifetime: %u",
|
|
|
|
pntohl(&use->rpu_vltime));
|
|
|
|
if (pntohl(&use->rpu_pltime) == 0xffffffff)
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_pltime),
|
|
|
|
sizeof(use->rpu_pltime), "Preferred Lifetime: infinity");
|
|
|
|
else
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_pltime),
|
|
|
|
sizeof(use->rpu_pltime), "Preferred Lifetime: %u",
|
|
|
|
pntohl(&use->rpu_pltime));
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
flagoff = off + offsetof(struct rr_pco_use, rpu_flags),
|
|
|
|
sizeof(use->rpu_flags), "Flags: 0x%08x",
|
|
|
|
pntohl(&use->rpu_flags));
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2001-04-23 03:37:31 +00:00
|
|
|
flags = tvb_get_guint8(tvb, flagoff);
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
|
|
|
|
decode_boolean_bitfield(flags,
|
2000-11-09 16:39:59 +00:00
|
|
|
ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, 32,
|
|
|
|
"Decrement valid lifetime", "No decrement valid lifetime"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
|
|
|
|
decode_boolean_bitfield(flags,
|
2000-11-09 16:39:59 +00:00
|
|
|
ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, 32,
|
|
|
|
"Decrement preferred lifetime",
|
|
|
|
"No decrement preferred lifetime"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(opt_tree, tvb,
|
2000-11-09 16:39:59 +00:00
|
|
|
off + offsetof(struct rr_pco_use, rpu_prefix),
|
|
|
|
sizeof(use->rpu_prefix), "UsePrefix: %s",
|
|
|
|
ip6_to_str(&use->rpu_prefix));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-19 23:20:53 +00:00
|
|
|
/*
|
2004-04-22 08:22:07 +00:00
|
|
|
* See I-D draft-vida-mld-v2-08
|
2003-12-19 23:20:53 +00:00
|
|
|
*/
|
|
|
|
static const value_string mldrv2ModesNames[] = {
|
|
|
|
{ 1, "Include" },
|
|
|
|
{ 2, "Exclude" },
|
|
|
|
{ 3, "Changed to include" },
|
|
|
|
{ 4, "Changed to exclude" },
|
|
|
|
{ 5, "Allow new sources" },
|
|
|
|
{ 6, "Block old sources" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
dissect_mldrv2( tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree )
|
|
|
|
{
|
|
|
|
proto_tree *sub_tree;
|
|
|
|
proto_item *tf;
|
|
|
|
|
|
|
|
guint8 recordType, auxDataLen;
|
|
|
|
guint32 sourceNb, recordSize, localOffset;
|
|
|
|
struct e_in6_addr addr;
|
|
|
|
|
|
|
|
for( ; count; count--, offset += recordSize ) {
|
|
|
|
localOffset = offset;
|
|
|
|
recordType = tvb_get_guint8( tvb, localOffset );
|
|
|
|
localOffset += 1;
|
|
|
|
auxDataLen = tvb_get_guint8( tvb, localOffset );
|
|
|
|
localOffset += 1;
|
|
|
|
sourceNb = tvb_get_ntohs( tvb, localOffset );
|
|
|
|
localOffset += 2;
|
|
|
|
recordSize = 4 + 16 + (16 * sourceNb) + (auxDataLen * 4);
|
|
|
|
|
2005-09-11 21:25:37 +00:00
|
|
|
tvb_get_ipv6(tvb, localOffset, &addr);
|
2007-07-30 17:21:40 +00:00
|
|
|
tf = proto_tree_add_text( tree, tvb, offset, recordSize,
|
2003-12-19 23:20:53 +00:00
|
|
|
#ifdef INET6
|
|
|
|
"%s: %s (%s)", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
|
2007-07-30 17:21:40 +00:00
|
|
|
get_hostname6(&addr), ip6_to_str(&addr)
|
2003-12-19 23:20:53 +00:00
|
|
|
#else
|
|
|
|
"%s: %s", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
|
2007-07-30 17:21:40 +00:00
|
|
|
ip6_to_str(&addr)
|
2003-12-19 23:20:53 +00:00
|
|
|
#endif
|
|
|
|
);
|
|
|
|
sub_tree = proto_item_add_subtree(tf, ett_multicastRR);
|
|
|
|
|
2007-07-30 17:21:40 +00:00
|
|
|
proto_tree_add_text( sub_tree, tvb, offset, 1, "Mode: %s",
|
2003-12-19 23:20:53 +00:00
|
|
|
val_to_str(recordType, mldrv2ModesNames,"Unknown mode") );
|
|
|
|
proto_tree_add_text( sub_tree, tvb, offset+1, 1, "Aux data len: %u", auxDataLen * 4);
|
|
|
|
proto_tree_add_text( sub_tree, tvb, localOffset, 16, "Multicast Address: %s", ip6_to_str(&addr) );
|
|
|
|
localOffset += 16;
|
|
|
|
|
|
|
|
for( ; sourceNb; sourceNb--, localOffset += 16 ) {
|
2005-09-11 21:25:37 +00:00
|
|
|
tvb_get_ipv6(tvb, localOffset, &addr);
|
2007-07-30 17:21:40 +00:00
|
|
|
proto_tree_add_text( sub_tree, tvb, localOffset, 16,
|
2003-12-19 23:20:53 +00:00
|
|
|
#ifdef INET6
|
|
|
|
"Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr) );
|
|
|
|
#else
|
|
|
|
"Source Address: %s", ip6_to_str(&addr) );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-22 08:22:07 +00:00
|
|
|
static void
|
|
|
|
dissect_mldqv2(tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree)
|
|
|
|
{
|
|
|
|
struct e_in6_addr addr;
|
|
|
|
|
|
|
|
for ( ; count; count--, offset += 16) {
|
2005-09-11 21:25:37 +00:00
|
|
|
tvb_get_ipv6(tvb, offset, &addr);
|
2007-07-30 17:21:40 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, 16,
|
2004-04-22 08:22:07 +00:00
|
|
|
"Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-04-20 07:05:58 +00:00
|
|
|
static void
|
2001-04-23 03:37:31 +00:00
|
|
|
dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
1999-03-29 02:21:34 +00:00
|
|
|
{
|
|
|
|
proto_tree *icmp6_tree, *field_tree;
|
2008-05-14 01:47:41 +00:00
|
|
|
proto_item *ti, *hidden_item, *tf = NULL;
|
2001-04-23 03:37:31 +00:00
|
|
|
struct icmp6_hdr icmp6_hdr, *dp;
|
2000-08-18 12:05:27 +00:00
|
|
|
struct icmp6_nodeinfo *ni = NULL;
|
2005-06-26 19:56:52 +00:00
|
|
|
const char *codename, *typename;
|
|
|
|
const char *colcodename, *coltypename;
|
1999-03-29 02:21:34 +00:00
|
|
|
int len;
|
2000-12-14 21:45:12 +00:00
|
|
|
guint length, reported_length;
|
|
|
|
vec_t cksum_vec[4];
|
|
|
|
guint32 phdr[2];
|
|
|
|
guint16 cksum, computed_cksum;
|
2001-04-23 03:37:31 +00:00
|
|
|
int offset;
|
|
|
|
tvbuff_t *next_tvb;
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMPv6");
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2001-05-27 04:14:53 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
offset = 0;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&icmp6_hdr, offset, sizeof icmp6_hdr);
|
|
|
|
dp = &icmp6_hdr;
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = typename = colcodename = coltypename = "Unknown";
|
1999-03-29 02:21:34 +00:00
|
|
|
len = sizeof(*dp);
|
|
|
|
switch (dp->icmp6_type) {
|
|
|
|
case ICMP6_DST_UNREACH:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Unreachable";
|
1999-03-29 02:21:34 +00:00
|
|
|
switch (dp->icmp6_code) {
|
|
|
|
case ICMP6_DST_UNREACH_NOROUTE:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Route unreachable";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_DST_UNREACH_ADMIN:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Administratively prohibited";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_DST_UNREACH_NOTNEIGHBOR:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Not a neighbor";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_DST_UNREACH_ADDR:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Address unreachable";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_DST_UNREACH_NOPORT:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Port unreachable";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ICMP6_PACKET_TOO_BIG:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Too big";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_TIME_EXCEEDED:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Time exceeded";
|
1999-03-29 02:21:34 +00:00
|
|
|
switch (dp->icmp6_code) {
|
|
|
|
case ICMP6_TIME_EXCEED_TRANSIT:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "In-transit";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_TIME_EXCEED_REASSEMBLY:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Reassembly";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-07-28 02:32:25 +00:00
|
|
|
break;
|
1999-03-29 02:21:34 +00:00
|
|
|
case ICMP6_PARAM_PROB:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Parameter problem";
|
1999-03-29 02:21:34 +00:00
|
|
|
switch (dp->icmp6_code) {
|
|
|
|
case ICMP6_PARAMPROB_HEADER:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Header";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_PARAMPROB_NEXTHEADER:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Next header";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_PARAMPROB_OPTION:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Option";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-07-28 02:32:25 +00:00
|
|
|
break;
|
1999-03-29 02:21:34 +00:00
|
|
|
case ICMP6_ECHO_REQUEST:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Echo request";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_ECHO_REPLY:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Echo reply";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_MEMBERSHIP_QUERY:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Multicast listener query";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_MEMBERSHIP_REPORT:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Multicast listener report";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_MEMBERSHIP_REDUCTION:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Multicast listener done";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ND_ROUTER_SOLICIT:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Router solicitation";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
len = sizeof(struct nd_router_solicit);
|
|
|
|
break;
|
|
|
|
case ND_ROUTER_ADVERT:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Router advertisement";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
len = sizeof(struct nd_router_advert);
|
|
|
|
break;
|
|
|
|
case ND_NEIGHBOR_SOLICIT:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Neighbor solicitation";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
len = sizeof(struct nd_neighbor_solicit);
|
|
|
|
break;
|
|
|
|
case ND_NEIGHBOR_ADVERT:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Neighbor advertisement";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
len = sizeof(struct nd_neighbor_advert);
|
|
|
|
break;
|
|
|
|
case ND_REDIRECT:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Redirect";
|
|
|
|
codename = colcodename = NULL;
|
1999-03-29 02:21:34 +00:00
|
|
|
len = sizeof(struct nd_redirect);
|
|
|
|
break;
|
|
|
|
case ICMP6_ROUTER_RENUMBERING:
|
2000-08-18 12:05:27 +00:00
|
|
|
typename = coltypename = "Router renumbering";
|
1999-03-29 02:21:34 +00:00
|
|
|
switch (dp->icmp6_code) {
|
|
|
|
case ICMP6_ROUTER_RENUMBERING_COMMAND:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Command";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_ROUTER_RENUMBERING_RESULT:
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = colcodename = "Result";
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
2000-11-09 16:39:59 +00:00
|
|
|
case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
|
|
|
|
codename = colcodename = "Sequence number reset";
|
|
|
|
break;
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
|
|
|
len = sizeof(struct icmp6_router_renum);
|
|
|
|
break;
|
2000-08-18 12:05:27 +00:00
|
|
|
case ICMP6_NI_QUERY:
|
|
|
|
case ICMP6_NI_REPLY:
|
|
|
|
ni = (struct icmp6_nodeinfo *)dp;
|
|
|
|
if (ni->ni_type == ICMP6_NI_QUERY) {
|
|
|
|
typename = coltypename = "Node information query";
|
|
|
|
switch (ni->ni_code) {
|
|
|
|
case ICMP6_NI_SUBJ_IPV6:
|
|
|
|
codename = "Query subject = IPv6 addresses";
|
|
|
|
break;
|
|
|
|
case ICMP6_NI_SUBJ_FQDN:
|
2001-04-23 03:37:31 +00:00
|
|
|
if (tvb_bytes_exist(tvb, offset, sizeof(*ni)))
|
2000-08-18 12:05:27 +00:00
|
|
|
codename = "Query subject = DNS name";
|
|
|
|
else
|
|
|
|
codename = "Query subject = empty";
|
|
|
|
break;
|
|
|
|
case ICMP6_NI_SUBJ_IPV4:
|
|
|
|
codename = "Query subject = IPv4 addresses";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
typename = coltypename = "Node information reply";
|
|
|
|
switch (ni->ni_code) {
|
|
|
|
case ICMP6_NI_SUCCESS:
|
|
|
|
codename = "Successful";
|
|
|
|
break;
|
|
|
|
case ICMP6_NI_REFUSED:
|
|
|
|
codename = "Refused";
|
|
|
|
break;
|
|
|
|
case ICMP6_NI_UNKNOWN:
|
|
|
|
codename = "Unknown query type";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
colcodename = val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
|
|
|
|
"Unknown");
|
|
|
|
len = sizeof(struct icmp6_nodeinfo);
|
|
|
|
break;
|
2003-02-04 20:17:01 +00:00
|
|
|
case ICMP6_MIP6_DHAAD_REQUEST:
|
|
|
|
typename = coltypename = "Dynamic Home Agent Address Discovery Request";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case ICMP6_MIP6_DHAAD_REPLY:
|
|
|
|
typename = coltypename = "Dynamic Home Agent Address Discovery Reply";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case ICMP6_MIP6_MPS:
|
|
|
|
typename = coltypename = "Mobile Prefix Solicitation";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case ICMP6_MIP6_MPA:
|
|
|
|
typename = coltypename = "Mobile Prefix Advertisement";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
2008-02-23 19:57:09 +00:00
|
|
|
case ICMP6_CERT_PATH_SOL:
|
|
|
|
typename = coltypename = "Certification Path Solicitation";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case ICMP6_CERT_PATH_AD:
|
|
|
|
typename = coltypename = "Certification Path Advertisement";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
2003-12-19 23:20:53 +00:00
|
|
|
case ICMP6_MLDV2_REPORT:
|
|
|
|
typename = coltypename = "Multicast Listener Report Message v2";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
2005-10-25 06:00:53 +00:00
|
|
|
case ICMP6_EXPERIMENTAL_MOBILITY:
|
|
|
|
typename = coltypename ="Experimental Mobility";
|
|
|
|
switch (dp->icmp6_data8[0]) {
|
|
|
|
case FMIP6_SUBTYPE_RTSOLPR:
|
|
|
|
typename = coltypename ="RtSolPr (ICMPv6 Experimental Mobility)";
|
|
|
|
codename = "Should always be zero";
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case FMIP6_SUBTYPE_PRRTADV:
|
|
|
|
typename = coltypename ="PrRtAdv (ICMPv6 Experimental Mobility)";
|
|
|
|
codename = val_to_str(dp->icmp6_code, names_fmip6_prrtadv_code, "Unknown");
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case FMIP6_SUBTYPE_HI:
|
|
|
|
typename = coltypename ="HI (ICMPv6 Experimental Mobility)";
|
|
|
|
codename = val_to_str(dp->icmp6_code, names_fmip6_hi_code, "Unknown");
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
case FMIP6_SUBTYPE_HACK:
|
|
|
|
typename = coltypename ="HAck (ICMPv6 Experimental Mobility)";
|
|
|
|
codename = val_to_str(dp->icmp6_code, names_fmip6_hack_code, "Unknown");
|
|
|
|
colcodename = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
1999-03-29 02:21:34 +00:00
|
|
|
char typebuf[256], codebuf[256];
|
|
|
|
|
2000-08-18 12:05:27 +00:00
|
|
|
if (coltypename && strcmp(coltypename, "Unknown") == 0) {
|
2005-08-17 23:10:28 +00:00
|
|
|
g_snprintf(typebuf, sizeof(typebuf), "Unknown (0x%02x)",
|
1999-03-29 02:21:34 +00:00
|
|
|
dp->icmp6_type);
|
2000-08-18 12:05:27 +00:00
|
|
|
coltypename = typebuf;
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
2000-08-18 12:05:27 +00:00
|
|
|
if (colcodename && strcmp(colcodename, "Unknown") == 0) {
|
2005-08-17 23:10:28 +00:00
|
|
|
g_snprintf(codebuf, sizeof(codebuf), "Unknown (0x%02x)",
|
1999-03-29 02:21:34 +00:00
|
|
|
dp->icmp6_code);
|
2000-08-18 12:05:27 +00:00
|
|
|
colcodename = codebuf;
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
2000-08-18 12:05:27 +00:00
|
|
|
if (colcodename) {
|
2001-12-10 00:26:21 +00:00
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", coltypename, colcodename);
|
1999-03-29 02:21:34 +00:00
|
|
|
} else {
|
2007-10-23 05:50:00 +00:00
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, coltypename);
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tree) {
|
|
|
|
/* !!! specify length */
|
2004-10-31 23:36:21 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_icmpv6, tvb, offset, -1, FALSE);
|
1999-11-16 11:44:20 +00:00
|
|
|
icmp6_tree = proto_item_add_subtree(ti, ett_icmpv6);
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_type, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_type), 1,
|
1999-10-10 16:09:33 +00:00
|
|
|
dp->icmp6_type,
|
2001-04-23 03:37:31 +00:00
|
|
|
"Type: %u (%s)", dp->icmp6_type, typename);
|
1999-03-29 02:21:34 +00:00
|
|
|
if (codename) {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
|
1999-10-10 16:09:33 +00:00
|
|
|
dp->icmp6_code,
|
2001-04-23 03:37:31 +00:00
|
|
|
"Code: %u (%s)", dp->icmp6_code, codename);
|
2000-08-18 12:05:27 +00:00
|
|
|
} else {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
|
|
|
|
dp->icmp6_code,
|
2001-04-23 03:37:31 +00:00
|
|
|
"Code: %u", dp->icmp6_code);
|
1999-03-29 02:21:34 +00:00
|
|
|
}
|
2002-08-02 23:36:07 +00:00
|
|
|
cksum = (guint16)g_htons(dp->icmp6_cksum);
|
2001-04-23 03:37:31 +00:00
|
|
|
length = tvb_length(tvb);
|
|
|
|
reported_length = tvb_reported_length(tvb);
|
|
|
|
if (!pinfo->fragmented && length >= reported_length) {
|
2000-12-14 21:45:12 +00:00
|
|
|
/* The packet isn't part of a fragmented datagram and isn't
|
|
|
|
truncated, so we can checksum it. */
|
|
|
|
|
|
|
|
/* Set up the fields of the pseudo-header. */
|
2001-04-23 03:37:31 +00:00
|
|
|
cksum_vec[0].ptr = pinfo->src.data;
|
|
|
|
cksum_vec[0].len = pinfo->src.len;
|
|
|
|
cksum_vec[1].ptr = pinfo->dst.data;
|
|
|
|
cksum_vec[1].len = pinfo->dst.len;
|
2000-12-14 21:45:12 +00:00
|
|
|
cksum_vec[2].ptr = (const guint8 *)&phdr;
|
2002-08-02 23:36:07 +00:00
|
|
|
phdr[0] = g_htonl(tvb_reported_length(tvb));
|
|
|
|
phdr[1] = g_htonl(IP_PROTO_ICMPV6);
|
2000-12-14 21:45:12 +00:00
|
|
|
cksum_vec[2].len = 8;
|
2001-04-23 03:37:31 +00:00
|
|
|
cksum_vec[3].len = tvb_reported_length(tvb);
|
|
|
|
cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, cksum_vec[3].len);
|
2000-12-14 21:45:12 +00:00
|
|
|
computed_cksum = in_cksum(cksum_vec, 4);
|
|
|
|
if (computed_cksum == 0) {
|
|
|
|
proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb,
|
2000-12-14 21:45:12 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
|
|
|
|
cksum,
|
2005-07-08 22:11:13 +00:00
|
|
|
"Checksum: 0x%04x [correct]", cksum);
|
2000-12-14 21:45:12 +00:00
|
|
|
} else {
|
2008-05-14 01:47:41 +00:00
|
|
|
hidden_item = proto_tree_add_boolean(icmp6_tree, hf_icmpv6_checksum_bad,
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb,
|
2001-02-28 19:33:49 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
|
|
|
|
TRUE);
|
2008-05-14 01:47:41 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(hidden_item);
|
2000-12-14 21:45:12 +00:00
|
|
|
proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb,
|
2000-12-14 21:45:12 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
|
|
|
|
cksum,
|
2005-07-08 22:11:13 +00:00
|
|
|
"Checksum: 0x%04x [incorrect, should be 0x%04x]",
|
2000-12-14 21:45:12 +00:00
|
|
|
cksum, in_cksum_shouldbe(cksum, computed_cksum));
|
|
|
|
}
|
|
|
|
} else {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint(icmp6_tree, hf_icmpv6_checksum, tvb,
|
2000-12-14 21:45:12 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
|
|
|
|
cksum);
|
|
|
|
}
|
1999-03-29 02:21:34 +00:00
|
|
|
|
|
|
|
/* decode... */
|
|
|
|
switch (dp->icmp6_type) {
|
|
|
|
case ICMP6_DST_UNREACH:
|
|
|
|
case ICMP6_TIME_EXCEEDED:
|
2001-05-27 04:14:53 +00:00
|
|
|
dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
|
|
|
|
icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_PACKET_TOO_BIG:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_mtu), 4,
|
2001-04-23 03:37:31 +00:00
|
|
|
"MTU: %u", pntohl(&dp->icmp6_mtu));
|
2001-05-27 04:14:53 +00:00
|
|
|
dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
|
|
|
|
icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_PARAM_PROB:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_pptr), 4,
|
|
|
|
"Problem pointer: 0x%04x", pntohl(&dp->icmp6_pptr));
|
2001-05-27 04:14:53 +00:00
|
|
|
dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
|
|
|
|
icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_ECHO_REQUEST:
|
|
|
|
case ICMP6_ECHO_REPLY:
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_id), 2,
|
2002-08-02 23:36:07 +00:00
|
|
|
"ID: 0x%04x", (guint16)g_ntohs(dp->icmp6_id));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_seq), 2,
|
2002-08-02 23:36:07 +00:00
|
|
|
"Sequence: 0x%04x", (guint16)g_ntohs(dp->icmp6_seq));
|
2001-05-27 04:14:53 +00:00
|
|
|
next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
|
2001-11-25 22:51:14 +00:00
|
|
|
call_dissector(data_handle,next_tvb, pinfo, icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_MEMBERSHIP_QUERY:
|
|
|
|
case ICMP6_MEMBERSHIP_REPORT:
|
|
|
|
case ICMP6_MEMBERSHIP_REDUCTION:
|
2004-04-22 08:22:07 +00:00
|
|
|
#define MLDV2_MINLEN 28
|
|
|
|
#define MLDV1_MINLEN 24
|
|
|
|
if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) {
|
|
|
|
if (length >= MLDV2_MINLEN) {
|
|
|
|
guint32 mrc;
|
|
|
|
guint16 qqi;
|
|
|
|
guint8 flag;
|
|
|
|
guint16 nsrcs;
|
2007-07-30 17:21:40 +00:00
|
|
|
|
2004-04-22 08:22:07 +00:00
|
|
|
mrc = g_ntohs(dp->icmp6_maxdelay);
|
|
|
|
flag = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16);
|
|
|
|
qqi = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16 + 1);
|
|
|
|
nsrcs = tvb_get_ntohs(tvb, offset + sizeof(*dp) + 16 + 2);
|
|
|
|
|
|
|
|
if (mrc >= 32768)
|
2007-07-30 17:21:40 +00:00
|
|
|
mrc = ((mrc & 0x0fff) | 0x1000) <<
|
2004-04-22 08:22:07 +00:00
|
|
|
(((mrc & 0x7000) >> 12) + 3);
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
|
|
|
|
"Maximum response delay[ms]: %u", mrc);
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp),
|
|
|
|
16, "Multicast Address: %s",
|
|
|
|
ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb,
|
|
|
|
offset + sizeof *dp, sizeof (struct e_in6_addr)))));
|
|
|
|
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + sizeof(*dp) + 16, 1, "S Flag: %s",
|
|
|
|
flag & 0x08 ? "ON" : "OFF");
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + sizeof(*dp) + 16, 1, "Robustness: %d",
|
|
|
|
flag & 0x07);
|
|
|
|
if (qqi >= 128)
|
|
|
|
qqi = ((qqi & 0x0f) | 0x10) << (((qqi & 0x70) >> 4) + 3);
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + sizeof(*dp) + 17, 1, "QQI: %d", qqi);
|
|
|
|
|
|
|
|
dissect_mldqv2(tvb, offset + sizeof(*dp) + 20, nsrcs,
|
|
|
|
icmp6_tree);
|
|
|
|
break;
|
|
|
|
} else if (length > MLDV1_MINLEN) {
|
|
|
|
next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
|
|
|
|
call_dissector(data_handle,next_tvb, pinfo, tree);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* MLDv1 Query -> FALLTHOUGH */
|
|
|
|
}
|
|
|
|
#undef MLDV2_MINLEN
|
|
|
|
#undef MLDV1_MINLEN
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
|
2001-04-23 03:37:31 +00:00
|
|
|
"Maximum response delay: %u",
|
2002-08-02 23:36:07 +00:00
|
|
|
(guint16)g_ntohs(dp->icmp6_maxdelay));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp), 16,
|
1999-03-29 02:21:34 +00:00
|
|
|
"Multicast Address: %s",
|
2002-12-02 23:43:30 +00:00
|
|
|
ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb, offset + sizeof *dp, sizeof (struct e_in6_addr)))));
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
case ND_ROUTER_SOLICIT:
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
2003-12-19 23:20:53 +00:00
|
|
|
case ICMP6_MLDV2_REPORT: {
|
|
|
|
guint16 nbRecords;
|
2007-07-30 17:21:40 +00:00
|
|
|
|
2003-12-19 23:20:53 +00:00
|
|
|
nbRecords = tvb_get_ntohs( tvb, offset+4+2 );
|
|
|
|
dissect_mldrv2( tvb, offset+4+2+2, nbRecords, icmp6_tree );
|
|
|
|
break;
|
|
|
|
}
|
1999-03-29 02:21:34 +00:00
|
|
|
case ND_ROUTER_ADVERT:
|
|
|
|
{
|
2001-04-23 03:37:31 +00:00
|
|
|
struct nd_router_advert nd_router_advert, *ra;
|
1999-03-29 02:21:34 +00:00
|
|
|
int flagoff;
|
|
|
|
guint32 ra_flags;
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
ra = &nd_router_advert;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)ra, offset, sizeof *ra);
|
2006-10-30 15:36:40 +00:00
|
|
|
|
|
|
|
/* Current hop limit */
|
|
|
|
proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_cur_hop_limit, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_router_advert, nd_ra_curhoplimit),
|
2006-10-30 15:36:40 +00:00
|
|
|
1, ra->nd_ra_curhoplimit);
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2006-10-30 15:36:40 +00:00
|
|
|
/* Flags */
|
1999-03-29 02:21:34 +00:00
|
|
|
flagoff = offset + offsetof(struct nd_router_advert, nd_ra_flags_reserved);
|
2001-04-23 03:37:31 +00:00
|
|
|
ra_flags = tvb_get_guint8(tvb, flagoff);
|
|
|
|
tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", ra_flags);
|
1999-11-16 11:44:20 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2006-10-30 15:36:40 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(ra_flags,
|
2001-06-01 23:53:49 +00:00
|
|
|
ND_RA_FLAG_MANAGED, 8, "Managed", "Not managed"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(ra_flags,
|
2001-06-01 23:53:49 +00:00
|
|
|
ND_RA_FLAG_OTHER, 8, "Other", "Not other"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
2001-01-23 02:49:55 +00:00
|
|
|
decode_boolean_bitfield(ra_flags,
|
2001-06-01 23:53:49 +00:00
|
|
|
ND_RA_FLAG_HOME_AGENT, 8,
|
2002-08-28 21:04:11 +00:00
|
|
|
"Home Agent", "Not Home Agent"));
|
2001-06-01 23:53:49 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_enumerated_bitfield(ra_flags, ND_RA_FLAG_RTPREF_MASK, 8,
|
|
|
|
names_router_pref, "Router preference: %s"));
|
2006-10-30 15:36:40 +00:00
|
|
|
|
|
|
|
/* Router lifetime */
|
|
|
|
proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_router_lifetime, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_router_advert, nd_ra_router_lifetime),
|
2006-10-30 15:36:40 +00:00
|
|
|
2, (guint16)g_ntohs(ra->nd_ra_router_lifetime));
|
|
|
|
|
|
|
|
/* Reachable time */
|
|
|
|
proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_reachable_time, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_router_advert, nd_ra_reachable), 4,
|
2006-10-30 15:36:40 +00:00
|
|
|
pntohl(&ra->nd_ra_reachable));
|
|
|
|
|
|
|
|
/* Retrans timer */
|
|
|
|
proto_tree_add_uint(icmp6_tree, hf_icmpv6_ra_retrans_timer, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_router_advert, nd_ra_retransmit), 4,
|
2006-10-30 15:36:40 +00:00
|
|
|
pntohl(&ra->nd_ra_retransmit));
|
|
|
|
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ND_NEIGHBOR_SOLICIT:
|
|
|
|
{
|
2001-04-23 03:37:31 +00:00
|
|
|
struct nd_neighbor_solicit nd_neighbor_solicit, *ns;
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
ns = &nd_neighbor_solicit;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)ns, offset, sizeof *ns);
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_neighbor_solicit, nd_ns_target), 16,
|
|
|
|
#ifdef INET6
|
|
|
|
"Target: %s (%s)",
|
|
|
|
get_hostname6(&ns->nd_ns_target),
|
|
|
|
#else
|
|
|
|
"Target: %s",
|
|
|
|
#endif
|
|
|
|
ip6_to_str(&ns->nd_ns_target));
|
|
|
|
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ND_NEIGHBOR_ADVERT:
|
|
|
|
{
|
|
|
|
int flagoff, targetoff;
|
|
|
|
guint32 na_flags;
|
2001-04-23 03:37:31 +00:00
|
|
|
struct e_in6_addr na_target;
|
1999-03-29 02:21:34 +00:00
|
|
|
|
|
|
|
flagoff = offset + offsetof(struct nd_neighbor_advert, nd_na_flags_reserved);
|
2001-04-23 03:37:31 +00:00
|
|
|
na_flags = tvb_get_ntohl(tvb, flagoff);
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 4, "Flags: 0x%08x", na_flags);
|
1999-11-16 11:44:20 +00:00
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(na_flags,
|
2000-11-11 10:23:43 +00:00
|
|
|
ND_NA_FLAG_ROUTER, 32, "Router", "Not router"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(na_flags,
|
2000-11-11 10:23:43 +00:00
|
|
|
ND_NA_FLAG_SOLICITED, 32, "Solicited", "Not adverted"));
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
|
1999-03-29 02:21:34 +00:00
|
|
|
decode_boolean_bitfield(na_flags,
|
2000-11-11 10:23:43 +00:00
|
|
|
ND_NA_FLAG_OVERRIDE, 32, "Override", "Not override"));
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
targetoff = offset + offsetof(struct nd_neighbor_advert, nd_na_target);
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&na_target, targetoff, sizeof na_target);
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb, targetoff, 16,
|
1999-03-29 02:21:34 +00:00
|
|
|
#ifdef INET6
|
|
|
|
"Target: %s (%s)",
|
2001-04-23 03:37:31 +00:00
|
|
|
get_hostname6(&na_target),
|
1999-03-29 02:21:34 +00:00
|
|
|
#else
|
|
|
|
"Target: %s",
|
|
|
|
#endif
|
2001-04-23 03:37:31 +00:00
|
|
|
ip6_to_str(&na_target));
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ND_REDIRECT:
|
|
|
|
{
|
2001-04-23 03:37:31 +00:00
|
|
|
struct nd_redirect nd_redirect, *rd;
|
1999-03-29 02:21:34 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
rd = &nd_redirect;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)rd, offset, sizeof *rd);
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_redirect, nd_rd_target), 16,
|
|
|
|
#ifdef INET6
|
|
|
|
"Target: %s (%s)",
|
|
|
|
get_hostname6(&rd->nd_rd_target),
|
|
|
|
#else
|
|
|
|
"Target: %s",
|
|
|
|
#endif
|
|
|
|
ip6_to_str(&rd->nd_rd_target));
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
1999-03-29 02:21:34 +00:00
|
|
|
offset + offsetof(struct nd_redirect, nd_rd_dst), 16,
|
|
|
|
#ifdef INET6
|
|
|
|
"Destination: %s (%s)",
|
|
|
|
get_hostname6(&rd->nd_rd_dst),
|
|
|
|
#else
|
|
|
|
"Destination: %s",
|
|
|
|
#endif
|
|
|
|
ip6_to_str(&rd->nd_rd_dst));
|
|
|
|
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ICMP6_ROUTER_RENUMBERING:
|
2001-04-23 03:37:31 +00:00
|
|
|
dissect_rrenum(tvb, offset, pinfo, icmp6_tree);
|
2000-11-09 14:09:41 +00:00
|
|
|
break;
|
2000-08-18 12:05:27 +00:00
|
|
|
case ICMP6_NI_QUERY:
|
|
|
|
case ICMP6_NI_REPLY:
|
|
|
|
ni = (struct icmp6_nodeinfo *)dp;
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
2000-08-18 12:05:27 +00:00
|
|
|
offset + offsetof(struct icmp6_nodeinfo, ni_qtype),
|
|
|
|
sizeof(ni->ni_qtype),
|
|
|
|
"Query type: 0x%04x (%s)", pntohs(&ni->ni_qtype),
|
|
|
|
val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
|
|
|
|
"Unknown"));
|
2001-04-23 03:37:31 +00:00
|
|
|
dissect_nodeinfo(tvb, offset, pinfo, icmp6_tree);
|
2000-08-18 12:05:27 +00:00
|
|
|
break;
|
2003-02-04 20:17:01 +00:00
|
|
|
case ICMP6_MIP6_DHAAD_REQUEST:
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 2, "Identifier: %d (0x%02x)",
|
|
|
|
tvb_get_ntohs(tvb, offset + 4),
|
|
|
|
tvb_get_ntohs(tvb, offset + 4));
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2, "Reserved: %d",
|
|
|
|
tvb_get_ntohs(tvb, offset + 6));
|
|
|
|
break;
|
|
|
|
case ICMP6_MIP6_DHAAD_REPLY:
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 2, "Identifier: %d (0x%02x)",
|
|
|
|
tvb_get_ntohs(tvb, offset + 4),
|
|
|
|
tvb_get_ntohs(tvb, offset + 4));
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2, "Reserved: %d",
|
|
|
|
tvb_get_ntohs(tvb, offset + 6));
|
2004-01-29 03:59:04 +00:00
|
|
|
/* Show all Home Agent Addresses */
|
|
|
|
{
|
|
|
|
int i, suboffset;
|
|
|
|
int ha_num = (length - 8)/16;
|
|
|
|
|
|
|
|
for (i = 0; i < ha_num; i++) {
|
|
|
|
suboffset = 16 * i;
|
|
|
|
proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_haad_ha_addrs,
|
|
|
|
tvb, offset + 8 + suboffset, 16,
|
|
|
|
tvb_get_ptr(tvb, offset + 8 + suboffset, 16));
|
|
|
|
}
|
|
|
|
}
|
2003-02-04 20:17:01 +00:00
|
|
|
break;
|
|
|
|
case ICMP6_MIP6_MPS:
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 2, "Identifier: %d (0x%02x)",
|
|
|
|
tvb_get_ntohs(tvb, offset + 4),
|
|
|
|
tvb_get_ntohs(tvb, offset + 4));
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2, "Reserved: %d",
|
|
|
|
tvb_get_ntohs(tvb, offset + 6));
|
|
|
|
break;
|
|
|
|
case ICMP6_MIP6_MPA:
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 2, "Identifier: %d (0x%02x)",
|
|
|
|
tvb_get_ntohs(tvb, offset + 4),
|
|
|
|
tvb_get_ntohs(tvb, offset + 4));
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
2008-10-31 15:11:57 +00:00
|
|
|
offset + 6, 1, "%s",
|
2003-02-04 20:17:01 +00:00
|
|
|
decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
|
2004-01-29 03:59:04 +00:00
|
|
|
0x80, 8,
|
2003-02-04 20:17:01 +00:00
|
|
|
"Managed Address Configuration",
|
|
|
|
"No Managed Address Configuration"));
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
2008-10-31 15:11:57 +00:00
|
|
|
offset + 6, 1, "%s",
|
2003-02-04 20:17:01 +00:00
|
|
|
decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
|
2004-01-29 03:59:04 +00:00
|
|
|
0x40, 8,
|
2003-02-04 20:17:01 +00:00
|
|
|
"Other Stateful Configuration",
|
|
|
|
"No Other Stateful Configuration"));
|
2004-01-29 03:59:04 +00:00
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 7, 1, "Reserved: %d",
|
|
|
|
tvb_get_guint8(tvb, offset + 7));
|
|
|
|
/* Show all options */
|
2005-10-25 06:00:53 +00:00
|
|
|
dissect_icmpv6ndopt(tvb, offset + 8, pinfo, icmp6_tree);
|
|
|
|
break;
|
2008-02-24 21:04:42 +00:00
|
|
|
case ICMP6_EXPERIMENTAL_MOBILITY:
|
2005-10-25 06:00:53 +00:00
|
|
|
switch (dp->icmp6_data8[0]) {
|
|
|
|
case FMIP6_SUBTYPE_RTSOLPR:
|
|
|
|
{
|
|
|
|
struct fmip6_rtsolpr *rtsolpr;
|
|
|
|
rtsolpr = (struct fmip6_rtsolpr*) dp;
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 1,
|
|
|
|
"Subtype: Router Solicitation for Proxy Advertisement");
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2,
|
|
|
|
"Identifier: %d", pntohs(&rtsolpr->fmip6_rtsolpr_id));
|
2006-03-29 22:04:37 +00:00
|
|
|
dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
|
2005-10-25 06:00:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMIP6_SUBTYPE_PRRTADV:
|
|
|
|
{
|
|
|
|
struct fmip6_prrtadv *prrtadv;
|
|
|
|
prrtadv = (struct fmip6_prrtadv*) dp;
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 1,
|
|
|
|
"Subtype: Proxy Router Advertisement");
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2,
|
|
|
|
"Identifier: %d", pntohs(&prrtadv->fmip6_prrtadv_id));
|
2006-03-29 22:04:37 +00:00
|
|
|
dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
|
2005-10-25 06:00:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMIP6_SUBTYPE_HI:
|
|
|
|
{
|
|
|
|
struct fmip6_hi *hi;
|
|
|
|
int flagoff;
|
|
|
|
guint8 hi_flags;
|
|
|
|
hi = (struct fmip6_hi*) dp;
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 1,
|
|
|
|
"Subtype: Handover Initiate");
|
|
|
|
|
|
|
|
flagoff = offset + offsetof(struct fmip6_hi, fmip6_hi_flags_reserved);
|
|
|
|
hi_flags = tvb_get_guint8(tvb, flagoff);
|
|
|
|
tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", hi_flags);
|
|
|
|
field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(hi_flags,
|
|
|
|
FMIP_HI_FLAG_ASSIGNED, 8, "Assigned", "Not assigned"));
|
|
|
|
proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
|
|
|
|
decode_boolean_bitfield(hi_flags,
|
|
|
|
FMIP_HI_FLAG_BUFFER, 8, "Buffered", "Not buffered"));
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2,
|
|
|
|
"Identifier: %d", pntohs(&hi->fmip6_hi_id));
|
2006-03-29 22:04:37 +00:00
|
|
|
dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
|
2005-10-25 06:00:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FMIP6_SUBTYPE_HACK:
|
|
|
|
{
|
|
|
|
struct fmip6_hack *hack;
|
|
|
|
hack = (struct fmip6_hack*) dp;
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 4, 1,
|
|
|
|
"Subtype: Handover Acknowledge");
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb,
|
|
|
|
offset + 6, 2,
|
|
|
|
"Identifier: %d", pntohs(&hack->fmip6_hack_id));
|
2006-03-29 22:04:37 +00:00
|
|
|
dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), icmp6_tree);
|
2005-10-25 06:00:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-02-04 20:17:01 +00:00
|
|
|
break;
|
2008-11-05 10:59:20 +00:00
|
|
|
case ICMP6_CERT_PATH_SOL:
|
|
|
|
/*RFC 3971 6.4.1. Certification Path Solicitation Message Format */
|
|
|
|
offset += 4;
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb, offset, -1,
|
|
|
|
"Certification Path Solicitation Message");
|
|
|
|
/* Identifier A 16-bit unsigned integer field */
|
|
|
|
proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset,
|
|
|
|
2, FALSE);
|
|
|
|
offset += 2;
|
|
|
|
/* Component A 16-bit unsigned integer field,
|
|
|
|
* 65,535 if the sender seeks to retrieve all certificates.
|
|
|
|
* Otherwise, set to the identifier that the receiver wants.
|
|
|
|
*/
|
|
|
|
proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2,
|
|
|
|
FALSE);
|
|
|
|
offset += 2;
|
|
|
|
dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
|
|
|
|
break;
|
2008-02-24 21:04:42 +00:00
|
|
|
case ICMP6_CERT_PATH_AD:
|
|
|
|
/*RFC 3971 6.4.2. Certification Path Advertisement Message Format */
|
|
|
|
offset = offset +4;
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb, offset, -1,"Certification Path Advertisement Message");
|
2008-03-01 16:23:14 +00:00
|
|
|
|
|
|
|
/* Identifier A 16-bit unsigned integer field */
|
2008-02-24 21:04:42 +00:00
|
|
|
proto_tree_add_item(icmp6_tree, hf_icmpv6_identifier, tvb, offset, 2, FALSE);
|
|
|
|
offset = offset + 2;
|
|
|
|
/* All Components A 16-bit unsigned integer field*/
|
|
|
|
proto_tree_add_item(icmp6_tree, hf_icmpv6_all_comp, tvb, offset, 2, FALSE);
|
|
|
|
offset = offset + 2;
|
|
|
|
|
|
|
|
/* Component A 16-bit unsigned integer field, used to inform the receiver
|
|
|
|
* which certificate is being sent.
|
|
|
|
*/
|
|
|
|
proto_tree_add_item(icmp6_tree, hf_icmpv6_comp, tvb, offset, 2, FALSE);
|
|
|
|
offset = offset + 2;
|
|
|
|
|
|
|
|
/* Reserved */
|
|
|
|
proto_tree_add_text(icmp6_tree, tvb, offset, 2,"Reserved");
|
|
|
|
offset = offset + 2;
|
|
|
|
|
|
|
|
dissect_icmpv6ndopt(tvb, offset, pinfo, icmp6_tree);
|
|
|
|
break;
|
1999-03-29 02:21:34 +00:00
|
|
|
default:
|
2001-05-27 04:14:53 +00:00
|
|
|
next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
|
2001-11-25 22:51:14 +00:00
|
|
|
call_dissector(data_handle,next_tvb, pinfo, tree);
|
1999-03-29 02:21:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-07-29 05:47:07 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_icmpv6(void)
|
|
|
|
{
|
1999-10-10 16:09:33 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_icmpv6_type,
|
2001-04-23 03:37:31 +00:00
|
|
|
{ "Type", "icmpv6.type", FT_UINT8, BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-10 16:09:33 +00:00
|
|
|
{ &hf_icmpv6_code,
|
2001-04-23 03:37:31 +00:00
|
|
|
{ "Code", "icmpv6.code", FT_UINT8, BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-10 16:09:33 +00:00
|
|
|
{ &hf_icmpv6_checksum,
|
1999-10-12 06:21:15 +00:00
|
|
|
{ "Checksum", "icmpv6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2001-02-28 19:33:49 +00:00
|
|
|
{ &hf_icmpv6_checksum_bad,
|
|
|
|
{ "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
2008-11-05 10:59:20 +00:00
|
|
|
"", HFILL }},
|
2004-01-29 03:59:04 +00:00
|
|
|
{ &hf_icmpv6_haad_ha_addrs,
|
2008-11-05 10:59:20 +00:00
|
|
|
{ "Home Agent Addresses", "icmpv6.haad.ha_addrs", FT_IPv6, BASE_HEX, NULL, 0x0,
|
2004-01-29 03:59:04 +00:00
|
|
|
"", HFILL }},
|
2006-10-30 15:36:40 +00:00
|
|
|
{ &hf_icmpv6_ra_cur_hop_limit,
|
|
|
|
{ "Cur hop limit", "icmpv6.ra.cur_hop_limit", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Current hop limit", HFILL }},
|
|
|
|
{ &hf_icmpv6_ra_router_lifetime,
|
|
|
|
{ "Router lifetime", "icmpv6.ra.router_lifetime", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Router lifetime (s)", HFILL }},
|
|
|
|
{ &hf_icmpv6_ra_reachable_time,
|
|
|
|
{ "Reachable time", "icmpv6.ra.reachable_time", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
|
|
"Reachable time (ms)", HFILL }},
|
|
|
|
{ &hf_icmpv6_ra_retrans_timer,
|
|
|
|
{ "Retrans timer", "icmpv6.ra.retrans_timer", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
|
|
"Retrans timer (ms)", HFILL }},
|
|
|
|
{ &hf_icmpv6_option,
|
|
|
|
{ "ICMPv6 Option", "icmpv6.option", FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Option", HFILL }},
|
|
|
|
{ &hf_icmpv6_option_type,
|
|
|
|
{ "Type", "icmpv6.option.type", FT_UINT8, BASE_DEC, VALS(option_vals), 0x0,
|
|
|
|
"Options type", HFILL }},
|
|
|
|
{ &hf_icmpv6_option_length,
|
|
|
|
{ "Length", "icmpv6.option.length", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Options length (in bytes)", HFILL }},
|
2008-11-05 10:59:20 +00:00
|
|
|
{ &hf_icmpv6_opt_cga_pad_len,
|
2008-02-24 17:14:47 +00:00
|
|
|
{ "Pad Length", "icmpv6.option.cga.pad_length", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Pad Length (in bytes)", HFILL }},
|
2008-11-05 10:59:20 +00:00
|
|
|
{ &hf_icmpv6_opt_cga,
|
2008-02-24 17:14:47 +00:00
|
|
|
{ "CGA", "icmpv6.option.cga", FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
"CGA", HFILL }},
|
2008-11-05 10:59:20 +00:00
|
|
|
{ &hf_icmpv6_opt_cga_modifier,
|
|
|
|
{ "Modifier", "icmpv6.option.cga.modifier", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"Modifier", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_cga_subnet_prefix,
|
|
|
|
{ "Subnet Prefix", "icmpv6.option.cga.subnet_prefix", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"Subnet Prefix", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_cga_count,
|
|
|
|
{ "Count", "icmpv6.option.cga.count", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"Count", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_cga_ext_type,
|
|
|
|
{ "Ext Type", "icmpv6.option.cga.ext_type", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"Ext Type", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_cga_ext_length,
|
|
|
|
{ "Ext Length", "icmpv6.option.cga.ext_length", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"Ext Length", HFILL }},
|
2008-02-24 17:14:47 +00:00
|
|
|
{ &hf_icmpv6_opt_rsa_key_hash,
|
|
|
|
{ "Key Hash", "icmpv6.option.rsa.key_hash", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"Key Hash", HFILL }},
|
2008-02-24 21:04:42 +00:00
|
|
|
{ &hf_icmpv6_opt_name_type,
|
|
|
|
{ "Name Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_name_type_vals), 0x0,
|
|
|
|
"Name Type", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_name_x501,
|
|
|
|
{ "DER Encoded X.501 Name", "icmpv6.option.name_x501", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"DER Encoded X.501 Name", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_name_fqdn,
|
|
|
|
{ "FQDN", "icmpv6.option.name_type.fqdn", FT_STRING, BASE_NONE, NULL, 0x0,
|
|
|
|
"FQDN", HFILL }},
|
|
|
|
{ &hf_icmpv6_opt_cert_type,
|
|
|
|
{ "Cert Type", "icmpv6.option.name_type", FT_UINT8, BASE_DEC, VALS(icmpv6_option_cert_type_vals), 0x0,
|
|
|
|
"Cert Type", HFILL }},
|
|
|
|
{ &hf_icmpv6_identifier,
|
|
|
|
{ "Identifier", "icmpv6.identifier", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Identifier", HFILL }},
|
|
|
|
{ &hf_icmpv6_all_comp,
|
|
|
|
{ "All Components", "icmpv6.all_comp", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"All Components", HFILL }},
|
|
|
|
{ &hf_icmpv6_comp,
|
|
|
|
{ "Component", "icmpv6.comp", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Component", HFILL }},
|
2008-02-25 22:17:24 +00:00
|
|
|
{ &hf_icmpv6_x509if_Name,
|
2008-11-05 10:59:20 +00:00
|
|
|
{ "Name", "icmpv6.x509_Name", FT_UINT32, BASE_DEC, VALS(x509if_Name_vals), 0x0,
|
2008-02-25 22:17:24 +00:00
|
|
|
"Name", HFILL }},
|
|
|
|
{ &hf_icmpv6_x509af_Certificate,
|
2008-11-05 10:59:20 +00:00
|
|
|
{ "Certificate", "icmpv6.x509_Certificate", FT_NONE, BASE_NONE, NULL, 0x0,
|
2008-02-25 22:17:24 +00:00
|
|
|
"Certificate", HFILL }},
|
2008-03-17 21:21:48 +00:00
|
|
|
{ &hf_icmpv6_recursive_dns_serv,
|
2008-11-05 10:59:20 +00:00
|
|
|
{ "Recursive DNS Servers", "icmpv6.recursive_dns_serv", FT_IPv6, BASE_HEX, NULL, 0x0,
|
|
|
|
"Recursive DNS Servers", HFILL }}
|
1999-10-10 16:09:33 +00:00
|
|
|
};
|
2008-02-24 17:14:47 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_icmpv6,
|
|
|
|
&ett_icmpv6opt,
|
|
|
|
&ett_icmpv6flag,
|
2000-08-18 12:05:27 +00:00
|
|
|
&ett_nodeinfo_flag,
|
|
|
|
&ett_nodeinfo_subject4,
|
|
|
|
&ett_nodeinfo_subject6,
|
|
|
|
&ett_nodeinfo_node4,
|
|
|
|
&ett_nodeinfo_node6,
|
2000-08-22 08:30:00 +00:00
|
|
|
&ett_nodeinfo_nodebitmap,
|
|
|
|
&ett_nodeinfo_nodedns,
|
2003-12-19 23:20:53 +00:00
|
|
|
&ett_multicastRR,
|
2008-11-05 10:59:20 +00:00
|
|
|
&ett_icmpv6opt_name,
|
|
|
|
&ett_cga_param_name
|
1999-11-16 11:44:20 +00:00
|
|
|
};
|
1999-10-10 16:09:33 +00:00
|
|
|
|
|
|
|
proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",
|
2001-01-03 06:56:03 +00:00
|
|
|
"ICMPv6", "icmpv6");
|
1999-10-10 16:09:33 +00:00
|
|
|
proto_register_field_array(proto_icmpv6, hf, array_length(hf));
|
1999-11-16 11:44:20 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2007-07-30 17:21:40 +00:00
|
|
|
|
|
|
|
register_dissector("icmpv6", dissect_icmpv6, proto_icmpv6);
|
1999-07-29 05:47:07 +00:00
|
|
|
}
|
2000-04-20 07:05:58 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_icmpv6(void)
|
|
|
|
{
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_handle_t icmpv6_handle;
|
|
|
|
|
|
|
|
icmpv6_handle = create_dissector_handle(dissect_icmpv6, proto_icmpv6);
|
|
|
|
dissector_add("ip.proto", IP_PROTO_ICMPV6, icmpv6_handle);
|
2001-04-23 03:56:57 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a handle for the IPv6 dissector.
|
|
|
|
*/
|
|
|
|
ipv6_handle = find_dissector("ipv6");
|
2001-11-25 22:51:14 +00:00
|
|
|
data_handle = find_dissector("data");
|
2000-04-20 07:05:58 +00:00
|
|
|
}
|