From Joerg Mayer: get rid of extra arguments to capture routines.
[obnox/wireshark/wip.git] / packet-vines.c
index f5b3895ce4bf02b72478418f0be0c63f522d8a85..e70845e3bfff2786cc145532503e5236a80ba49c 100644 (file)
@@ -1,15 +1,14 @@
 /* packet-vines.c
  * Routines for Banyan VINES protocol packet disassembly
  *
- * $Id: packet-vines.c,v 1.10 1999/11/16 11:43:02 guy Exp $
+ * $Id: packet-vines.c,v 1.40 2002/04/24 06:03:34 guy Exp $
  *
  * Don Lafontaine <lafont02@cn.ca>
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
- * Joerg Mayer <jmayer@telemation.de>
- *
+ * Joerg Mayer <jmayer@loplof.de>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -26,7 +25,9 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #include <netinet/in.h>
 #endif
 
+#include <string.h>
 #include <glib.h>
-#include "packet.h"
+#include <epan/packet.h>
 #include "packet-vines.h"
+#include "etypes.h"
+#include "ppptypes.h"
+#include "ipproto.h"
+
+#define UDP_PORT_VINES 573
+
+static int proto_vines = -1;
+static int hf_vines_protocol = -1;
 
 static gint ett_vines = -1;
+
+static int proto_vines_frp = -1;
+
 static gint ett_vines_frp = -1;
+
+static int proto_vines_spp = -1;
+
 static gint ett_vines_spp = -1;
 
-/* AFAIK Vines FRP (Fragmentation Protocol) is used on all media except Ethernet
- * and TR (and probably FDDI) - Fragmentation on these media types is not possible
+static void dissect_vines_frp(tvbuff_t *, packet_info *, proto_tree *);
+#if 0
+static void dissect_vines_arp(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_vines_icp(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_vines_ipc(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_vines_rtp(tvbuff_t *, packet_info *, proto_tree *);
+#endif
+static void dissect_vines_spp(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_vines(tvbuff_t *, packet_info *, proto_tree *);
+
+void
+capture_vines(packet_counts *ld)
+{
+       ld->vines++;
+}
+
+static dissector_handle_t vines_handle;
+static dissector_handle_t data_handle;
+
+/* AFAIK Vines FRP (Fragmentation Protocol) is used on all media except
+ * Ethernet and TR (and probably FDDI) - Fragmentation on these media types
+ * is not possible
  * FIXME: Do we need to use this header with PPP too?
  */
+static void
+dissect_vines_frp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       guint8   vines_frp_ctrl;
+       proto_tree *vines_frp_tree;
+       proto_item *ti;
+       gchar   frp_flags_str[32];
+       tvbuff_t *next_tvb;
 
