1998-09-16 02:39:15 +00:00
|
|
|
/* packet-ipv6.c
|
2001-06-26 17:31:36 +00:00
|
|
|
* Routines for IPv6 packet disassembly
|
1998-09-16 02:39:15 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1998-09-16 03:22:19 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* Ethereal - Network traffic analyzer
|
2001-01-23 02:49:55 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
1998-09-16 02:39:15 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2001-01-23 02:49:55 +00:00
|
|
|
* MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
|
|
|
|
*
|
1998-09-16 02:39:15 +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.
|
2001-06-26 17:31:36 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +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.
|
2001-06-26 17:31:36 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +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
|
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
1999-03-23 03:14:46 +00:00
|
|
|
#include <glib.h>
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2000-02-15 21:06:58 +00:00
|
|
|
#include "packet-ipsec.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "packet-ipv6.h"
|
2003-07-11 09:30:49 +00:00
|
|
|
#include "ip_opts.h"
|
2004-08-06 19:57:49 +00:00
|
|
|
#include <epan/addr_resolv.h>
|
2004-09-27 22:55:15 +00:00
|
|
|
#include <epan/prefs.h>
|
2001-06-08 08:30:42 +00:00
|
|
|
#include "reassemble.h"
|
2004-09-29 00:52:45 +00:00
|
|
|
#include <epan/ipproto.h>
|
2001-04-17 06:43:21 +00:00
|
|
|
#include "etypes.h"
|
|
|
|
#include "ppptypes.h"
|
|
|
|
#include "aftypes.h"
|
2001-12-02 00:07:46 +00:00
|
|
|
#include "nlpid.h"
|
2003-01-23 09:39:33 +00:00
|
|
|
#include "arcnet_pids.h"
|
1999-03-28 18:32:03 +00:00
|
|
|
|
1999-10-15 04:22:48 +00:00
|
|
|
/*
|
|
|
|
* NOTE: ipv6.nxt is not very useful as we will have chained header.
|
|
|
|
* now testing ipv6.final, but it raises SEGV.
|
|
|
|
#define TEST_FINALHDR
|
|
|
|
*/
|
|
|
|
|
1999-07-29 05:47:07 +00:00
|
|
|
static int proto_ipv6 = -1;
|
1999-10-15 04:22:48 +00:00
|
|
|
static int hf_ipv6_version = -1;
|
|
|
|
static int hf_ipv6_class = -1;
|
|
|
|
static int hf_ipv6_flow = -1;
|
|
|
|
static int hf_ipv6_plen = -1;
|
|
|
|
static int hf_ipv6_nxt = -1;
|
|
|
|
static int hf_ipv6_hlim = -1;
|
1999-10-11 17:05:49 +00:00
|
|
|
static int hf_ipv6_src = -1;
|
|
|
|
static int hf_ipv6_dst = -1;
|
2000-08-11 22:18:22 +00:00
|
|
|
static int hf_ipv6_addr = -1;
|
1999-10-15 04:22:48 +00:00
|
|
|
#ifdef TEST_FINALHDR
|
|
|
|
static int hf_ipv6_final = -1;
|
|
|
|
#endif
|
2001-06-08 08:30:42 +00:00
|
|
|
static int hf_ipv6_fragments = -1;
|
|
|
|
static int hf_ipv6_fragment = -1;
|
|
|
|
static int hf_ipv6_fragment_overlap = -1;
|
|
|
|
static int hf_ipv6_fragment_overlap_conflict = -1;
|
|
|
|
static int hf_ipv6_fragment_multiple_tails = -1;
|
|
|
|
static int hf_ipv6_fragment_too_long_fragment = -1;
|
|
|
|
static int hf_ipv6_fragment_error = -1;
|
2003-04-20 08:06:01 +00:00
|
|
|
static int hf_ipv6_reassembled_in = -1;
|
1999-07-29 05:47:07 +00:00
|
|
|
|
2001-01-23 02:49:55 +00:00
|
|
|
static int hf_ipv6_mipv6_type = -1;
|
|
|
|
static int hf_ipv6_mipv6_length = -1;
|
|
|
|
static int hf_ipv6_mipv6_home_address = -1;
|
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint ett_ipv6 = -1;
|
2001-06-08 08:30:42 +00:00
|
|
|
static gint ett_ipv6_fragments = -1;
|
|
|
|
static gint ett_ipv6_fragment = -1;
|
|
|
|
|
2002-10-24 06:17:36 +00:00
|
|
|
static const fragment_items ipv6_frag_items = {
|
2002-06-07 10:11:41 +00:00
|
|
|
&ett_ipv6_fragment,
|
|
|
|
&ett_ipv6_fragments,
|
|
|
|
&hf_ipv6_fragments,
|
|
|
|
&hf_ipv6_fragment,
|
|
|
|
&hf_ipv6_fragment_overlap,
|
|
|
|
&hf_ipv6_fragment_overlap_conflict,
|
|
|
|
&hf_ipv6_fragment_multiple_tails,
|
|
|
|
&hf_ipv6_fragment_too_long_fragment,
|
|
|
|
&hf_ipv6_fragment_error,
|
2003-04-20 11:36:16 +00:00
|
|
|
&hf_ipv6_reassembled_in,
|
2002-06-07 10:11:41 +00:00
|
|
|
"fragments"
|
|
|
|
};
|
|
|
|
|
2001-11-26 04:52:51 +00:00
|
|
|
static dissector_handle_t data_handle;
|
|
|
|
|
2003-04-29 17:24:35 +00:00
|
|
|
static dissector_table_t ip_dissector_table;
|
|
|
|
|
2001-06-08 08:30:42 +00:00
|
|
|
/* Reassemble fragmented datagrams */
|
|
|
|
static gboolean ipv6_reassemble = FALSE;
|
1999-11-16 11:44:20 +00:00
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
#ifndef offsetof
|
|
|
|
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
|
|
|
#endif
|
|
|
|
|
2001-06-08 08:30:42 +00:00
|
|
|
/*
|
|
|
|
* defragmentation of IPv6
|
|
|
|
*/
|
|
|
|
static GHashTable *ipv6_fragment_table = NULL;
|
Use "fragment_add_check()" for IPv6 and CLNP reassembly. (Possibly an
issue for CLNP, with its 16-bit IDs, which could be duplicated in a
sufficiently large capture even if CLNP implementations don't
deliberately reuse IDs; less of an issue for IPv6, with its 32-bit IDs
and with its prohibition on reuse:
For every packet that is to be fragmented, the source node generates
an Identification value. The Identification must be different than
that of any other fragmented packet sent recently* with the same
Source Address and Destination Address. If a Routing header is
present, the Destination Address of concern is that of the final
destination.
* "recently" means within the maximum likely lifetime of a packet,
including transit time from source to destination and time spent
awaiting reassembly with other fragments of the same packet.
However, it is not required that a source node know the maximum
packet lifetime. Rather, it is assumed that the requirement can
be met by maintaining the Identification value as a simple, 32-
bit, "wrap-around" counter, incremented each time a packet must
be fragmented. It is an implementation choice whether to
maintain a single counter for the node or multiple counters,
e.g., one for each of the node's possible source addresses, or
one for each active (source address, destination address)
combination.
but perhaps we'll ultimately be able to get rid of the old
"fragment_add()" entirely and rename "fragment_add_check()" to
"fragment_add()").
svn path=/trunk/; revision=7507
2003-04-20 00:21:17 +00:00
|
|
|
static GHashTable *ipv6_reassembled_table = NULL;
|
2001-06-08 08:30:42 +00:00
|
|
|
|
2002-10-22 22:04:23 +00:00
|
|
|
void
|
|
|
|
capture_ipv6(const guchar *pd, int offset, int len, packet_counts *ld)
|
|
|
|
{
|
2002-10-25 23:23:28 +00:00
|
|
|
guint8 nxt;
|
|
|
|
int advance;
|
|
|
|
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, 4+4+16+16)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nxt = pd[offset+6]; /* get the "next header" value */
|
|
|
|
offset += 4+4+16+16; /* skip past the IPv6 header */
|
|
|
|
|
|
|
|
again:
|
|
|
|
switch (nxt) {
|
|
|
|
case IP_PROTO_HOPOPTS:
|
|
|
|
case IP_PROTO_ROUTING:
|
|
|
|
case IP_PROTO_DSTOPTS:
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nxt = pd[offset];
|
|
|
|
advance = (pd[offset+1] + 1) << 3;
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
offset += advance;
|
|
|
|
goto again;
|
|
|
|
case IP_PROTO_FRAGMENT:
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nxt = pd[offset];
|
|
|
|
advance = 8;
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
offset += advance;
|
|
|
|
goto again;
|
|
|
|
case IP_PROTO_AH:
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nxt = pd[offset];
|
|
|
|
advance = 8 + ((pd[offset+1] - 1) << 2);
|
|
|
|
if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
|
|
|
|
ld->other++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
offset += advance;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(nxt) {
|
|
|
|
case IP_PROTO_SCTP:
|
|
|
|
ld->sctp++;
|
|
|
|
break;
|
|
|
|
case IP_PROTO_TCP:
|
|
|
|
ld->tcp++;
|
|
|
|
break;
|
|
|
|
case IP_PROTO_UDP:
|
|
|
|
ld->udp++;
|
|
|
|
break;
|
|
|
|
case IP_PROTO_ICMP:
|
|
|
|
case IP_PROTO_ICMPV6: /* XXX - separate counters? */
|
|
|
|
ld->icmp++;
|
|
|
|
break;
|
|
|
|
case IP_PROTO_OSPF:
|
|
|
|
ld->ospf++;
|
|
|
|
break;
|
|
|
|
case IP_PROTO_GRE:
|
|
|
|
ld->gre++;
|
|
|
|
break;
|
|
|
|
case IP_PROTO_VINES:
|
|
|
|
ld->vines++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ld->other++;
|
|
|
|
}
|
2002-10-22 22:04:23 +00:00
|
|
|
}
|
|
|
|
|
2001-06-08 08:30:42 +00:00
|
|
|
static void
|
|
|
|
ipv6_reassemble_init(void)
|
|
|
|
{
|
|
|
|
fragment_table_init(&ipv6_fragment_table);
|
Use "fragment_add_check()" for IPv6 and CLNP reassembly. (Possibly an
issue for CLNP, with its 16-bit IDs, which could be duplicated in a
sufficiently large capture even if CLNP implementations don't
deliberately reuse IDs; less of an issue for IPv6, with its 32-bit IDs
and with its prohibition on reuse:
For every packet that is to be fragmented, the source node generates
an Identification value. The Identification must be different than
that of any other fragmented packet sent recently* with the same
Source Address and Destination Address. If a Routing header is
present, the Destination Address of concern is that of the final
destination.
* "recently" means within the maximum likely lifetime of a packet,
including transit time from source to destination and time spent
awaiting reassembly with other fragments of the same packet.
However, it is not required that a source node know the maximum
packet lifetime. Rather, it is assumed that the requirement can
be met by maintaining the Identification value as a simple, 32-
bit, "wrap-around" counter, incremented each time a packet must
be fragmented. It is an implementation choice whether to
maintain a single counter for the node or multiple counters,
e.g., one for each of the node's possible source addresses, or
one for each active (source address, destination address)
combination.
but perhaps we'll ultimately be able to get rid of the old
"fragment_add()" entirely and rename "fragment_add_check()" to
"fragment_add()").
svn path=/trunk/; revision=7507
2003-04-20 00:21:17 +00:00
|
|
|
reassembled_table_init(&ipv6_reassembled_table);
|
2001-06-08 08:30:42 +00:00
|
|
|
}
|
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
static int
|
2001-04-23 03:37:31 +00:00
|
|
|
dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree) {
|
1999-10-12 23:12:06 +00:00
|
|
|
struct ip6_rthdr rt;
|
2001-10-26 18:28:17 +00:00
|
|
|
guint len;
|
1999-10-12 23:12:06 +00:00
|
|
|
proto_tree *rthdr_tree;
|
|
|
|
proto_item *ti;
|
|
|
|
char buf[sizeof(struct ip6_rthdr0) + sizeof(struct e_in6_addr) * 23];
|
2001-06-26 17:31:36 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)&rt, offset, sizeof(rt));
|
1999-10-12 23:12:06 +00:00
|
|
|
len = (rt.ip6r_len + 1) << 3;
|
|
|
|
|
|
|
|
if (tree) {
|
|
|
|
/* !!! specify length */
|
2001-04-23 03:37:31 +00:00
|
|
|
ti = proto_tree_add_text(tree, tvb, offset, len,
|
2000-03-07 05:28:39 +00:00
|
|
|
"Routing Header, Type %u", rt.ip6r_type);
|
1999-11-16 11:44:20 +00:00
|
|
|
rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
|
1999-10-12 23:12:06 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
1999-10-13 02:04:04 +00:00
|
|
|
offset + offsetof(struct ip6_rthdr, ip6r_nxt), 1,
|
1999-10-14 03:50:51 +00:00
|
|
|
"Next header: %s (0x%02x)", ipprotostr(rt.ip6r_nxt), rt.ip6r_nxt);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
1999-10-12 23:12:06 +00:00
|
|
|
offset + offsetof(struct ip6_rthdr, ip6r_len), 1,
|
2000-03-07 05:28:39 +00:00
|
|
|
"Length: %u (%d bytes)", rt.ip6r_len, len);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
1999-10-12 23:12:06 +00:00
|
|
|
offset + offsetof(struct ip6_rthdr, ip6r_type), 1,
|
2000-03-07 05:28:39 +00:00
|
|
|
"Type: %u", rt.ip6r_type);
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
1999-10-12 23:12:06 +00:00
|
|
|
offset + offsetof(struct ip6_rthdr, ip6r_segleft), 1,
|
2000-03-07 05:28:39 +00:00
|
|
|
"Segments left: %u", rt.ip6r_segleft);
|
1999-10-12 23:12:06 +00:00
|
|
|
|
|
|
|
if (rt.ip6r_type == 0 && len <= sizeof(buf)) {
|
|
|
|
struct e_in6_addr *a;
|
|
|
|
int n;
|
|
|
|
struct ip6_rthdr0 *rt0;
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb_memcpy(tvb, buf, offset, len);
|
1999-10-12 23:12:06 +00:00
|
|
|
rt0 = (struct ip6_rthdr0 *)buf;
|
|
|
|
for (a = rt0->ip6r0_addr, n = 0;
|
|
|
|
a < (struct e_in6_addr *)(buf + len);
|
|
|
|
a++, n++) {
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
1999-10-12 23:12:06 +00:00
|
|
|
offset + offsetof(struct ip6_rthdr0, ip6r0_addr) + n * sizeof(struct e_in6_addr),
|
|
|
|
sizeof(struct e_in6_addr),
|
|
|
|
#ifdef INET6
|
|
|
|
"address %d: %s (%s)",
|
|
|
|
n, get_hostname6(a), ip6_to_str(a)
|
|
|
|
#else
|
|
|
|
"address %d: %s", n, ip6_to_str(a)
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2003-02-04 20:17:01 +00:00
|
|
|
if (rt.ip6r_type == 2) {
|
|
|
|
proto_tree_add_ipv6(rthdr_tree, hf_ipv6_mipv6_home_address,
|
|
|
|
tvb, offset + 8, 16,
|
|
|
|
tvb_get_ptr(tvb, offset + 8, 16));
|
|
|
|
}
|
1999-10-12 23:12:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
1999-03-28 18:32:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-06-26 17:31:36 +00:00
|
|
|
dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
|
2001-06-08 08:30:42 +00:00
|
|
|
guint16 *offlg, guint32 *ident) {
|
1999-10-12 23:12:06 +00:00
|
|
|
struct ip6_frag frag;
|
|
|
|
int len;
|
2000-08-08 21:49:13 +00:00
|
|
|
proto_item *ti;
|
|
|
|
proto_tree *rthdr_tree;
|
1999-10-12 23:12:06 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)&frag, offset, sizeof(frag));
|
1999-10-12 23:12:06 +00:00
|
|
|
len = sizeof(frag);
|
2002-08-02 23:36:07 +00:00
|
|
|
frag.ip6f_offlg = g_ntohs(frag.ip6f_offlg);
|
2004-01-21 08:39:29 +00:00
|
|
|
frag.ip6f_ident = g_ntohl(frag.ip6f_ident);
|
2001-06-08 08:30:42 +00:00
|
|
|
*offlg = frag.ip6f_offlg;
|
|
|
|
*ident = frag.ip6f_ident;
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO,
|
2000-05-24 07:52:31 +00:00
|
|
|
"IPv6 fragment (nxt=%s (0x%02x) off=%u id=0x%x)",
|
1999-10-14 03:50:51 +00:00
|
|
|
ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt,
|
2001-06-08 08:30:42 +00:00
|
|
|
frag.ip6f_offlg & IP6F_OFF_MASK, frag.ip6f_ident);
|
1999-03-28 18:32:03 +00:00
|
|
|
}
|
2000-08-08 21:49:13 +00:00
|
|
|
if (tree) {
|
2001-04-23 03:37:31 +00:00
|
|
|
ti = proto_tree_add_text(tree, tvb, offset, len,
|
2002-10-25 23:23:28 +00:00
|
|
|
"Fragmentation Header");
|
2000-08-08 21:49:13 +00:00
|
|
|
rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
2000-08-08 21:49:13 +00:00
|
|
|
offset + offsetof(struct ip6_frag, ip6f_nxt), 1,
|
|
|
|
"Next header: %s (0x%02x)",
|
|
|
|
ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt);
|
|
|
|
|
2001-06-26 17:31:36 +00:00
|
|
|
#if 0
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
2000-08-08 21:49:13 +00:00
|
|
|
offset + offsetof(struct ip6_frag, ip6f_reserved), 1,
|
|
|
|
"Reserved: %u",
|
|
|
|
frag.ip6f_reserved);
|
2001-06-26 17:31:36 +00:00
|
|
|
#endif
|
2000-08-08 21:49:13 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
2000-08-08 21:49:13 +00:00
|
|
|
offset + offsetof(struct ip6_frag, ip6f_offlg), 2,
|
|
|
|
"Offset: %u",
|
2000-11-11 10:23:43 +00:00
|
|
|
frag.ip6f_offlg & IP6F_OFF_MASK);
|
2000-08-08 21:49:13 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
2000-08-08 21:49:13 +00:00
|
|
|
offset + offsetof(struct ip6_frag, ip6f_offlg), 2,
|
|
|
|
"More fragments: %s",
|
|
|
|
frag.ip6f_offlg & IP6F_MORE_FRAG ?
|
|
|
|
"Yes" : "No");
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_text(rthdr_tree, tvb,
|
2000-08-08 21:49:13 +00:00
|
|
|
offset + offsetof(struct ip6_frag, ip6f_ident), 4,
|
|
|
|
"Identification: 0x%08x",
|
|
|
|
frag.ip6f_ident);
|
|
|
|
}
|
1999-10-12 23:12:06 +00:00
|
|
|
return len;
|
1999-03-28 18:32:03 +00:00
|
|
|
}
|
|
|
|
|
2001-01-23 02:49:55 +00:00
|
|
|
static int
|
2003-02-04 20:17:01 +00:00
|
|
|
dissect_mipv6_hoa(tvbuff_t *tvb, proto_tree *dstopt_tree, int offset)
|
2001-06-26 17:31:36 +00:00
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
proto_tree_add_uint_format(dstopt_tree, hf_ipv6_mipv6_type, tvb,
|
2003-02-04 20:17:01 +00:00
|
|
|
offset + len, 1,
|
2001-06-26 17:31:36 +00:00
|
|
|
tvb_get_guint8(tvb, offset + len),
|
2003-02-04 20:17:01 +00:00
|
|
|
"Option Type: %u (0x%02x) - Home Address Option",
|
2001-06-26 17:31:36 +00:00
|
|
|
tvb_get_guint8(tvb, offset + len),
|
|
|
|
tvb_get_guint8(tvb, offset + len));
|
2003-02-04 20:17:01 +00:00
|
|
|
len += 1;
|
2001-01-23 02:49:55 +00:00
|
|
|
|
2003-02-04 20:17:01 +00:00
|
|
|
proto_tree_add_uint(dstopt_tree, hf_ipv6_mipv6_length, tvb, offset + len,
|
|
|
|
1, tvb_get_guint8(tvb, offset + len));
|
|
|
|
len += 1;
|
2001-06-26 17:31:36 +00:00
|
|
|
|
2003-02-04 20:17:01 +00:00
|
|
|
proto_tree_add_ipv6(dstopt_tree, hf_ipv6_mipv6_home_address, tvb,
|
|
|
|
offset + len, 16, tvb_get_ptr(tvb, offset + len, 16));
|
|
|
|
len += 16;
|
2001-06-26 17:31:36 +00:00
|
|
|
return len;
|
|
|
|
}
|
2001-01-23 02:49:55 +00:00
|
|
|
|
2001-06-26 17:31:36 +00:00
|
|
|
static const value_string rtalertvals[] = {
|
|
|
|
{ IP6OPT_RTALERT_MLD, "MLD" },
|
|
|
|
{ IP6OPT_RTALERT_RSVP, "RSVP" },
|
|
|
|
{ 0, NULL },
|
|
|
|
};
|
2001-01-23 02:49:55 +00:00
|
|
|
|
2003-07-11 09:30:49 +00:00
|
|
|
/* Like "dissect_ip_tcp_options()", but assumes the length of an option
|
|
|
|
*doesn't* include the type and length bytes. */
|
|
|
|
void
|
|
|
|
dissect_ipv6_options(tvbuff_t *tvb, int offset, guint length,
|
|
|
|
const ip_tcp_opt *opttab, int nopts, int eol,
|
|
|
|
packet_info *pinfo, proto_tree *opt_tree)
|
|
|
|
{
|
|
|
|
guchar opt;
|
|
|
|
const ip_tcp_opt *optp;
|
|
|
|
opt_len_type len_type;
|
|
|
|
unsigned int optlen;
|
|
|
|
char *name;
|
|
|
|
char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
|
|
|
|
void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
|
|
|
|
int, guint, packet_info *, proto_tree *);
|
|
|
|
guint len;
|
|
|
|
|
|
|
|
while (length > 0) {
|
|
|
|
opt = tvb_get_guint8(tvb, offset);
|
|
|
|
for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
|
|
|
|
if (optp->optcode == opt)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (optp == &opttab[nopts]) {
|
|
|
|
/* We assume that the only NO_LENGTH options are Pad1 options,
|
|
|
|
so that we can treat unknown options as VARIABLE_LENGTH with a
|
|
|
|
minimum of 0, and at least be able to move on to the next option
|
|
|
|
by using the length in the option. */
|
|
|
|
optp = NULL; /* indicate that we don't know this option */
|
|
|
|
len_type = VARIABLE_LENGTH;
|
|
|
|
optlen = 0;
|
|
|
|
snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
|
|
|
|
name = name_str;
|
|
|
|
dissect = NULL;
|
|
|
|
} else {
|
|
|
|
len_type = optp->len_type;
|
|
|
|
optlen = optp->optlen;
|
|
|
|
name = optp->name;
|
|
|
|
dissect = optp->dissect;
|
|
|
|
}
|
|
|
|
--length; /* account for type byte */
|
|
|
|
if (len_type != NO_LENGTH) {
|
|
|
|
/* Option has a length. Is it in the packet? */
|
|
|
|
if (length == 0) {
|
|
|
|
/* Bogus - packet must at least include option code byte and
|
|
|
|
length byte! */
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, 1,
|
|
|
|
"%s (length byte past end of options)", name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
|
|
|
|
--length; /* account for length byte */
|
|
|
|
if (len > length) {
|
|
|
|
/* Bogus - option goes past the end of the header. */
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, length,
|
|
|
|
"%s (option length = %u byte%s says option goes past end of options)",
|
|
|
|
name, len, plurality(len, "", "s"));
|
|
|
|
return;
|
|
|
|
} else if (len_type == FIXED_LENGTH && len != optlen) {
|
|
|
|
/* Bogus - option length isn't what it's supposed to be for this
|
|
|
|
option. */
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, 2 + len,
|
|
|
|
"%s (with option length = %u byte%s; should be %u)", name,
|
|
|
|
len, plurality(len, "", "s"), optlen);
|
|
|
|
return;
|
|
|
|
} else if (len_type == VARIABLE_LENGTH && len < optlen) {
|
|
|
|
/* Bogus - option length is less than what it's supposed to be for
|
|
|
|
this option. */
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, 2 + len,
|
|
|
|
"%s (with option length = %u byte%s; should be >= %u)", name,
|
|
|
|
len, plurality(len, "", "s"), optlen);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if (optp == NULL) {
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, 2 + len, "%s (%u byte%s)",
|
|
|
|
name, len, plurality(len, "", "s"));
|
|
|
|
} else {
|
|
|
|
if (dissect != NULL) {
|
|
|
|
/* Option has a dissector. */
|
|
|
|
(*dissect)(optp, tvb, offset, 2 + len, pinfo, opt_tree);
|
|
|
|
} else {
|
|
|
|
/* Option has no data, hence no dissector. */
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, 2 + len, "%s", name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset += 2 + len;
|
|
|
|
}
|
|
|
|
length -= len;
|
|
|
|
} else {
|
|
|
|
proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
if (opt == eol)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-26 17:31:36 +00:00
|
|
|
static int
|
|
|
|
dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, char *optname)
|
|
|
|
{
|
|
|
|
struct ip6_ext ext;
|
|
|
|
int len;
|
|
|
|
proto_tree *dstopt_tree;
|
|
|
|
proto_item *ti;
|
|
|
|
gint p;
|
|
|
|
guint8 tmp;
|
|
|
|
int mip_offset = 0, delta = 0;
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2001-06-26 17:31:36 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)&ext, offset, sizeof(ext));
|
|
|
|
len = (ext.ip6e_len + 1) << 3;
|
2001-01-23 02:49:55 +00:00
|
|
|
|
2001-06-26 17:31:36 +00:00
|
|
|
if (tree) {
|
|
|
|
/* !!! specify length */
|
|
|
|
ti = proto_tree_add_text(tree, tvb, offset, len, "%s Header ", optname);
|
|
|
|
|
|
|
|
dstopt_tree = proto_item_add_subtree(ti, ett_ipv6);
|
|
|
|
|
|
|
|
proto_tree_add_text(dstopt_tree, tvb,
|
|
|
|
offset + offsetof(struct ip6_ext, ip6e_nxt), 1,
|
|
|
|
"Next header: %s (0x%02x)", ipprotostr(ext.ip6e_nxt), ext.ip6e_nxt);
|
|
|
|
proto_tree_add_text(dstopt_tree, tvb,
|
|
|
|
offset + offsetof(struct ip6_ext, ip6e_len), 1,
|
|
|
|
"Length: %u (%d bytes)", ext.ip6e_len, len);
|
|
|
|
|
|
|
|
mip_offset = offset;
|
|
|
|
mip_offset += 2;
|
|
|
|
|
|
|
|
p = offset + 2;
|
|
|
|
|
|
|
|
while (p < offset + len) {
|
|
|
|
switch (tvb_get_guint8(tvb, p)) {
|
|
|
|
case IP6OPT_PAD1:
|
|
|
|
proto_tree_add_text(dstopt_tree, tvb, p, 1, "Pad1");
|
|
|
|
p++;
|
|
|
|
mip_offset++;
|
|
|
|
break;
|
|
|
|
case IP6OPT_PADN:
|
|
|
|
tmp = tvb_get_guint8(tvb, p + 1);
|
|
|
|
proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
|
|
|
|
"PadN: %u bytes", tmp + 2);
|
|
|
|
p += tmp;
|
|
|
|
p += 2;
|
|
|
|
mip_offset += tvb_get_guint8(tvb, mip_offset + 1) + 2;
|
|
|
|
break;
|
|
|
|
case IP6OPT_JUMBO:
|
|
|
|
tmp = tvb_get_guint8(tvb, p + 1);
|
|
|
|
if (tmp == 4) {
|
|
|
|
proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
|
|
|
|
"Jumbo payload: %u (%u bytes)",
|
|
|
|
tvb_get_ntohl(tvb, p + 2), tmp + 2);
|
|
|
|
} else {
|
|
|
|
proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
|
|
|
|
"Jumbo payload: Invalid length (%u bytes)",
|
|
|
|
tmp + 2);
|
1999-10-12 23:12:06 +00:00
|
|
|
}
|
2001-06-26 17:31:36 +00:00
|
|
|
p += tmp;
|
|
|
|
p += 2;
|
|
|
|
mip_offset += tvb_get_guint8(tvb, mip_offset+1)+2;
|
|
|
|
break;
|
|
|
|
case IP6OPT_RTALERT:
|
|
|
|
{
|
|
|
|
char *rta;
|
|
|
|
|
|
|
|
tmp = tvb_get_guint8(tvb, p + 1);
|
|
|
|
if (tmp == 2) {
|
|
|
|
rta = val_to_str(tvb_get_ntohs(tvb, p + 2), rtalertvals,
|
|
|
|
"Unknown");
|
|
|
|
} else
|
|
|
|
rta = "Invalid length";
|
|
|
|
ti = proto_tree_add_text(dstopt_tree, tvb, p , tmp + 2,
|
|
|
|
"Router alert: %s (%u bytes)", rta, tmp + 2);
|
|
|
|
p += tmp;
|
|
|
|
p += 2;
|
|
|
|
mip_offset += tvb_get_guint8(tvb, mip_offset + 1) + 2;
|
|
|
|
break;
|
|
|
|
}
|
2003-02-04 20:17:01 +00:00
|
|
|
case IP6OPT_HOME_ADDRESS:
|
|
|
|
delta = dissect_mipv6_hoa(tvb, dstopt_tree, mip_offset);
|
2001-06-26 17:31:36 +00:00
|
|
|
p += delta;
|
|
|
|
mip_offset += delta;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
p = offset + len;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-10-12 23:12:06 +00:00
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
/* decode... */
|
2001-06-26 17:31:36 +00:00
|
|
|
}
|
1999-03-28 18:32:03 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
1999-10-12 23:12:06 +00:00
|
|
|
static int
|
2001-06-26 17:31:36 +00:00
|
|
|
dissect_hopopts(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
|
|
{
|
2001-04-23 03:37:31 +00:00
|
|
|
return dissect_opts(tvb, offset, tree, "Hop-by-hop Option");
|
1999-10-12 23:12:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-06-26 17:31:36 +00:00
|
|
|
dissect_dstopts(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
|
|
{
|
2001-04-23 03:37:31 +00:00
|
|
|
return dissect_opts(tvb, offset, tree, "Destination Option");
|
1999-10-12 23:12:06 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2001-04-23 03:56:57 +00:00
|
|
|
static void
|
2001-06-26 17:31:36 +00:00
|
|
|
dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
2001-06-08 08:30:42 +00:00
|
|
|
proto_tree *ipv6_tree = NULL;
|
1999-03-23 03:14:46 +00:00
|
|
|
proto_item *ti;
|
1999-03-28 18:32:03 +00:00
|
|
|
guint8 nxt;
|
|
|
|
int advance;
|
1999-10-15 04:22:48 +00:00
|
|
|
int poffset;
|
2001-06-08 08:30:42 +00:00
|
|
|
guint16 plen;
|
2002-05-02 08:55:52 +00:00
|
|
|
gboolean hopopts, routing, frag, ah, dstopts;
|
2001-06-08 08:30:42 +00:00
|
|
|
guint16 offlg;
|
|
|
|
guint32 ident;
|
2001-04-23 03:37:31 +00:00
|
|
|
int offset;
|
2001-06-08 08:30:42 +00:00
|
|
|
fragment_data *ipfd_head;
|
|
|
|
tvbuff_t *next_tvb;
|
|
|
|
gboolean update_col_info = TRUE;
|
Use the "fragmented" field of the "packet_info" structure in
"dissect_frame()" to indicate whether a ReportedBoundsError was due to
the packet being malformed (i.e., the packet was shorter than it's
supposed to be, so the dissector went past the end trying to extract
fields that were supposed to be there) or due to it not being
reassembled (i.e., the packet was fragmented, and we didn't reassemble
it, but just treated the first fragment as the entire packet, so the
dissector went past the end trying to extract fields that were partially
or completely in fragments after that). Mark the latter as being
unreasembled rather than malformed.
Properly initialize, save, and restore that field, and properly set it,
so that works.
svn path=/trunk/; revision=4555
2002-01-17 06:29:20 +00:00
|
|
|
gboolean save_fragmented;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
struct ip6_hdr ipv6;
|
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPv6");
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2001-04-23 03:37:31 +00:00
|
|
|
|
|
|
|
offset = 0;
|
2001-06-26 17:31:36 +00:00
|
|
|
tvb_memcpy(tvb, (guint8 *)&ipv6, offset, sizeof(ipv6));
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
pinfo->ipproto = ipv6.ip6_nxt; /* XXX make work TCP follow (ipproto = 6) */
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2001-06-08 08:30:42 +00:00
|
|
|
/* Get the payload length */
|
2002-08-02 23:36:07 +00:00
|
|
|
plen = g_ntohs(ipv6.ip6_plen);
|
2001-06-08 08:30:42 +00:00
|
|
|
|
2001-06-29 09:46:54 +00:00
|
|
|
/* Adjust the length of this tvbuff to include only the IPv6 datagram. */
|
2002-02-17 00:51:21 +00:00
|
|
|
set_actual_length(tvb, plen + sizeof (struct ip6_hdr));
|
2000-08-11 22:18:22 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
SET_ADDRESS(&pinfo->net_src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_SRC, 16));
|
|
|
|
SET_ADDRESS(&pinfo->src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_SRC, 16));
|
|
|
|
SET_ADDRESS(&pinfo->net_dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_DST, 16));
|
|
|
|
SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_DST, 16));
|
Generalize the "ip_src" and "ip_dst" members of the "packet_info"
structure to "dl_src"/"dl_dst", "net_src"/"net_dst", and "src"/"dst"
addresses, where an address is an address type, an address length in
bytes, and a pointer to that many bytes.
"dl_{src,dst}" are the link-layer source/destination; "net_{src,dst}"
are the network-layer source/destination; "{src,dst}" are the
source/destination from the highest of those two layers that we have in
the packet.
Add a port type to "packet_info" as well, specifying whether it's a TCP
or UDP port.
Don't set the address and port columns in the dissector functions; just
set the address and port members of the "packet_info" structure. Set
the columns in "fill_in_columns()"; this means that if we're showing
COL_{DEF,RES,UNRES}_SRC" or "COL_{DEF,RES,UNRES}_DST", we only generate
the string from "src" or "dst", we don't generate a string for the
link-layer address and then overwrite it with a string for the
network-layer address (generating those strings costs CPU).
Add support for "conversations", where a "conversation" is (at present)
a source and destination address and a source and destination port. (In
the future, we may support "conversations" above the transport layer,
e.g. a TFTP conversation, where the first packet goes from the client to
the TFTP server port, but the reply comes back from a different port,
and all subsequent packets go between the client address/port and the
server address/new port, or an NFS conversation, which might include
lock manager, status monitor, and mount packets, as well as NFS
packets.)
Currently, all we support is a call that takes the source and
destination address/port pairs, looks them up in a hash table, and:
if nothing is found, creates a new entry in the hash table, and
assigns it a unique 32-bit conversation ID, and returns that
conversation ID;
if an entry is found, returns its conversation ID.
Use that in the SMB and AFS code to keep track of individual SMB or AFS
conversations. We need to match up requests and replies, as, for
certain replies, the operation code for the request to which it's a
reply doesn't show up in the reply - you have to find the request with a
matching transaction ID. Transaction IDs are per-conversation, so the
hash table for requests should include a conversation ID and transaction
ID as the key.
This allows SMB and AFS decoders to handle IPv4 or IPv6 addresses
transparently (and should allow the SMB decoder to handle NetBIOS atop
other protocols as well, if the source and destination address and port
values in the "packet_info" structure are set appropriately).
In the "Follow TCP Connection" code, check to make sure that the
addresses are IPv4 addressses; ultimately, that code should be changed
to use the conversation code instead, which will let it handle IPv6
transparently.
svn path=/trunk/; revision=909
1999-10-22 07:18:23 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
if (tree) {
|
|
|
|
/* !!! specify length */
|
2001-04-23 03:37:31 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_ipv6, tvb, offset, 40, FALSE);
|
1999-11-16 11:44:20 +00:00
|
|
|
ipv6_tree = proto_item_add_subtree(ti, ett_ipv6);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
/* !!! warning: version also contains 4 Bit priority */
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint(ipv6_tree, hf_ipv6_version, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_vfc), 1,
|
1999-10-15 04:22:48 +00:00
|
|
|
(ipv6.ip6_vfc >> 4) & 0x0f);
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint(ipv6_tree, hf_ipv6_class, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_flow), 4,
|
2002-08-02 23:36:07 +00:00
|
|
|
(guint8)((g_ntohl(ipv6.ip6_flow) >> 20) & 0xff));
|
1999-04-09 13:32:31 +00:00
|
|
|
|
1999-10-15 04:22:48 +00:00
|
|
|
/*
|
|
|
|
* there should be no alignment problems for ip6_flow, since it's the first
|
|
|
|
* guint32 in the ipv6 struct
|
|
|
|
*/
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint_format(ipv6_tree, hf_ipv6_flow, tvb,
|
1999-04-09 13:32:31 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_flow), 4,
|
2002-08-02 23:36:07 +00:00
|
|
|
(unsigned long)(g_ntohl(ipv6.ip6_flow) & IPV6_FLOWLABEL_MASK),
|
1999-08-03 03:48:04 +00:00
|
|
|
"Flowlabel: 0x%05lx",
|
2002-08-02 23:36:07 +00:00
|
|
|
(unsigned long)(g_ntohl(ipv6.ip6_flow) & IPV6_FLOWLABEL_MASK));
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint(ipv6_tree, hf_ipv6_plen, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_plen), 2,
|
2001-06-08 08:30:42 +00:00
|
|
|
plen);
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint_format(ipv6_tree, hf_ipv6_nxt, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_nxt), 1,
|
1999-10-15 04:22:48 +00:00
|
|
|
ipv6.ip6_nxt,
|
1999-10-14 03:50:51 +00:00
|
|
|
"Next header: %s (0x%02x)",
|
|
|
|
ipprotostr(ipv6.ip6_nxt), ipv6.ip6_nxt);
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint(ipv6_tree, hf_ipv6_hlim, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_hlim), 1,
|
1999-10-15 04:22:48 +00:00
|
|
|
ipv6.ip6_hlim);
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2001-06-26 17:31:36 +00:00
|
|
|
proto_tree_add_ipv6_hidden(ipv6_tree, hf_ipv6_addr, tvb,
|
2000-08-11 22:18:22 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_src), 16,
|
|
|
|
ipv6.ip6_src.s6_addr8);
|
2001-06-26 17:31:36 +00:00
|
|
|
proto_tree_add_ipv6_hidden(ipv6_tree, hf_ipv6_addr, tvb,
|
2000-08-11 22:18:22 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_dst), 16,
|
|
|
|
ipv6.ip6_dst.s6_addr8);
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_ipv6_format(ipv6_tree, hf_ipv6_src, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_src), 16,
|
2000-03-14 06:03:26 +00:00
|
|
|
(guint8 *)&ipv6.ip6_src,
|
1999-03-28 18:32:03 +00:00
|
|
|
#ifdef INET6
|
|
|
|
"Source address: %s (%s)",
|
|
|
|
get_hostname6(&ipv6.ip6_src),
|
|
|
|
#else
|
|
|
|
"Source address: %s",
|
|
|
|
#endif
|
|
|
|
ip6_to_str(&ipv6.ip6_src));
|
|
|
|
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_ipv6_format(ipv6_tree, hf_ipv6_dst, tvb,
|
1999-03-28 18:32:03 +00:00
|
|
|
offset + offsetof(struct ip6_hdr, ip6_dst), 16,
|
2000-03-14 06:03:26 +00:00
|
|
|
(guint8 *)&ipv6.ip6_dst,
|
1999-03-28 18:32:03 +00:00
|
|
|
#ifdef INET6
|
|
|
|
"Destination address: %s (%s)",
|
|
|
|
get_hostname6(&ipv6.ip6_dst),
|
|
|
|
#else
|
|
|
|
"Destination address: %s",
|
|
|
|
#endif
|
|
|
|
ip6_to_str(&ipv6.ip6_dst));
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* start of the new header (could be a extension header) */
|
2001-04-23 03:37:31 +00:00
|
|
|
poffset = offset + offsetof(struct ip6_hdr, ip6_nxt);
|
|
|
|
nxt = tvb_get_guint8(tvb, poffset);
|
1999-10-15 04:22:48 +00:00
|
|
|
offset += sizeof(struct ip6_hdr);
|
2001-06-08 08:30:42 +00:00
|
|
|
offlg = 0;
|
|
|
|
ident = 0;
|
1999-03-28 18:32:03 +00:00
|
|
|
|
2002-05-02 08:55:52 +00:00
|
|
|
/* start out assuming this isn't fragmented, and has none of the other
|
|
|
|
non-final headers */
|
|
|
|
hopopts = FALSE;
|
|
|
|
routing = FALSE;
|
2001-06-08 08:30:42 +00:00
|
|
|
frag = FALSE;
|
2002-05-02 08:55:52 +00:00
|
|
|
ah = FALSE;
|
|
|
|
dstopts = FALSE;
|
2000-12-14 18:56:22 +00:00
|
|
|
|
1999-03-28 18:32:03 +00:00
|
|
|
again:
|
2001-06-08 08:30:42 +00:00
|
|
|
switch (nxt) {
|
|
|
|
case IP_PROTO_HOPOPTS:
|
2002-05-02 08:55:52 +00:00
|
|
|
hopopts = TRUE;
|
2001-04-23 03:37:31 +00:00
|
|
|
advance = dissect_hopopts(tvb, offset, tree);
|
|
|
|
nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
poffset = offset;
|
2001-01-23 02:49:55 +00:00
|
|
|
offset += advance;
|
2001-06-08 08:30:42 +00:00
|
|
|
plen -= advance;
|
2001-01-23 02:49:55 +00:00
|
|
|
goto again;
|
1999-03-28 18:32:03 +00:00
|
|
|
case IP_PROTO_ROUTING:
|
2002-05-02 08:55:52 +00:00
|
|
|
routing = TRUE;
|
2001-04-23 03:37:31 +00:00
|
|
|
advance = dissect_routing6(tvb, offset, tree);
|
|
|
|
nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
poffset = offset;
|
2001-01-23 02:49:55 +00:00
|
|
|
offset += advance;
|
2001-06-08 08:30:42 +00:00
|
|
|
plen -= advance;
|
2001-01-23 02:49:55 +00:00
|
|
|
goto again;
|
1999-03-28 18:32:03 +00:00
|
|
|
case IP_PROTO_FRAGMENT:
|
2001-06-08 08:30:42 +00:00
|
|
|
frag = TRUE;
|
|
|
|
advance = dissect_frag6(tvb, offset, pinfo, tree,
|
|
|
|
&offlg, &ident);
|
2001-04-23 03:37:31 +00:00
|
|
|
nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
poffset = offset;
|
2001-01-23 02:49:55 +00:00
|
|
|
offset += advance;
|
2001-06-08 08:30:42 +00:00
|
|
|
plen -= advance;
|
2001-01-23 02:49:55 +00:00
|
|
|
goto again;
|
1999-03-28 18:32:03 +00:00
|
|
|
case IP_PROTO_AH:
|
2002-05-02 08:55:52 +00:00
|
|
|
ah = TRUE;
|
2001-04-23 03:37:31 +00:00
|
|
|
advance = dissect_ah_header(
|
|
|
|
tvb_new_subset(tvb, offset, -1, -1),
|
|
|
|
pinfo, tree, NULL, NULL);
|
|
|
|
nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
poffset = offset;
|
2001-01-23 02:49:55 +00:00
|
|
|
offset += advance;
|
2001-06-08 08:30:42 +00:00
|
|
|
plen -= advance;
|
2001-04-23 03:37:31 +00:00
|
|
|
goto again;
|
1999-03-28 18:32:03 +00:00
|
|
|
case IP_PROTO_DSTOPTS:
|
2002-05-02 08:55:52 +00:00
|
|
|
dstopts = TRUE;
|
2001-04-23 03:37:31 +00:00
|
|
|
advance = dissect_dstopts(tvb, offset, tree);
|
|
|
|
nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
poffset = offset;
|
2001-01-23 02:49:55 +00:00
|
|
|
offset += advance;
|
2001-06-08 08:30:42 +00:00
|
|
|
plen -= advance;
|
2001-01-23 02:49:55 +00:00
|
|
|
goto again;
|
2000-04-20 07:05:58 +00:00
|
|
|
}
|
|
|
|
|
1999-10-15 04:22:48 +00:00
|
|
|
#ifdef TEST_FINALHDR
|
2001-04-23 03:37:31 +00:00
|
|
|
proto_tree_add_uint_hidden(ipv6_tree, hf_ipv6_final, tvb, poffset, 1, nxt);
|
1999-10-15 04:22:48 +00:00
|
|
|
#endif
|
2001-06-08 08:30:42 +00:00
|
|
|
|
2002-01-20 01:04:18 +00:00
|
|
|
/* If ipv6_reassemble is on, this is a fragment, and we have all the data
|
|
|
|
* in the fragment, then just add the fragment to the hashtable.
|
2001-06-08 08:30:42 +00:00
|
|
|
*/
|
Use the "fragmented" field of the "packet_info" structure in
"dissect_frame()" to indicate whether a ReportedBoundsError was due to
the packet being malformed (i.e., the packet was shorter than it's
supposed to be, so the dissector went past the end trying to extract
fields that were supposed to be there) or due to it not being
reassembled (i.e., the packet was fragmented, and we didn't reassemble
it, but just treated the first fragment as the entire packet, so the
dissector went past the end trying to extract fields that were partially
or completely in fragments after that). Mark the latter as being
unreasembled rather than malformed.
Properly initialize, save, and restore that field, and properly set it,
so that works.
svn path=/trunk/; revision=4555
2002-01-17 06:29:20 +00:00
|
|
|
save_fragmented = pinfo->fragmented;
|
2003-03-04 06:47:10 +00:00
|
|
|
if (ipv6_reassemble && frag && tvb_bytes_exist(tvb, offset, plen)) {
|
Use "fragment_add_check()" for IPv6 and CLNP reassembly. (Possibly an
issue for CLNP, with its 16-bit IDs, which could be duplicated in a
sufficiently large capture even if CLNP implementations don't
deliberately reuse IDs; less of an issue for IPv6, with its 32-bit IDs
and with its prohibition on reuse:
For every packet that is to be fragmented, the source node generates
an Identification value. The Identification must be different than
that of any other fragmented packet sent recently* with the same
Source Address and Destination Address. If a Routing header is
present, the Destination Address of concern is that of the final
destination.
* "recently" means within the maximum likely lifetime of a packet,
including transit time from source to destination and time spent
awaiting reassembly with other fragments of the same packet.
However, it is not required that a source node know the maximum
packet lifetime. Rather, it is assumed that the requirement can
be met by maintaining the Identification value as a simple, 32-
bit, "wrap-around" counter, incremented each time a packet must
be fragmented. It is an implementation choice whether to
maintain a single counter for the node or multiple counters,
e.g., one for each of the node's possible source addresses, or
one for each active (source address, destination address)
combination.
but perhaps we'll ultimately be able to get rid of the old
"fragment_add()" entirely and rename "fragment_add_check()" to
"fragment_add()").
svn path=/trunk/; revision=7507
2003-04-20 00:21:17 +00:00
|
|
|
ipfd_head = fragment_add_check(tvb, offset, pinfo, ident,
|
2002-01-20 01:04:18 +00:00
|
|
|
ipv6_fragment_table,
|
Use "fragment_add_check()" for IPv6 and CLNP reassembly. (Possibly an
issue for CLNP, with its 16-bit IDs, which could be duplicated in a
sufficiently large capture even if CLNP implementations don't
deliberately reuse IDs; less of an issue for IPv6, with its 32-bit IDs
and with its prohibition on reuse:
For every packet that is to be fragmented, the source node generates
an Identification value. The Identification must be different than
that of any other fragmented packet sent recently* with the same
Source Address and Destination Address. If a Routing header is
present, the Destination Address of concern is that of the final
destination.
* "recently" means within the maximum likely lifetime of a packet,
including transit time from source to destination and time spent
awaiting reassembly with other fragments of the same packet.
However, it is not required that a source node know the maximum
packet lifetime. Rather, it is assumed that the requirement can
be met by maintaining the Identification value as a simple, 32-
bit, "wrap-around" counter, incremented each time a packet must
be fragmented. It is an implementation choice whether to
maintain a single counter for the node or multiple counters,
e.g., one for each of the node's possible source addresses, or
one for each active (source address, destination address)
combination.
but perhaps we'll ultimately be able to get rid of the old
"fragment_add()" entirely and rename "fragment_add_check()" to
"fragment_add()").
svn path=/trunk/; revision=7507
2003-04-20 00:21:17 +00:00
|
|
|
ipv6_reassembled_table,
|
2002-01-20 01:04:18 +00:00
|
|
|
offlg & IP6F_OFF_MASK,
|
|
|
|
plen,
|
|
|
|
offlg & IP6F_MORE_FRAG);
|
2003-04-20 11:36:16 +00:00
|
|
|
|
2003-08-28 04:19:29 +00:00
|
|
|
next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv6",
|
2003-04-20 11:36:16 +00:00
|
|
|
ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
|
2001-06-08 08:30:42 +00:00
|
|
|
} else {
|
|
|
|
/* If this is the first fragment, dissect its contents, otherwise
|
|
|
|
just show it as a fragment.
|
|
|
|
|
|
|
|
XXX - if we eventually don't save the reassembled contents of all
|
|
|
|
fragmented datagrams, we may want to always reassemble. */
|
|
|
|
if (offlg & IP6F_OFF_MASK) {
|
|
|
|
/* Not the first fragment - don't dissect it. */
|
|
|
|
next_tvb = NULL;
|
|
|
|
} else {
|
|
|
|
/* First fragment, or not fragmented. Dissect what we have here. */
|
|
|
|
|
|
|
|
/* Get a tvbuff for the payload. */
|
|
|
|
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is the first fragment, but not the only fragment,
|
|
|
|
* tell the next protocol that.
|
|
|
|
*/
|
|
|
|
if (offlg & IP6F_MORE_FRAG)
|
|
|
|
pinfo->fragmented = TRUE;
|
|
|
|
else
|
|
|
|
pinfo->fragmented = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next_tvb == NULL) {
|
|
|
|
/* Just show this as a fragment. */
|
2000-04-20 07:05:58 +00:00
|
|
|
/* COL_INFO was filled in by "dissect_frag6()" */
|
2002-05-02 08:55:52 +00:00
|
|
|
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
/* As we haven't reassembled anything, we haven't changed "pi", so
|
|
|
|
we don't have to restore it. */
|
Use the "fragmented" field of the "packet_info" structure in
"dissect_frame()" to indicate whether a ReportedBoundsError was due to
the packet being malformed (i.e., the packet was shorter than it's
supposed to be, so the dissector went past the end trying to extract
fields that were supposed to be there) or due to it not being
reassembled (i.e., the packet was fragmented, and we didn't reassemble
it, but just treated the first fragment as the entire packet, so the
dissector went past the end trying to extract fields that were partially
or completely in fragments after that). Mark the latter as being
unreasembled rather than malformed.
Properly initialize, save, and restore that field, and properly set it,
so that works.
svn path=/trunk/; revision=4555
2002-01-17 06:29:20 +00:00
|
|
|
pinfo->fragmented = save_fragmented;
|
2001-06-08 08:30:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do lookup with the subdissector table */
|
|
|
|
if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
|
2002-05-02 08:55:52 +00:00
|
|
|
/* Unknown protocol.
|
|
|
|
Handle "no next header" specially. */
|
|
|
|
if (nxt == IP_PROTO_NONE) {
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
|
|
|
/* If we had an Authentication Header, the AH dissector already
|
|
|
|
put something in the Info column; leave it there. */
|
|
|
|
if (!ah) {
|
|
|
|
if (hopopts || routing || dstopts) {
|
2002-05-02 11:52:52 +00:00
|
|
|
char *sep = "IPv6 ";
|
2002-05-02 08:55:52 +00:00
|
|
|
if (hopopts) {
|
2002-05-02 11:52:52 +00:00
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "%shop-by-hop options",
|
|
|
|
sep);
|
2002-05-02 08:55:52 +00:00
|
|
|
sep = ", ";
|
|
|
|
}
|
|
|
|
if (routing) {
|
2002-05-02 11:52:52 +00:00
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "%srouting", sep);
|
2002-05-02 08:55:52 +00:00
|
|
|
sep = ", ";
|
|
|
|
}
|
|
|
|
if (dstopts) {
|
2002-05-02 11:52:52 +00:00
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "%sdestination options",
|
|
|
|
sep);
|
2002-05-02 08:55:52 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "IPv6 no next header");
|
|
|
|
}
|
|
|
|
}
|
2001-06-26 17:31:36 +00:00
|
|
|
} else {
|
2002-05-02 08:55:52 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(nxt),nxt);
|
2001-06-26 17:31:36 +00:00
|
|
|
}
|
2002-05-02 08:55:52 +00:00
|
|
|
call_dissector(data_handle, next_tvb, pinfo, tree);
|
|
|
|
}
|
|
|
|
pinfo->fragmented = save_fragmented;
|
1999-03-28 18:32:03 +00:00
|
|
|
}
|
|
|
|
|
1999-07-29 05:47:07 +00:00
|
|
|
void
|
|
|
|
proto_register_ipv6(void)
|
|
|
|
{
|
1999-10-11 17:05:49 +00:00
|
|
|
static hf_register_info hf[] = {
|
1999-10-15 04:22:48 +00:00
|
|
|
{ &hf_ipv6_version,
|
|
|
|
{ "Version", "ipv6.version",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
|
1999-10-15 04:22:48 +00:00
|
|
|
{ &hf_ipv6_class,
|
|
|
|
{ "Traffic class", "ipv6.class",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
|
1999-10-15 04:22:48 +00:00
|
|
|
{ &hf_ipv6_flow,
|
|
|
|
{ "Flowlabel", "ipv6.flow",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
1999-10-15 04:22:48 +00:00
|
|
|
{ &hf_ipv6_plen,
|
|
|
|
{ "Payload length", "ipv6.plen",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
1999-10-15 04:22:48 +00:00
|
|
|
{ &hf_ipv6_nxt,
|
|
|
|
{ "Next header", "ipv6.nxt",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
|
1999-10-15 04:22:48 +00:00
|
|
|
{ &hf_ipv6_hlim,
|
|
|
|
{ "Hop limit", "ipv6.hlim",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
|
1999-10-11 17:05:49 +00:00
|
|
|
{ &hf_ipv6_src,
|
1999-10-15 04:22:48 +00:00
|
|
|
{ "Source", "ipv6.src",
|
|
|
|
FT_IPv6, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Source IPv6 Address", HFILL }},
|
1999-10-11 17:05:49 +00:00
|
|
|
{ &hf_ipv6_dst,
|
1999-10-15 04:22:48 +00:00
|
|
|
{ "Destination", "ipv6.dst",
|
|
|
|
FT_IPv6, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Destination IPv6 Address", HFILL }},
|
2000-08-11 22:18:22 +00:00
|
|
|
{ &hf_ipv6_addr,
|
|
|
|
{ "Address", "ipv6.addr",
|
|
|
|
FT_IPv6, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Source or Destination IPv6 Address", HFILL }},
|
2001-01-23 02:49:55 +00:00
|
|
|
|
2001-06-08 08:30:42 +00:00
|
|
|
{ &hf_ipv6_fragment_overlap,
|
|
|
|
{ "Fragment overlap", "ipv6.fragment.overlap",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Fragment overlaps with other fragments", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
{ &hf_ipv6_fragment_overlap_conflict,
|
|
|
|
{ "Conflicting data in fragment overlap", "ipv6.fragment.overlap.conflict",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Overlapping fragments contained conflicting data", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
{ &hf_ipv6_fragment_multiple_tails,
|
|
|
|
{ "Multiple tail fragments found", "ipv6.fragment.multipletails",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Several tails were found when defragmenting the packet", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
{ &hf_ipv6_fragment_too_long_fragment,
|
|
|
|
{ "Fragment too long", "ipv6.fragment.toolongfragment",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Fragment contained data past end of packet", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
{ &hf_ipv6_fragment_error,
|
|
|
|
{ "Defragmentation error", "ipv6.fragment.error",
|
2002-12-19 11:22:38 +00:00
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Defragmentation error due to illegal fragments", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
{ &hf_ipv6_fragment,
|
|
|
|
{ "IPv6 Fragment", "ipv6.fragment",
|
2002-12-19 11:22:38 +00:00
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"IPv6 Fragment", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
|
|
|
{ &hf_ipv6_fragments,
|
|
|
|
{ "IPv6 Fragments", "ipv6.fragments",
|
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"IPv6 Fragments", HFILL }},
|
2001-06-08 08:30:42 +00:00
|
|
|
|
2003-04-20 08:06:01 +00:00
|
|
|
{ &hf_ipv6_reassembled_in,
|
|
|
|
{ "Reassembled IPv6 in frame", "ipv6.reassembled_in",
|
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
|
|
|
"This IPv6 packet is reassembled in this frame", HFILL }},
|
|
|
|
|
2003-02-04 20:17:01 +00:00
|
|
|
/* Mobile IPv6 */
|
2001-01-23 02:49:55 +00:00
|
|
|
{ &hf_ipv6_mipv6_type,
|
|
|
|
{ "Option Type ", "ipv6.mipv6_type",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2001-01-23 02:49:55 +00:00
|
|
|
{ &hf_ipv6_mipv6_length,
|
2003-02-04 20:17:01 +00:00
|
|
|
{ "Option Length ", "ipv6.mipv6_length",
|
2001-01-23 02:49:55 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2001-01-23 02:49:55 +00:00
|
|
|
{ &hf_ipv6_mipv6_home_address,
|
2003-02-04 20:17:01 +00:00
|
|
|
{ "Home Address ", "ipv6.mipv6_home_address",
|
2001-01-23 02:49:55 +00:00
|
|
|
FT_IPv6, BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2001-01-23 02:49:55 +00:00
|
|
|
|
1999-10-15 04:22:48 +00:00
|
|
|
#ifdef TEST_FINALHDR
|
|
|
|
{ &hf_ipv6_final,
|
|
|
|
{ "Final next header", "ipv6.final",
|
2001-06-18 02:18:27 +00:00
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
|
1999-10-15 04:22:48 +00:00
|
|
|
#endif
|
1999-10-11 17:05:49 +00:00
|
|
|
};
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_ipv6,
|
2001-06-08 08:30:42 +00:00
|
|
|
&ett_ipv6_fragments,
|
|
|
|
&ett_ipv6_fragment,
|
1999-11-16 11:44:20 +00:00
|
|
|
};
|
2001-06-08 08:30:42 +00:00
|
|
|
module_t *ipv6_module;
|
1999-10-11 17:05:49 +00:00
|
|
|
|
2001-01-23 02:49:55 +00:00
|
|
|
proto_ipv6 = proto_register_protocol("Internet Protocol Version 6", "IPv6", "ipv6");
|
1999-10-11 17:05:49 +00:00
|
|
|
proto_register_field_array(proto_ipv6, hf, array_length(hf));
|
1999-11-16 11:44:20 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2001-04-23 03:56:57 +00:00
|
|
|
|
2001-06-08 08:30:42 +00:00
|
|
|
/* Register configuration options */
|
|
|
|
ipv6_module = prefs_register_protocol(proto_ipv6, NULL);
|
|
|
|
prefs_register_bool_preference(ipv6_module, "defragment",
|
|
|
|
"Reassemble fragmented IPv6 datagrams",
|
|
|
|
"Whether fragmented IPv6 datagrams should be reassembled",
|
|
|
|
&ipv6_reassemble);
|
|
|
|
|
2001-04-23 03:56:57 +00:00
|
|
|
register_dissector("ipv6", dissect_ipv6, proto_ipv6);
|
2001-06-08 08:30:42 +00:00
|
|
|
register_init_routine(ipv6_reassemble_init);
|
1999-07-29 05:47:07 +00:00
|
|
|
}
|
Change the sub-dissector handoff registration routines so that the
sub-dissector table is not stored in the header_field_info struct, but
in a separate namespace. Dissector tables are now registered by name
and not by field ID. For example:
udp_dissector_table = register_dissector_table("udp.port");
Because of this different namespace, dissector tables can have names
that are not field names. This is useful for ethertype, since multiple
fields are "ethertypes".
packet-ethertype.c replaces ethertype.c (the name was changed so that it
would be named in the same fashion as all the filenames passed to make-reg-dotc)
Although it registers no protocol or field, it registers one dissector table:
ethertype_dissector_table = register_dissector_table("ethertype");
All protocols that can be called because of an ethertype field now register
that fact with dissector_add() calls.
In this way, one dissector_table services all ethertype fields
(hf_eth_type, hf_llc_type, hf_null_etype, hf_vlan_etype)
Furthermore, the code allows for names of protocols to exist in the
etype_vals, yet a dissector for that protocol doesn't exist. The name
of the dissector is printed in COL_INFO. You're welcome, Richard. :-)
svn path=/trunk/; revision=1848
2000-04-13 18:18:56 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_ipv6(void)
|
|
|
|
{
|
2002-05-02 08:55:52 +00:00
|
|
|
dissector_handle_t ipv6_handle;
|
2001-12-03 04:00:26 +00:00
|
|
|
|
2001-11-26 04:52:51 +00:00
|
|
|
data_handle = find_dissector("data");
|
2001-12-03 04:00:26 +00:00
|
|
|
ipv6_handle = find_dissector("ipv6");
|
|
|
|
dissector_add("ethertype", ETHERTYPE_IPv6, ipv6_handle);
|
|
|
|
dissector_add("ppp.protocol", PPP_IPV6, ipv6_handle);
|
|
|
|
dissector_add("ppp.protocol", ETHERTYPE_IPv6, ipv6_handle);
|
|
|
|
dissector_add("gre.proto", ETHERTYPE_IPv6, ipv6_handle);
|
|
|
|
dissector_add("ip.proto", IP_PROTO_IPV6, ipv6_handle);
|
|
|
|
dissector_add("null.type", BSD_AF_INET6_BSD, ipv6_handle);
|
|
|
|
dissector_add("null.type", BSD_AF_INET6_FREEBSD, ipv6_handle);
|
2002-07-30 07:25:29 +00:00
|
|
|
dissector_add("null.type", BSD_AF_INET6_DARWIN, ipv6_handle);
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_add("chdlctype", ETHERTYPE_IPv6, ipv6_handle);
|
|
|
|
dissector_add("fr.ietf", NLPID_IP6, ipv6_handle);
|
|
|
|
dissector_add("x.25.spi", NLPID_IP6, ipv6_handle);
|
2003-01-23 09:39:33 +00:00
|
|
|
dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPv6, ipv6_handle);
|
2003-04-29 17:24:35 +00:00
|
|
|
|
|
|
|
ip_dissector_table = find_dissector_table("ip.proto");
|
Change the sub-dissector handoff registration routines so that the
sub-dissector table is not stored in the header_field_info struct, but
in a separate namespace. Dissector tables are now registered by name
and not by field ID. For example:
udp_dissector_table = register_dissector_table("udp.port");
Because of this different namespace, dissector tables can have names
that are not field names. This is useful for ethertype, since multiple
fields are "ethertypes".
packet-ethertype.c replaces ethertype.c (the name was changed so that it
would be named in the same fashion as all the filenames passed to make-reg-dotc)
Although it registers no protocol or field, it registers one dissector table:
ethertype_dissector_table = register_dissector_table("ethertype");
All protocols that can be called because of an ethertype field now register
that fact with dissector_add() calls.
In this way, one dissector_table services all ethertype fields
(hf_eth_type, hf_llc_type, hf_null_etype, hf_vlan_etype)
Furthermore, the code allows for names of protocols to exist in the
etype_vals, yet a dissector for that protocol doesn't exist. The name
of the dissector is printed in COL_INFO. You're welcome, Richard. :-)
svn path=/trunk/; revision=1848
2000-04-13 18:18:56 +00:00
|
|
|
}
|