/* packet-ipv6.c
* Routines for IPv6 packet disassembly
*
- * $Id: packet-ipv6.c,v 1.62 2001/09/04 21:04:51 guy Exp $
+ * $Id: packet-ipv6.c,v 1.78 2002/02/27 05:45:48 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <string.h>
#include <stdio.h>
#include <glib.h>
-#include "packet.h"
+#include <epan/packet.h>
#include "packet-ip.h"
#include "packet-ipsec.h"
#include "packet-ipv6.h"
-#include "packet-tcp.h"
-#include "packet-udp.h"
-#include "resolv.h"
+#include <epan/resolv.h>
#include "prefs.h"
#include "reassemble.h"
#include "ipproto.h"
#include "etypes.h"
#include "ppptypes.h"
#include "aftypes.h"
+#include "nlpid.h"
/*
* NOTE: ipv6.nxt is not very useful as we will have chained header.
static gint ett_ipv6_fragments = -1;
static gint ett_ipv6_fragment = -1;
+static dissector_handle_t data_handle;
+
/* Reassemble fragmented datagrams */
static gboolean ipv6_reassemble = FALSE;
static int
dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree) {
struct ip6_rthdr rt;
- int len;
+ guint len;
proto_tree *rthdr_tree;
proto_item *ti;
char buf[sizeof(struct ip6_rthdr0) + sizeof(struct e_in6_addr) * 23];
frag.ip6f_offlg = ntohs(frag.ip6f_offlg);
*offlg = frag.ip6f_offlg;
*ident = frag.ip6f_ident;
- if (check_col(pinfo->fd, COL_INFO)) {
- col_add_fstr(pinfo->fd, COL_INFO,
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
"IPv6 fragment (nxt=%s (0x%02x) off=%u id=0x%x)",
ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt,
frag.ip6f_offlg & IP6F_OFF_MASK, frag.ip6f_ident);
int offset;
fragment_data *ipfd_head;
tvbuff_t *next_tvb;
- packet_info save_pi;
- gboolean must_restore_pi = FALSE;
gboolean update_col_info = TRUE;
+ gboolean save_fragmented;
struct ip6_hdr ipv6;
- if (check_col(pinfo->fd, COL_PROTOCOL))
- col_set_str(pinfo->fd, COL_PROTOCOL, "IPv6");
- if (check_col(pinfo->fd, COL_INFO))
- col_clear(pinfo->fd, COL_INFO);
+ 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);
offset = 0;
tvb_memcpy(tvb, (guint8 *)&ipv6, offset, sizeof(ipv6));
plen = ntohs(ipv6.ip6_plen);
/* Adjust the length of this tvbuff to include only the IPv6 datagram. */
- set_actual_length(tvb, pinfo, plen + sizeof (struct ip6_hdr));
+ set_actual_length(tvb, plen + sizeof (struct ip6_hdr));
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));
proto_tree_add_uint_hidden(ipv6_tree, hf_ipv6_final, tvb, poffset, 1, nxt);
#endif
- /* If ipv6_reassemble is on and this is a fragment, then just add the fragment
- * to the hashtable.
+ /* 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.
*/
- if (ipv6_reassemble && frag) {
- /* We're reassembling, and this is part of a fragmented datagram.
- Add the fragment to the hash table if the frame isn't truncated. */
- if (tvb_reported_length(tvb) <= tvb_length(tvb)) {
- ipfd_head = fragment_add(tvb, offset, pinfo, ident,
- ipv6_fragment_table,
- offlg & IP6F_OFF_MASK,
- plen,
- offlg & IP6F_MORE_FRAG);
- } else {
- ipfd_head = NULL;
- }
+ save_fragmented = pinfo->fragmented;
+ if (ipv6_reassemble && frag && tvb_reported_length(tvb) <= tvb_length(tvb)) {
+ ipfd_head = fragment_add(tvb, offset, pinfo, ident,
+ ipv6_fragment_table,
+ offlg & IP6F_OFF_MASK,
+ plen,
+ offlg & IP6F_MORE_FRAG);
if (ipfd_head != NULL) {
fragment_data *ipfd;
}
fei = proto_tree_add_none_format(ft, hf,
tvb, 0, 0,
- "Frame:%d payload:%d-%d",
+ "Frame:%u payload:%u-%u",
ipfd->frame,
ipfd->offset,
ipfd->offset+ipfd->len-1
/* nothing of interest for this fragment */
proto_tree_add_none_format(ft, hf_ipv6_fragment,
tvb, 0, 0,
- "Frame:%d payload:%d-%d",
+ "Frame:%u payload:%u-%u",
ipfd->frame,
ipfd->offset,
ipfd->offset+ipfd->len-1
}
if (ipfd_head->flags & (FD_OVERLAPCONFLICT
|FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
- if (check_col(pinfo->fd, COL_INFO)) {
- col_set_str(pinfo->fd, COL_INFO, "[Illegal fragments]");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "[Illegal fragments]");
update_col_info = FALSE;
}
}
/* Allocate a new tvbuff, referring to the reassembled payload. */
next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen,
- ipfd_head->datalen, "Reassembled");
+ ipfd_head->datalen);
/* Add the tvbuff to the list of tvbuffs to which the tvbuff we
were handed refers, so it'll get cleaned up when that tvbuff
tvb_set_child_real_data_tvbuff(tvb, next_tvb);
/* Add the defragmented data to the data source list. */
- pinfo->fd->data_src = g_slist_append(pinfo->fd->data_src, next_tvb);
+ add_new_data_source(pinfo->fd, next_tvb, "Reassembled IPv6");
/* It's not fragmented. */
pinfo->fragmented = FALSE;
-
- /* Save the current value of "pi", and adjust certain fields to
- reflect the new tvbuff. */
- save_pi = pi;
- pi.compat_top_tvb = next_tvb;
- pi.len = tvb_reported_length(next_tvb);
- pi.captured_len = tvb_length(next_tvb);
- must_restore_pi = TRUE;
} else {
/* We don't have the complete reassembled payload. */
next_tvb = NULL;
if (next_tvb == NULL) {
/* Just show this as a fragment. */
/* COL_INFO was filled in by "dissect_frag6()" */
- dissect_data(tvb, offset, pinfo, tree);
+ call_dissector(data_handle,tvb_new_subset(tvb, offset, -1,tvb_reported_length_remaining(tvb,offset)),pinfo, tree);
/* As we haven't reassembled anything, we haven't changed "pi", so
we don't have to restore it. */
+ pinfo->fragmented = save_fragmented;
return;
}
/* do lookup with the subdissector table */
if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
/* Unknown protocol */
- if (check_col(pinfo->fd, COL_INFO))
- col_add_fstr(pinfo->fd, COL_INFO, "%s (0x%02x)", ipprotostr(nxt),nxt);
- dissect_data(next_tvb, 0, pinfo, tree);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(nxt),nxt);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
}
+ pinfo->fragmented = save_fragmented;
}
static void
dissect_ipv6_none(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (hf_ipv6_mipv6_length != -1) {
- if (check_col(pinfo->fd, COL_INFO))
- col_add_fstr(pinfo->fd, COL_INFO, "Mobile IPv6 Destination Option");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Mobile IPv6 Destination Option");
} else {
- if (check_col(pinfo->fd, COL_INFO))
- col_add_fstr(pinfo->fd, COL_INFO, "IPv6 no next header");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "IPv6 no next header");
}
/* XXX - dissect the payload as padding? */
}
void
proto_reg_handoff_ipv6(void)
{
- dissector_add("ethertype", ETHERTYPE_IPv6, dissect_ipv6, proto_ipv6);
- dissector_add("ppp.protocol", PPP_IPV6, dissect_ipv6, proto_ipv6);
- dissector_add("ip.proto", IP_PROTO_IPV6, dissect_ipv6, proto_ipv6);
- dissector_add("null.type", BSD_AF_INET6_BSD, dissect_ipv6, proto_ipv6);
- dissector_add("null.type", BSD_AF_INET6_FREEBSD, dissect_ipv6, proto_ipv6);
- dissector_add("ip.proto", IP_PROTO_NONE, dissect_ipv6_none, proto_ipv6);
+ dissector_handle_t ipv6_handle, ipv6_none_handle;
+
+ data_handle = find_dissector("data");
+ 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);
+ ipv6_none_handle = create_dissector_handle(dissect_ipv6_none, proto_ipv6);
+ dissector_add("ip.proto", IP_PROTO_NONE, ipv6_none_handle);
+ dissector_add("null.type", BSD_AF_INET6_BSD, ipv6_handle);
+ dissector_add("null.type", BSD_AF_INET6_FREEBSD, ipv6_handle);
+ dissector_add("chdlctype", ETHERTYPE_IPv6, ipv6_handle);
+ dissector_add("fr.ietf", NLPID_IP6, ipv6_handle);
+ dissector_add("x.25.spi", NLPID_IP6, ipv6_handle);
}