*
* Laurent Deniel <deniel@worldnet.fr>
*
- * $Id: packet-fddi.c,v 1.14 1999/07/15 15:32:41 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>
# include <sys/types.h>
#endif
+#include <stdio.h>
#include <glib.h>
#include "packet.h"
#include "resolv.h"
-int proto_fddi = -1;
-int hf_fddi_fc = -1;
-int hf_fddi_dst = -1;
-int hf_fddi_dst_vendor = -1;
-int hf_fddi_src = -1;
-int hf_fddi_src_vendor = -1;
+static int proto_fddi = -1;
+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_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 */
#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
-
-#ifdef BIT_SWAPPED_MAC_ADDRS
/* "swaptab[i]" is the value of "i" with the bits reversed. */
static u_char swaptab[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
-#endif
-
-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)
} /* 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) {
/* 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_hidden(fh_tree, hf_fddi_dst_vendor, FDDI_P_DHOST, 3, dst);
proto_tree_add_item(fh_tree, hf_fddi_src, FDDI_P_SHOST, 6, src);
- proto_tree_add_item_hidden(fh_tree, hf_fddi_src_vendor, FDDI_P_SHOST, 3, 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_dst_vendor, FDDI_P_DHOST, 3, dst_swapped);
- proto_tree_add_item_hidden(fh_tree, hf_fddi_src_vendor, FDDI_P_SHOST, 3, 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 */
{
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 }},
-
- { &hf_fddi_dst_vendor,
- { "Destination Hardware Vendor", "fddi.dst_vendor", FT_ETHER_VENDOR, NULL }},
-
- { &hf_fddi_src_vendor,
- { "Source Hardware Vendor", "fddi.src_vendor", FT_ETHER_VENDOR, 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));
}