-void
-dissect_vines_frp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
-  guint8   vines_frp_ctrl, vines_frp_seqno; 
-  proto_tree *vines_frp_tree;
-  proto_item *ti;
-  gchar        frp_flags_str[32];
-
-  /* To do: Check for {cap len,pkt len} < struct len */
-  /* Avoids alignment problems on many architectures. */
-  vines_frp_ctrl = pd[offset];
-  vines_frp_seqno = pd[offset+1];
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines FRP");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
+
+       if (tree) {
+               ti = proto_tree_add_item(tree, proto_vines_frp, tvb, 0, 2,
+                   FALSE);
+               vines_frp_tree = proto_item_add_subtree(ti, ett_vines_frp);
+
+               vines_frp_ctrl = tvb_get_guint8(tvb, 0);
   
-  if (check_col(fd, COL_PROTOCOL))
-    col_add_str(fd, COL_PROTOCOL, "Vines FRP");
-  /*
-   * 1: first fragment of vines packet
-   * 2: last fragment of vines packet
-   * 4 ... 80: unused
-   */
-  switch (vines_frp_ctrl) {
-  case 0:
-    strcpy(frp_flags_str, "middle");
-    break;
-  case 1:
-    strcpy(frp_flags_str, "first");
-    break;
-  case 2:
-    strcpy(frp_flags_str, "last");
-    break;
-  case 3:
-    strcpy(frp_flags_str, "only");
-    break;
-  default:
-    strcpy(frp_flags_str, "please report: unknown");
-    break;
-  }
+               /*
+                * 1: first fragment of vines packet
+                * 2: last fragment of vines packet
+                * 4 ... 80: unused
+                */
+               switch (vines_frp_ctrl) {
+
+               case 0:
+                       strcpy(frp_flags_str, "middle");
+                       break;
+
+               case 1:
+                       strcpy(frp_flags_str, "first");
+                       break;
+
+               case 2:
+                       strcpy(frp_flags_str, "last");
+                       break;
+
+               case 3:
+                       strcpy(frp_flags_str, "only");
+                       break;
+
+               default:
+                       strcpy(frp_flags_str, "please report: unknown");
+                       break;
+               }
   
-  if (tree) {
-    ti = proto_tree_add_text(tree, offset, 2, "Vines Fragmentation Protocol");
-    vines_frp_tree = proto_item_add_subtree(ti, ett_vines_frp);
-    proto_tree_add_text(vines_frp_tree, offset,     1, "Control Flags: 0x%02x = %s fragment", vines_frp_ctrl, frp_flags_str);
-    proto_tree_add_text(vines_frp_tree, offset + 1, 1, "Sequence Number: 0x%02x", vines_frp_seqno);
-  }
-
-  /* Skip over header */
-  offset += 2;
-
-  /* Decode the "real" Vines now */
-  dissect_vines(pd, offset, fd, tree);
+               proto_tree_add_text(vines_frp_tree, tvb, 0, 1, 
+                                   "Control Flags: 0x%02x = %s fragment", 
+                                   vines_frp_ctrl, frp_flags_str);
+
+               proto_tree_add_text(vines_frp_tree, tvb, 1, 1, 
+                                   "Sequence Number: 0x%02x",
+                                   tvb_get_guint8(tvb, 1));
+       }
+
+       /* Decode the "real" Vines now */
+       next_tvb = tvb_new_subset(tvb, 2, -1, -1);
+       call_dissector(vines_handle, next_tvb, pinfo, tree);
 }
 
-gchar *
-vines_addr_to_str(const guint8 *addrp)
+void
+proto_register_vines_frp(void)
 {
-  static gchar str[3][214];
-  static gchar *cur;
-
-  if (cur == &str[0][0]) {
-    cur = &str[1][0];
-  } else if (cur == &str[1][0]) {
-    cur = &str[2][0];
-  } else {
-    cur = &str[0][0];
-  }
-
-  sprintf(cur, "%08x.%04x", pntohl(&addrp[0]), pntohs(&addrp[4]));
-  return cur;
+       static gint *ett[] = {
+               &ett_vines_frp,
+       };
+
+       proto_vines_frp = proto_register_protocol(
+           "Banyan Vines Fragmentation Protocol", "Vines FRP", "vines_frp");
+       proto_register_subtree_array(ett, array_length(ett));
 }
 
 void
-dissect_vines(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
-       {
-       e_vip       viph;
-       proto_tree *vip_tree;
+proto_reg_handoff_vines_frp(void)
+{
+       dissector_handle_t vines_frp_handle;
+
+       vines_frp_handle = create_dissector_handle(dissect_vines_frp,
+           proto_vines_frp);
+       dissector_add("ip.proto", IP_PROTO_VINES, vines_frp_handle);
+
+       /* XXX: AFAIK, src and dst port must be the same; should
+          the dissector check for that? */
+       dissector_add("udp.port", UDP_PORT_VINES, vines_frp_handle);
+}
+
+static dissector_table_t vines_dissector_table;
+
+static void
+dissect_vines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       int         offset = 0;
+       e_vip       viph;
+       proto_tree *vip_tree;
        proto_item *ti;
-/*     gchar      tos_str[32]; */
+/*     gchar      tos_str[32]; */
+       const guint8     *dst_addr, *src_addr;
        int  is_broadcast = 0;
        int  hops = 0;
+       tvbuff_t *next_tvb;
+
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
+
+       /* To do: check for runts, errs, etc. */
+
+       /* Avoids alignment problems on many architectures. */
+       tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vip));
 
