When doing a capture, decode enough of the incoming packets to correctly
[obnox/wireshark/wip.git] / packet-tr.c
index 43d303ae9ac4ac8196d7cdb516eb85fb3674fbf1..eeb27f7db75d5b5951ebff4fd679887b6a7cc3db 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for Token-Ring packet disassembly
  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
  *
- * $Id: packet-tr.c,v 1.4 1998/09/17 22:28:07 gram Exp $
+ * $Id: packet-tr.c,v 1.10 1999/02/09 00:35:38 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@unicom.net>
 # include <netinet/in.h>
 #endif
 
-#include <pcap.h>
 
-#include "packet.h"
 #include "ethereal.h"
+#include "packet.h"
 #include "etypes.h"
 
 static void
@@ -75,6 +74,100 @@ sr_frame(u_char val) {
 }
 
 
+void
+capture_tr(const u_char *pd, guint32 cap_len, packet_counts *ld) {
+
+       int                     offset = 14;
+
+       int                     source_routed = 0;
+       int                     frame_type;
+       guint8                  trn_rif_bytes;
+       guint8                  actual_rif_bytes;
+
+       /* The trn_hdr struct, as separate variables */
+       guint8                  trn_fc;         /* field control field */
+       guint8                  trn_shost[6];   /* source host */
+
+       /* get the data */
+       memcpy(&trn_fc, &pd[1], sizeof(guint8));
+       memcpy(trn_shost, &pd[8], 6 * sizeof(guint8));
+
+       frame_type = (trn_fc & 192) >> 6;
+
+       /* if the high bit on the first byte of src hwaddr is 1, then
+               this packet is source-routed */
+       source_routed = trn_shost[0] & 128;
+
+       trn_rif_bytes = pd[14] & 31;
+
+       /* sometimes we have a RCF but no RIF... half source-routed? */
+       /* I'll check for 2 bytes of RIF and the 0x70 byte */
+       if (!source_routed) {
+               if (trn_rif_bytes == 2) {
+                       source_routed = 1;
+               }
+               /* the Linux 2.0 TR code strips source-route bits in
+                * order to test for SR. This can be removed from most
+                * packets with oltr, but not all. So, I try to figure out
+                * which packets should have been SR here. I'll check to
+                * see if there's a SNAP or IPX field right after
+                * my RIF fields.
+                */
+               else if ( (
+                       pd[0x0e + trn_rif_bytes] == 0xaa &&
+                       pd[0x0f + trn_rif_bytes] == 0xaa &&
+                       pd[0x10 + trn_rif_bytes] == 0x03) ||
+                         (
+                       pd[0x0e + trn_rif_bytes] == 0xe0 &&
+                       pd[0x0f + trn_rif_bytes] == 0xe0) ) {
+
+                       source_routed = 1;
+               }
+/*             else {
+                       printf("0e+%d = %02X   0f+%d = %02X\n", trn_rif_bytes, pd[0x0e + trn_rif_bytes],
+                                       trn_rif_bytes, pd[0x0f + trn_rif_bytes]);
+               } */
+
+       }
+
+       if (source_routed) {
+               actual_rif_bytes = trn_rif_bytes;
+       }
+       else {
+               trn_rif_bytes = 0;
+               actual_rif_bytes = 0;
+       }
+
+       /* this is a silly hack for Linux 2.0.x. Read the comment below,
+       in front of the other #ifdef linux. If we're sniffing our own NIC,
+        we get a full RIF, sometimes with garbage */
+       if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
+               (!source_routed && frame_type == 1)) {
+               /* look for SNAP or IPX only */
+               if ( (pd[0x20] == 0xaa && pd[0x21] == 0xaa && pd[0x22] == 03) ||
+                        (pd[0x20] == 0xe0 && pd[0x21] == 0xe0) ) {
+                       actual_rif_bytes = 18;
+               }
+       }
+       offset += actual_rif_bytes;
+
+       /* The package is either MAC or LLC */
+       switch (frame_type) {
+               /* MAC */
+               case 0:
+                       ld->other++;
+                       break;
+               case 1:
+                       capture_llc(pd, offset, cap_len, ld);
+                       break;
+               default:
+                       /* non-MAC, non-LLC, i.e., "Reserved" */
+                       ld->other++;
+                       break;
+       }
+}
+
+
 void
 dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
 
