Update dissect_ndr_nt_STRING so it can also accept FT_BYTES and for that type
[obnox/wireshark/wip.git] / packet-ipv6.c
index 5288f8f424fc1d7be989e6465dead44bd6155b82..2d23f17e69e1d6e95c0fb0bf8d4b9881811445e1 100644 (file)
@@ -1,7 +1,7 @@
 /* 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.
@@ -107,6 +106,8 @@ static gint ett_ipv6 = -1;
 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;
 
@@ -128,7 +129,7 @@ ipv6_reassemble_init(void)
 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];
@@ -197,8 +198,8 @@ dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
     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);
@@ -655,16 +656,15 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   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));
@@ -675,7 +675,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   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));
@@ -807,21 +807,16 @@ again:
   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;
@@ -851,7 +846,7 @@ again:
           }
           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
@@ -881,7 +876,7 @@ again:
           /* 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
@@ -890,15 +885,15 @@ again:
       }
       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
@@ -906,18 +901,10 @@ again:
       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;
@@ -951,31 +938,33 @@ again:
   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? */
 }
@@ -1162,10 +1151,20 @@ proto_register_ipv6(void)
 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);
 }