-  /* To do: check for runts, errs, etc. */
-  /* Avoids alignment problems on many architectures. */
-       memcpy(&viph, &pd[offset], sizeof(e_vip));
-
-       viph.vip_chksum = pntohs(&pd[offset]);
-       viph.vip_pktlen = pntohs(&pd[offset+2]);
-       viph.vip_dnet = pntohl(&pd[offset+6]);
-       viph.vip_dsub = pntohs(&pd[offset+10]);
-       viph.vip_snet = pntohl(&pd[offset+12]);
-       viph.vip_ssub = pntohs(&pd[offset+16]);
-
-       switch (viph.vip_proto) {
-               case VIP_PROTO_IPC:
-               if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "Vines IPC");
-               if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "IPC (%02x)", viph.vip_proto);
+       viph.vip_chksum = ntohs(viph.vip_chksum);
+       viph.vip_pktlen = ntohs(viph.vip_pktlen);
+       viph.vip_dnet = ntohl(viph.vip_dnet);
+       viph.vip_dsub = ntohs(viph.vip_dsub);
+       viph.vip_snet = ntohl(viph.vip_snet);
+       viph.vip_ssub = ntohs(viph.vip_ssub);
+
+       switch (viph.vip_proto) {
+       case VIP_PROTO_IPC:
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines IPC");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "IPC (%02x)", viph.vip_proto);
                break;
-               case VIP_PROTO_SPP:      
-               if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "Vines SPP");
-               if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "SPP (%02x)", viph.vip_proto);
+       case VIP_PROTO_SPP:      
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines SPP");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "SPP (%02x)", viph.vip_proto);
                break;
        case VIP_PROTO_ARP:
-               if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "Vines ARP");
-               if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "ARP (%02x)", viph.vip_proto);
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines ARP");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "ARP (%02x)", viph.vip_proto);
                break;
        case VIP_PROTO_RTP:
-               if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "Vines RTP");
-               if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "RTP (%02x)", viph.vip_proto);
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines RTP");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "RTP (%02x)", viph.vip_proto);
                break;
        case VIP_PROTO_ICP:
-               if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "Vines ICP");
-               if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "ICP (%02x)", viph.vip_proto);
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines ICP");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "ICP (%02x)", viph.vip_proto);
                break;
        default:
-               if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "Vines IP");
-               if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "Unknown VIP protocol (%02x)", viph.vip_proto);
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines IP");
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown VIP protocol (%02x)", 
+                                    viph.vip_proto);
        }
 
-       SET_ADDRESS(&pi.net_src, AT_VINES, 6, &pd[offset+12]);
-       SET_ADDRESS(&pi.src, AT_VINES, 6, &pd[offset+12]);
-       SET_ADDRESS(&pi.net_dst, AT_VINES, 6, &pd[offset+6]);
-       SET_ADDRESS(&pi.dst, AT_VINES, 6, &pd[offset+6]);
+       src_addr = tvb_get_ptr(tvb, offset+12, VINES_ADDR_LEN);
+       SET_ADDRESS(&pinfo->net_src, AT_VINES, VINES_ADDR_LEN, src_addr);
+       SET_ADDRESS(&pinfo->src, AT_VINES, VINES_ADDR_LEN, src_addr);
+       dst_addr = tvb_get_ptr(tvb, offset+6, VINES_ADDR_LEN);
+       SET_ADDRESS(&pinfo->net_dst, AT_VINES, VINES_ADDR_LEN,dst_addr);
+       SET_ADDRESS(&pinfo->dst, AT_VINES, VINES_ADDR_LEN, dst_addr);
 
        /* helpers to decode flags */
        /* FIXME: Not used yet */
@@ -189,141 +258,224 @@ dissect_vines(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
        }
        hops = viph.vip_tctl & 0xf; 
  
