Stuart Stanley's ISIS dissection support.
[obnox/wireshark/wip.git] / packet-fddi.c
index 91cef08dd93a3bbbb84d14c4753c8ebc3755ad8a..cdfae657b53bed80f6415d124324bb5849ee912e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Laurent Deniel <deniel@worldnet.fr>
  *
- * $Id: packet-fddi.c,v 1.17 1999/08/23 22:13:35 gram Exp $
+ * $Id: packet-fddi.c,v 1.25 1999/11/16 11:42:30 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -33,6 +33,7 @@
 # include <sys/types.h>
 #endif
 
+#include <stdio.h>
 #include <glib.h>
 #include "packet.h"
 #include "resolv.h"
@@ -42,6 +43,8 @@ static int hf_fddi_fc = -1;
 static int hf_fddi_dst = -1;
 static int hf_fddi_src = -1;
 
+static gint ett_fddi = -1;
+
 /* FDDI Frame Control values */
 
 #define FDDI_FC_VOID           0x00            /* Void frame */
@@ -69,6 +72,15 @@ static int hf_fddi_src = -1;
 #define FDDI_FC_IMP_ASYNC_MAX  0x6f
 #define FDDI_FC_IMP_SYNC       0xe0            /* Implementor Synch. */
 
+#define FDDI_FC_CLFF           0xF0            /* Class/Length/Format bits */
+#define FDDI_FC_ZZZZ           0x0F            /* Control bits */
+
+/*
+ * Async frame ZZZZ bits:
+ */
+#define FDDI_FC_ASYNC_R                0x08            /* Reserved */
+#define FDDI_FC_ASYNC_PRI      0x07            /* Priority */
+
 #define FDDI_HEADER_SIZE       13
 
 /* field positions */
@@ -77,11 +89,6 @@ static int hf_fddi_src = -1;
 #define FDDI_P_DHOST           1
 #define FDDI_P_SHOST           7
 