@@ -97,13 +190,23 @@ dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
        /* non-source-routed version of source addr */
        guint8                  trn_shost_nonsr[6];
 
+       static const value_string fc_pcf[] = {
+               { 0,    "Normal buffer" },
+               { 1,    "Express buffer" },
+               { 2,    "Purge" },
+               { 3,    "Claim Token" },
+               { 4,    "Beacon" },
+               { 5,    "Active Monitor Present" },
+               { 6,    "Standby Monitor Present" },
+               { 0,    NULL },
+       };
 
        /* Token-Ring Strings */
-       char *fc[] = { "MAC", "LLC", "Reserved" };
-       char *fc_pcf[] = {
+       char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
+/*     char *fc_pcf[] = {
                "Normal buffer", "Express buffer", "Purge",
                "Claim Token", "Beacon", "Active Monitor Present",
-               "Standby Monitor Present" };
+               "Standby Monitor Present" };*/
        char *rc_arrow[] = { "-->", "<--" };
        char *rc_direction[] = { "From originating station",
                "To originating station" };
@@ -179,17 +282,19 @@ dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
 
 
        /* information window */
-       if (fd->win_info[0]) {
-               strcpy(fd->win_info[2], ether_to_str((guint8 *)&pd[2]));
-               strcpy(fd->win_info[1], ether_to_str(trn_shost_nonsr));
-               strcpy(fd->win_info[3], "TR");
-               sprintf(fd->win_info[4], "Token-Ring %s", fc[frame_type]);
-       }
+       if (check_col(fd, COL_RES_DL_DST))
+               col_add_str(fd, COL_RES_DL_DST, ether_to_str((guint8 *)&pd[2]));
+       if (check_col(fd, COL_RES_DL_SRC))
+               col_add_str(fd, COL_RES_DL_SRC, ether_to_str(trn_shost_nonsr));
+       if (check_col(fd, COL_PROTOCOL))
+               col_add_str(fd, COL_PROTOCOL, "TR");
+       if (check_col(fd, COL_INFO))
+               col_add_fstr(fd, COL_INFO, "Token-Ring %s", fc[frame_type]);
 
        /* protocol analysis tree */
        if (tree) {
                ti = add_item_to_tree(GTK_WIDGET(tree), 0, 14 + actual_rif_bytes,
-                 "Token-Ring (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
+                 "Token-Ring");
                fh_tree = gtk_tree_new();
                add_subtree(ti, fh_tree, ETT_TOKEN_RING);
                add_item_to_tree(fh_tree, 0, 1,
@@ -203,7 +308,7 @@ dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
                add_item_to_tree(fh_tree, 1, 1,
                        "Frame Control: %s, Physical Control=%d (%s)",
                        fc[frame_type], (trn_fc & 15),
-                       fc_pcf[(trn_fc & 15)]);
+                       val_to_str((trn_fc & 15), fc_pcf, "Unknown"));
 
                add_item_to_tree(fh_tree, 2, 6, "Destination: %s",
                        ether_to_str((guint8 *) trn_dhost));
@@ -241,7 +346,7 @@ dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
                tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the
                frame type is LLC.  It's very much a hack. -- Gilbert Ramirez */
                if (actual_rif_bytes > trn_rif_bytes) {
-                       printf("trn_rif %d    actual_rif %d\n", trn_rif_bytes, actual_rif_bytes);
+                       /*printf("trn_rif %d    actual_rif %d\n", trn_rif_bytes, actual_rif_bytes);*/
                        add_item_to_tree(fh_tree, 14 + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes,
                                "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
                                "is also running a protocol stack.");