-  /*
-       viph.ip_tos = IPTOS_TOS(viph.ip_tos);
-       switch (viph.ip_tos) 
-               {
-       case IPTOS_NONE:
-               strcpy(tos_str, "None");
-               break;
-       case IPTOS_LOWDELAY:
-               strcpy(tos_str, "Minimize delay");
-               break;
-       case IPTOS_THROUGHPUT:
-               strcpy(tos_str, "Maximize throughput");
-               break;
-       case IPTOS_RELIABILITY:
-               strcpy(tos_str, "Maximize reliability");
-               break;
-       case IPTOS_LOWCOST:
-               strcpy(tos_str, "Minimize cost");
-               break;
-       default:
-               strcpy(tos_str, "Unknon.  Malformed?");
-               break;
-               }
-  */
-       if (tree) 
-               {
-       ti = proto_tree_add_text(tree, offset, (viph.vip_pktlen), "Vines IP");
-       vip_tree = proto_item_add_subtree(ti, ett_vines);
-       proto_tree_add_text(vip_tree, offset,      2, "Packet checksum: 0x%04x", viph.vip_chksum);
-       proto_tree_add_text(vip_tree, offset +  2, 2, "Packet length: 0x%04x (%d)", viph.vip_pktlen, viph.vip_pktlen); 
-       proto_tree_add_text(vip_tree, offset +  4, 1, "Transport control: 0x%02x",
-               viph.vip_tctl);
-       proto_tree_add_text(vip_tree, offset +  5, 1, "Protocol: 0x%02x", viph.vip_proto);
-               }
-
-
-       offset += 18;
-       switch (viph.vip_proto) 
-               {
-       case VIP_PROTO_SPP:
-               dissect_vines_spp(pd, offset, fd, tree);
-               break;
-               }
+       /*
+       viph.ip_tos = IPTOS_TOS(viph.ip_tos);
+       switch (viph.ip_tos) {
+       case IPTOS_NONE:
+               strcpy(tos_str, "None");
+               break;
+       case IPTOS_LOWDELAY:
+               strcpy(tos_str, "Minimize delay");
+               break;
+       case IPTOS_THROUGHPUT:
+               strcpy(tos_str, "Maximize throughput");
+               break;
+       case IPTOS_RELIABILITY:
+               strcpy(tos_str, "Maximize reliability");
+               break;
+       case IPTOS_LOWCOST:
+               strcpy(tos_str, "Minimize cost");
+               break;
+       default:
+               strcpy(tos_str, "Unknon.  Malformed?");
+               break;
+       }
+       */
+
+       if (tree) {
+               ti = proto_tree_add_protocol_format(tree, proto_vines, tvb, 
+                                                   offset, (viph.vip_pktlen),
+                                                   "Vines IP");
+               vip_tree = proto_item_add_subtree(ti, ett_vines);
+               proto_tree_add_text(vip_tree, tvb, offset,      2, 
+                                   "Packet checksum: 0x%04x", 
+                                   viph.vip_chksum);
+               proto_tree_add_text(vip_tree, tvb, offset +  2, 2, 
+                                   "Packet length: 0x%04x (%d)", 
+                                   viph.vip_pktlen, viph.vip_pktlen); 
+               proto_tree_add_text(vip_tree, tvb, offset +  4, 1, 
+                                   "Transport control: 0x%02x",
+                                   viph.vip_tctl);
+               proto_tree_add_uint(vip_tree, hf_vines_protocol, tvb, 
+                                   offset +  5, 1, 
+                                   viph.vip_proto);
+               proto_tree_add_text(vip_tree, tvb, offset +  6, 
+                                   VINES_ADDR_LEN, 
+                                   "Destination: %s",
+                                   vines_addr_to_str(dst_addr));
+               proto_tree_add_text(vip_tree, tvb, offset +  12, 
+                                   VINES_ADDR_LEN, 
+                                   "Source: %s",
+                                   vines_addr_to_str(src_addr));
+
        }