-/* On some systems, the FDDI MAC addresses are bit-swapped. */
-#if !defined(ultrix) && !defined(__alpha) && !defined(__bsdi)
-#define BIT_SWAPPED_MAC_ADDRS
-#endif
-
 /* "swaptab[i]" is the value of "i" with the bits reversed. */
 static u_char swaptab[256] = {
   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
@@ -118,19 +125,6 @@ static u_char swaptab[256] = {
   0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
 };
 
-static void get_mac_addr(u_char *swapped_addr, const u_char *addr)
-{
-  int i;
-
-  for (i = 0; i < 6; i++) {
-#ifdef BIT_SWAPPED_MAC_ADDRS
-    swapped_addr[i] = swaptab[addr[i]];
-#else
-    swapped_addr[i] = addr[i];
-#endif
-  }
-}
-
 static void
 swap_mac_addr(u_char *swapped_addr, const u_char *orig_addr)
 {
@@ -184,12 +178,85 @@ capture_fddi(const u_char *pd, guint32 cap_len, packet_counts *ld) {
 
 } /* capture_fddi */
 
-void dissect_fddi(const u_char *pd, frame_data *fd, proto_tree *tree) 
+static gchar *
+fddifc_to_str(int fc)
+{
+  static gchar strbuf[128+1];
+
+  switch (fc) {
+
+  case FDDI_FC_VOID:                   /* Void frame */
+    return "Void frame";
+
+  case FDDI_FC_NRT:                    /* Nonrestricted token */
+    return "Nonrestricted token";
+
+  case FDDI_FC_RT:                     /* Restricted token */
+    return "Restricted token";
+
+  case FDDI_FC_SMT_INFO:               /* SMT Info */
+    return "SMT info";
+
+  case FDDI_FC_SMT_NSA:                        /* SMT Next station adrs */
+    return "SMT Next station address";
+
+  case FDDI_FC_MAC_BEACON:             /* MAC Beacon frame */
+    return "MAC beacon";
+
+  case FDDI_FC_MAC_CLAIM:              /* MAC Claim frame */
+    return "MAC claim token";
+
+  default:
+    switch (fc & FDDI_FC_CLFF) {
+
+    case FDDI_FC_MAC:
+      sprintf(strbuf, "MAC frame, control %x", fc & FDDI_FC_ZZZZ);
+      return strbuf;
+
+    case FDDI_FC_SMT:
+      sprintf(strbuf, "SMT frame, control %x", fc & FDDI_FC_ZZZZ);
+      return strbuf;
+
+    case FDDI_FC_LLC_ASYNC:
+      if (fc & FDDI_FC_ASYNC_R)
+        sprintf(strbuf, "Async LLC frame, control %x", fc & FDDI_FC_ZZZZ);
+      else
+        sprintf(strbuf, "Async LLC frame, priority %d",
+                       fc & FDDI_FC_ASYNC_PRI);
+      return strbuf;
+
+    case FDDI_FC_LLC_SYNC:
+      if (fc & FDDI_FC_ZZZZ) {
+        sprintf(strbuf, "Sync LLC frame, control %x", fc & FDDI_FC_ZZZZ);
+        return strbuf;
+      } else
+        return "Sync LLC frame";
+
+    case FDDI_FC_IMP_ASYNC:
+      sprintf(strbuf, "Implementor async frame, control %x",
+                       fc & FDDI_FC_ZZZZ);
+      return strbuf;
+
+    case FDDI_FC_IMP_SYNC:
+      sprintf(strbuf, "Implementor sync frame, control %x",
+                       fc & FDDI_FC_ZZZZ);
+      return strbuf;
+      break;
+
+    default:
+      return "Unknown frame type";
+    }
+  }
+}
+
+void dissect_fddi(const u_char *pd, frame_data *fd, proto_tree *tree,
+               gboolean bitswapped)
 {
   int        offset = 0, fc;
   proto_tree *fh_tree;
   proto_item *ti;
-  u_char     src[6], dst[6];
+  gchar      *fc_str;
+  static u_char src[6], dst[6];
   u_char     src_swapped[6], dst_swapped[6];
 
   if (fd->cap_len < FDDI_HEADER_SIZE) {
@@ -199,45 +266,48 @@ void dissect_fddi(const u_char *pd, frame_data *fd, proto_tree *tree)
 
   /* Extract the source and destination addresses, possibly bit-swapping
      them. */
-  get_mac_addr(dst, (u_char *)&pd[FDDI_P_DHOST]);
-  get_mac_addr(src, (u_char *)&pd[FDDI_P_SHOST]);
+  if (bitswapped) {
+    swap_mac_addr(dst, (u_char *)&pd[FDDI_P_DHOST]);
+    swap_mac_addr(src, (u_char *)&pd[FDDI_P_SHOST]);
+  } else {
+    memcpy(dst, (u_char *)&pd[FDDI_P_DHOST], sizeof dst);
+    memcpy(src, (u_char *)&pd[FDDI_P_SHOST], sizeof src);
+  }
 
   fc = (int) pd[FDDI_P_FC];
+  fc_str = fddifc_to_str(fc);
+
+  /* XXX - copy them to some buffer associated with "pi", rather than
+     just making "src" and "dst" static? */
+  SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &src[0]);
+  SET_ADDRESS(&pi.src, AT_ETHER, 6, &src[0]);
+  SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &dst[0]);
+  SET_ADDRESS(&pi.dst, AT_ETHER, 6, &dst[0]);
 
-  if (check_col(fd, COL_RES_DL_SRC))
-    col_add_str(fd, COL_RES_DL_SRC, get_ether_name(src));
-  if (check_col(fd, COL_RES_DL_DST))
-    col_add_str(fd, COL_RES_DL_DST, get_ether_name(dst));
-  if (check_col(fd, COL_UNRES_DL_SRC))
-    col_add_str(fd, COL_UNRES_DL_SRC, ether_to_str(src));
-  if (check_col(fd, COL_UNRES_DL_DST))
-    col_add_str(fd, COL_UNRES_DL_DST, ether_to_str(dst));
   if (check_col(fd, COL_PROTOCOL))
-    col_add_str(fd, COL_PROTOCOL, "N/A");
+    col_add_str(fd, COL_PROTOCOL, "FDDI");
   if (check_col(fd, COL_INFO))
-    col_add_str(fd, COL_INFO, "FDDI");
+    col_add_str(fd, COL_INFO, fc_str);
 
   offset = FDDI_HEADER_SIZE;
 
   if (tree) {
        ti = proto_tree_add_item_format(tree, proto_fddi, 0, offset, NULL,
-               "Fiber Distributed Data Interface, %s",
-               (fc >= FDDI_FC_LLC_ASYNC_MIN && fc <= FDDI_FC_LLC_ASYNC_MAX) ?
-                         "Async LLC" : "unsupported FC");
+               "Fiber Distributed Data Interface, %s", fc_str);
 
       swap_mac_addr(dst_swapped, (u_char*)&pd[FDDI_P_DHOST]);
       swap_mac_addr(src_swapped, (u_char*)&pd[FDDI_P_SHOST]);
 
-      fh_tree = proto_item_add_subtree(ti, ETT_FDDI);
+      fh_tree = proto_item_add_subtree(ti, ett_fddi);
       proto_tree_add_item(fh_tree, hf_fddi_fc, FDDI_P_FC, 1, fc);
       proto_tree_add_item(fh_tree, hf_fddi_dst, FDDI_P_DHOST, 6, dst);
       proto_tree_add_item(fh_tree, hf_fddi_src, FDDI_P_SHOST, 6, src);
 
       /* hide some bit-swapped mac address fields in the proto_tree, just in case */
       proto_tree_add_item_hidden(fh_tree, hf_fddi_dst, FDDI_P_DHOST, 6, dst_swapped);
-      proto_tree_add_item_hidden(fh_tree, hf_fddi_dst, FDDI_P_SHOST, 6, src_swapped);
+      proto_tree_add_item_hidden(fh_tree, hf_fddi_src, FDDI_P_SHOST, 6, src_swapped);
 
-    }
+  }
   switch (fc) {
 
     /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
@@ -273,16 +343,28 @@ proto_register_fddi(void)
 {
        static hf_register_info hf[] = {
 
+               /*
+                * XXX - we want this guy to have his own private formatting
+                * routine, using "fc_to_str()"; if "fc_to_str()" returns
+                * NULL, just show the hex value, else show the string.
+                */
                { &hf_fddi_fc,
-               { "Frame Control",      "fddi.fc", FT_UINT8, NULL }},
+               { "Frame Control",      "fddi.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
+                       "" }},
 
                { &hf_fddi_dst,
-               { "Destination",        "fddi.dst", FT_ETHER, NULL }},
+               { "Destination",        "fddi.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
+                       "Destination Hardware Address" }},
 
                { &hf_fddi_src,
-               { "Source",             "fddi.src", FT_ETHER, NULL }},
+               { "Source",             "fddi.src", FT_ETHER, BASE_NONE, NULL, 0x0,
+                       "" }},
+       };
+       static gint *ett[] = {
+               &ett_fddi,
        };
 
        proto_fddi = proto_register_protocol ("Fiber Distributed Data Interface", "fddi" );
        proto_register_field_array(proto_fddi, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
 }