-#define VINES_VSPP_DATA 1
-#define VINES_VSPP_ACK 5
-void dissect_vines_spp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
-       {
-       e_vspp       viph;
-       proto_tree *vspp_tree;
+
+       offset += 18;
+       next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+       if (!dissector_try_port(vines_dissector_table, viph.vip_proto,
+           next_tvb, pinfo, tree))
+               call_dissector(data_handle,next_tvb, pinfo, tree);
+}
+
+void
+proto_register_vines(void)
+{
+       static gint *ett[] = {
+               &ett_vines,
+       };
+
+       static hf_register_info hf[] = {
+         { &hf_vines_protocol,
+           { "Protocol",                       "vines.protocol",
+             FT_UINT8,         BASE_HEX,       NULL,   0x0,
+             "Vines protocol", HFILL }}
+       };
+
+       proto_vines = proto_register_protocol("Banyan Vines", "Vines", "vines");
+       proto_register_field_array(proto_vines, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+
+       /* subdissector code */
+       vines_dissector_table = register_dissector_table("vines.proto",
+           "Vines protocol", FT_UINT8, BASE_HEX);
+
+       register_dissector("vines", dissect_vines, proto_vines);
+       vines_handle = find_dissector("vines");
+}
+
+void
+proto_reg_handoff_vines(void)
+{
+       dissector_add("ethertype", ETHERTYPE_VINES, vines_handle);
+       dissector_add("ppp.protocol", PPP_VINES, vines_handle);
+       data_handle = find_dissector("data");
+}
+
+static void
+dissect_vines_spp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       int          offset = 0;
+       e_vspp       viph;
+       proto_tree *vspp_tree;
        proto_item *ti;
 
-  /* To do: check for runts, errs, etc. */
-  /* Avoids alignment problems on many architectures. */
-       memcpy(&viph, &pd[offset], sizeof(e_vspp));
-
-       viph.vspp_sport = ntohs(viph.vspp_sport);
-       viph.vspp_dport = ntohs(viph.vspp_dport);
-       viph.vspp_lclid = ntohs(viph.vspp_lclid);
-       viph.vspp_rmtid = ntohs(viph.vspp_rmtid);
-
-    switch (viph.vspp_pkttype) 
-       {
-       case VSPP_PKTTYPE_DATA:      
-                                       if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "VSPP Data");
-               break;
-       case VSPP_PKTTYPE_DISC:      
-                                       if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "VSPP Disconnect");
-               break;
-       case VSPP_PKTTYPE_PROBE:      
-                                       if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "VSPP Probe");
-               break;
-       case VSPP_PKTTYPE_ACK:
-                                       if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "VSPP Ack");
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
+
+       /* To do: check for runts, errs, etc. */
+
+       /* Avoids alignment problems on many architectures. */
+       tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vspp));
+
+       viph.vspp_sport = ntohs(viph.vspp_sport);
+       viph.vspp_dport = ntohs(viph.vspp_dport);
+       viph.vspp_lclid = ntohs(viph.vspp_lclid);
+       viph.vspp_rmtid = ntohs(viph.vspp_rmtid);
+
+       switch (viph.vspp_pkttype) {
+       case VSPP_PKTTYPE_DATA:      
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP Data");
+               break;
+       case VSPP_PKTTYPE_DISC:      
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP Disconnect");
+               break;
+       case VSPP_PKTTYPE_PROBE:      
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP Probe");
+               break;
+       case VSPP_PKTTYPE_ACK:
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP Ack");
                break;
-       default:
-                                       if (check_col(fd, COL_PROTOCOL))
-                       col_add_str(fd, COL_PROTOCOL, "VSPP Unknown");
-       }
-       if (check_col(fd, COL_INFO))
-                       col_add_fstr(fd, COL_INFO, "NS=%04x NR=%04x Window=%04x RID=%04x LID=%04x D=%04x S=%04x", 
-                       viph.vspp_seqno, viph.vspp_ack, viph.vspp_win, viph.vspp_rmtid,
-                               viph.vspp_lclid, viph.vspp_dport, viph.vspp_sport);
-  /*
+       default:
+               if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP Unknown");
+       }
+
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_add_fstr(pinfo->cinfo, COL_INFO, 
+                            "NS=%04x NR=%04x Window=%04x RID=%04x LID=%04x D=%04x S=%04x", 
+                            viph.vspp_seqno, viph.vspp_ack, viph.vspp_win, 
+                            viph.vspp_rmtid, viph.vspp_lclid, viph.vspp_dport,
+                            viph.vspp_sport);
+
+       /*
        iph.ip_tos = IPTOS_TOS(iph.ip_tos);
-       switch (iph.ip_tos)
-               {
-       case IPTOS_NONE:
-               strcpy(tos_str, "None");
-               break;
-       case IPTOS_LOWDELAY:
-               strcpy(tos_str, "Minimize delay");
-               break;
-       case IPTOS_THROUGHPUT:
-               strcpy(tos_str, "Maximize throughput");
-               break;
-       case IPTOS_RELIABILITY:
-               strcpy(tos_str, "Maximize reliability");
-               break;
-       case IPTOS_LOWCOST:
-               strcpy(tos_str, "Minimize cost");
-               break;
-       default:
-               strcpy(tos_str, "Unknon.  Malformed?");
-               break;
-               }
-*/ 
-       if (tree) 
-               {
-       ti = proto_tree_add_text(tree, offset, sizeof(viph), "Vines SPP");
-       vspp_tree = proto_item_add_subtree(ti, ett_vines_spp);
-       proto_tree_add_text(vspp_tree, offset,      2, "Source port: 0x%04x", viph.vspp_sport);
-       proto_tree_add_text(vspp_tree, offset+2,    2, "Destination port: 0x%04x", viph.vspp_dport); 
-       proto_tree_add_text(vspp_tree, offset+4,    1, "Packet type: 0x%02x", viph.vspp_pkttype);
-       proto_tree_add_text(vspp_tree, offset+5,    1, "Control: 0x%02x", viph.vspp_control);
-       proto_tree_add_text(vspp_tree, offset+6,    2, "Local Connection ID: 0x%04x", viph.vspp_lclid);
-       proto_tree_add_text(vspp_tree, offset+8,    2, "Remote Connection ID: 0x%04x", viph.vspp_rmtid);
-       proto_tree_add_text(vspp_tree, offset+10,   2, "Sequence number: 0x%04x", viph.vspp_seqno);
-       proto_tree_add_text(vspp_tree, offset+12,   2, "Ack number: 0x%04x", viph.vspp_ack);
-       proto_tree_add_text(vspp_tree, offset+14,   2, "Window: 0x%04x", viph.vspp_win);
-               }
+       switch (iph.ip_tos) {
+       case IPTOS_NONE:
+               strcpy(tos_str, "None");
+               break;
+       case IPTOS_LOWDELAY:
+               strcpy(tos_str, "Minimize delay");
+               break;
+       case IPTOS_THROUGHPUT:
+               strcpy(tos_str, "Maximize throughput");
+               break;
+       case IPTOS_RELIABILITY:
+               strcpy(tos_str, "Maximize reliability");
+               break;
+       case IPTOS_LOWCOST:
+               strcpy(tos_str, "Minimize cost");
+               break;
+       default:
+               strcpy(tos_str, "Unknon.  Malformed?");
+               break;
        }
+       */ 
+
+       if (tree) {
+               ti = proto_tree_add_item(tree, proto_vines_spp, tvb, offset,
+                   sizeof(viph), FALSE);
+               vspp_tree = proto_item_add_subtree(ti, ett_vines_spp);
+               proto_tree_add_text(vspp_tree, tvb, offset,      2, 
+                                   "Source port: 0x%04x", viph.vspp_sport);
+               proto_tree_add_text(vspp_tree, tvb, offset + 2,  2, 
+                                   "Destination port: 0x%04x",
+                                   viph.vspp_dport); 
+               proto_tree_add_text(vspp_tree, tvb, offset + 4,  1, 
+                                   "Packet type: 0x%02x", viph.vspp_pkttype);
+               proto_tree_add_text(vspp_tree, tvb, offset + 5,  1, 
+                                   "Control: 0x%02x", viph.vspp_control);
+               proto_tree_add_text(vspp_tree, tvb, offset + 6,  2, 
+                                   "Local Connection ID: 0x%04x",
+                                   viph.vspp_lclid);
+               proto_tree_add_text(vspp_tree, tvb, offset + 8,  2,
+                                   "Remote Connection ID: 0x%04x", 
+                                   viph.vspp_rmtid);
+               proto_tree_add_text(vspp_tree, tvb, offset + 10, 2,
+                                   "Sequence number: 0x%04x", 
+                                   viph.vspp_seqno);
+               proto_tree_add_text(vspp_tree, tvb, offset + 12, 2,
+                                   "Ack number: 0x%04x", viph.vspp_ack);
+               proto_tree_add_text(vspp_tree, tvb, offset + 14, 2,
+                                   "Window: 0x%04x", viph.vspp_win);
+       }
+       offset += 16; /* sizeof SPP */
+       call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
+}
 
 void
-proto_register_vines(void)
+proto_register_vines_spp(void)
 {
        static gint *ett[] = {
-               &ett_vines,
-               &ett_vines_frp,
                &ett_vines_spp,
        };
 
+       proto_vines_spp = proto_register_protocol("Banyan Vines SPP",
+           "Vines SPP", "vines_spp");
        proto_register_subtree_array(ett, array_length(ett));
 }
+
+void
+proto_reg_handoff_vines_spp(void)
+{
+       dissector_handle_t vines_spp_handle;
+
+       vines_spp_handle = create_dissector_handle(dissect_vines_spp,
+           proto_vines_spp);
+       dissector_add("vines.proto", VIP_PROTO_SPP, vines_spp_handle);
+}