Include <time.h> to declare "gmtime()".
[obnox/wireshark/wip.git] / packet-tr.c
index bd782d468627e657789e2f248b2285777bbf9b9d..be357ba8cfcb998b1db11523d96635a45a97d897 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for Token-Ring packet disassembly
  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
  *
- * $Id: packet-tr.c,v 1.27 1999/09/17 04:20:22 gram Exp $
+ * $Id: packet-tr.c,v 1.31 1999/11/16 11:43:00 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@unicom.net>
@@ -56,14 +56,14 @@ static int hf_tr_rif = -1;
 static int hf_tr_rif_ring = -1;
 static int hf_tr_rif_bridge = -1;
 
+static gint ett_token_ring = -1;
+static gint ett_token_ring_ac = -1;
+static gint ett_token_ring_fc = -1;
+
 #define TR_MIN_HEADER_LEN 14
 #define TR_MAX_HEADER_LEN 32
 
-static const value_string ac_vals[] = {
-       { 0,    "Token" },
-       { 0x10, "Frame" },
-       { 0,    NULL }
-};
+static const true_false_string ac_truth = { "Frame", "Token" };
 
 static const value_string pcf_vals[] = {
        { 0,    "Normal buffer" },
@@ -78,8 +78,8 @@ static const value_string pcf_vals[] = {
 
 static const value_string frame_vals[] = {
        { 0,    "MAC" },
-       { 64,   "LLC" },
-       { 128,  "Reserved" },
+       { 1,    "LLC" },
+       { 2,    "Reserved" },
        { 0,    NULL },
 };
 
@@ -289,7 +289,7 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        guint16                 trn_rseg[8];    /* routing registers */
 
        /* non-source-routed version of source addr */
-       guint8                  trn_shost_nonsr[6];
+       static guint8           trn_shost_nonsr[6];
        int                     x;
        
        /* Token-Ring Strings */
@@ -401,12 +401,14 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                 }
        }
 
+       /* XXX - copy it to some buffer associated with "pi", rather than
+          just making "trn_shost_nonsr" static? */
+       SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &trn_shost_nonsr[0]);
+       SET_ADDRESS(&pi.src, AT_ETHER, 6, &trn_shost_nonsr[0]);
+       SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &pd[offset + 2]);
+       SET_ADDRESS(&pi.dst, AT_ETHER, 6, &pd[offset + 2]);
+
        /* information window */
-       if (check_col(fd, COL_RES_DL_DST))
-               col_add_str(fd, COL_RES_DL_DST,
-                 ether_to_str((guint8 *)&pd[offset + 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))
@@ -416,36 +418,23 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        if (tree) {
                /* Create Token-Ring Tree */
                ti = proto_tree_add_item(tree, proto_tr, offset, 14 + actual_rif_bytes, NULL);
-               tr_tree = proto_item_add_subtree(ti, ETT_TOKEN_RING);
+               tr_tree = proto_item_add_subtree(ti, ett_token_ring);
 
                /* Create the Access Control bitfield tree */
-               ti = proto_tree_add_item_format(tr_tree, hf_tr_ac, offset, 1, trn_ac,
-                       "Access Control (0x%02x)", trn_ac);
-               bf_tree = proto_item_add_subtree(ti, ETT_TOKEN_RING_AC);
-
-               proto_tree_add_item_format(bf_tree, hf_tr_priority, offset, 1, trn_ac & 0xe0,
-                       decode_numeric_bitfield(trn_ac, 0xe0, 8, "Priority = %d"));
-
-               proto_tree_add_item_format(bf_tree, hf_tr_frame, offset, 1, trn_ac & 0x10,
-                       decode_enumerated_bitfield(trn_ac, 0x10, 8, ac_vals, "%s"));
-
-               proto_tree_add_item_format(bf_tree, hf_tr_monitor_cnt, offset, 1, trn_ac & 0x08,
-                       decode_numeric_bitfield(trn_ac, 0x08, 8, "Monitor Count"));
+               ti = proto_tree_add_item(tr_tree, hf_tr_ac, offset, 1, trn_ac);
+               bf_tree = proto_item_add_subtree(ti, ett_token_ring_ac);
 
-               proto_tree_add_item_format(bf_tree, hf_tr_priority_reservation, offset, 1, trn_ac & 0x07,
-                       decode_numeric_bitfield(trn_ac, 0x07, 8, "Priority Reservation = %d"));
+               proto_tree_add_item(bf_tree, hf_tr_priority, offset, 1, trn_ac);
+               proto_tree_add_item(bf_tree, hf_tr_frame, offset, 1, trn_ac);
+               proto_tree_add_item(bf_tree, hf_tr_monitor_cnt, offset, 1, trn_ac);
+               proto_tree_add_item(bf_tree, hf_tr_priority_reservation, offset, 1, trn_ac);
 
                /* Create the Frame Control bitfield tree */
-               ti = proto_tree_add_item_format(tr_tree, hf_tr_fc, offset + 1, 1, trn_fc,
-                       "Frame Control (0x%02x)", trn_fc);
-               bf_tree = proto_item_add_subtree(ti, ETT_TOKEN_RING_FC);
-
-               proto_tree_add_item_format(bf_tree, hf_tr_fc_type, offset + 1, 1, trn_fc & 0xc0,
-                       decode_enumerated_bitfield(trn_fc, 0xc0, 8, frame_vals, "%s"));
-
-               proto_tree_add_item_format(bf_tree, hf_tr_fc_pcf, offset + 1, 1, trn_fc & 0x0f,
-                       decode_enumerated_bitfield(trn_fc, 0x0f, 8, pcf_vals, "%s"));
+               ti = proto_tree_add_item(tr_tree, hf_tr_fc, offset + 1, 1, trn_fc);
+               bf_tree = proto_item_add_subtree(ti, ett_token_ring_fc);
 
+               proto_tree_add_item(bf_tree, hf_tr_fc_type, offset + 1, 1, trn_fc);
+               proto_tree_add_item(bf_tree, hf_tr_fc_pcf,  offset + 1, 1, trn_fc);
                proto_tree_add_item(tr_tree, hf_tr_dst, offset + 2, 6, trn_dhost);
                proto_tree_add_item(tr_tree, hf_tr_src, offset + 8, 6, trn_shost);
 
@@ -465,12 +454,9 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
 
                        /* if we have more than 2 bytes of RIF, then we have
                                ring/bridge pairs */
-                       if (trn_rif_bytes > 18) {
-                               proto_tree_add_text(tr_tree, offset + 14, 1,
-                                               "Illegal number of RIF bytes: %d", trn_rif_bytes);
-                       } else if (trn_rif_bytes > 2) {
+                       if ((trn_rif_bytes > 2) && BYTES_ARE_IN_FRAME(offset + 14, trn_rif_bytes)) {
                                add_ring_bridge_pairs(trn_rif_bytes,
-                                       pd + offset, offset, tr_tree);
+                                       pd, offset, tr_tree);
                        }
                }
 
@@ -494,19 +480,21 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        }
        offset += 14 + actual_rif_bytes + fixoffset;
 
-       /* The package is either MAC or LLC */
-       switch (frame_type) {
-               /* MAC */
-               case 0:
-                       dissect_trmac(pd, offset, fd, tree);
-                       break;
-               case 1:
-                       dissect_llc(pd, offset, fd, tree);
-                       break;
-               default:
-                       /* non-MAC, non-LLC, i.e., "Reserved" */
-                       dissect_data(pd, offset, fd, tree);
-                       break;
+       if (IS_DATA_IN_FRAME(offset)) {
+               /* The package is either MAC or LLC */
+               switch (frame_type) {
+                       /* MAC */
+                       case 0:
+                               dissect_trmac(pd, offset, fd, tree);
+                               break;
+                       case 1:
+                               dissect_llc(pd, offset, fd, tree);
+                               break;
+                       default:
+                               /* non-MAC, non-LLC, i.e., "Reserved" */
+                               dissect_data(pd, offset, fd, tree);
+                               break;
+               }
        }
 }
 
@@ -516,10 +504,19 @@ static void
 add_ring_bridge_pairs(int rcf_len, const u_char *pd, int offset, proto_tree *tree)
 {
        int     j, size;
-       int     segment, brdgnmb;
-       char    buffer[50];
+       int     segment, brdgnmb, unprocessed_rif;
        int     buff_offset=0;
 
+#define RIF_BYTES_TO_PROCESS 30
+
+       char    buffer[3 + (RIF_BYTES_TO_PROCESS / 2) * 6 + 1];
+
+       /* Only process so many  bytes of RIF, as per TR spec, and not overflow
+        * static buffer above */
+       unprocessed_rif = rcf_len - RIF_BYTES_TO_PROCESS;
+       rcf_len = MIN(rcf_len, RIF_BYTES_TO_PROCESS);
+
+       /* Ignore the 2 RCF bytes, since they don't make up the ring/bride pairs */
        rcf_len -= 2;
 
        for(j = 1; j < rcf_len - 1; j += 2) {
@@ -537,6 +534,11 @@ add_ring_bridge_pairs(int rcf_len, const u_char *pd, int offset, proto_tree *tre
                buff_offset += size;    
        }
        proto_tree_add_item(tree, hf_tr_rif, offset+16, rcf_len, buffer);
+
+       if (unprocessed_rif > 0) {
+               proto_tree_add_text(tree, offset+14+RIF_BYTES_TO_PROCESS, unprocessed_rif,
+                               "Extra RIF bytes beyond spec: %d", unprocessed_rif);
+       }
 }
 
 void
@@ -544,61 +546,87 @@ proto_register_tr(void)
 {
        static hf_register_info hf[] = {
                { &hf_tr_ac,
-               { "Access Control",     "tr.ac", FT_UINT8, NULL }},
+               { "Access Control",     "tr.ac", FT_UINT8, BASE_HEX, NULL, 0x0,
+                       "" }},
 
                { &hf_tr_priority,
-               { "Priority",           "tr.priority", FT_UINT8, NULL }},
+               { "Priority",           "tr.priority", FT_UINT8, BASE_DEC, NULL, 0xe0,
+                       "" }},
 
                { &hf_tr_frame,
-               { "Frame",              "tr.frame", FT_VALS_UINT8, VALS(ac_vals) }},
+               { "Frame",              "tr.frame", FT_BOOLEAN, 8, TFS(&ac_truth), 0x10,
+                       "" }},
 
                { &hf_tr_monitor_cnt,
-               { "Monitor Count",      "tr.monitor_cnt", FT_UINT8, NULL }},
+               { "Monitor Count",      "tr.monitor_cnt", FT_UINT8, BASE_DEC, NULL, 0x08,
+                       "" }},
 
                { &hf_tr_priority_reservation,
-               { "Priority Reservation","tr.priority_reservation", FT_UINT8, NULL }},
+               { "Priority Reservation","tr.priority_reservation", FT_UINT8, BASE_DEC, NULL, 0x07,
+                       "" }},
 
                { &hf_tr_fc,
-               { "Frame Control",      "tr.fc", FT_UINT8, NULL }},
+               { "Frame Control",      "tr.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
+                       "" }},
 
                { &hf_tr_fc_type,
-               { "Frame Type",         "tr.frame_type", FT_VALS_UINT8, VALS(frame_vals) }},
+               { "Frame Type",         "tr.frame_type", FT_UINT8, BASE_DEC, VALS(frame_vals), 0xc0,
+                       "" }},
 
                { &hf_tr_fc_pcf,
-               { "Frame PCF",          "tr.frame_pcf", FT_VALS_UINT8, VALS(pcf_vals) }},
+               { "Frame PCF",          "tr.frame_pcf", FT_UINT8, BASE_DEC, VALS(pcf_vals), 0x0f,
+                       "" }},
 
                { &hf_tr_dst,
-               { "Destination",        "tr.dst", FT_ETHER, NULL }},
+               { "Destination",        "tr.dst", FT_ETHER, BASE_NONE,  NULL, 0x0,
+                       "Destination Hardware Address" }},
 
                { &hf_tr_src,
-               { "Source",             "tr.src", FT_ETHER, NULL }},
+               { "Source",             "tr.src", FT_ETHER, BASE_NONE, NULL, 0x0,
+                       "Source Hardware Address" }},
 
                { &hf_tr_sr,
-               { "Source Routed",      "tr.sr", FT_BOOLEAN, NULL }},
+               { "Source Routed",      "tr.sr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+                       "Source Routed" }},
 
                { &hf_tr_rif_bytes,
-               { "RIF Bytes",          "tr.rif_bytes", FT_UINT8, NULL }},
+               { "RIF Bytes",          "tr.rif_bytes", FT_UINT8, BASE_DEC, NULL, 0x0,
+                       "Number of bytes in Routing Information Fields, including "
+                       "the two bytes of Routing Control Field" }},
 
                { &hf_tr_broadcast,
-               { "Broadcast Type",     "tr.broadcast", FT_VALS_UINT8, VALS(broadcast_vals) }},
+               { "Broadcast Type",     "tr.broadcast", FT_UINT8, BASE_DEC, VALS(broadcast_vals), 0x0,
+                       "Type of Token-Ring Broadcast" }},
 
                { &hf_tr_max_frame_size,
-               { "Maximum Frame Size", "tr.max_frame_size", FT_VALS_UINT8, VALS(max_frame_size_vals) }},
+               { "Maximum Frame Size", "tr.max_frame_size", FT_UINT8, BASE_DEC, VALS(max_frame_size_vals),
+                       0x0,
+                       "" }},
 
                { &hf_tr_direction,
-               { "Direction",          "tr.direction", FT_VALS_UINT8, VALS(direction_vals) }},
+               { "Direction",          "tr.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
+                       "Direction of RIF" }},
 
                { &hf_tr_rif,
-               { "Ring-Bridge Pairs",  "tr.rif", FT_STRING, NULL }},
+               { "Ring-Bridge Pairs",  "tr.rif", FT_STRING, BASE_NONE, NULL, 0x0,
+                       "String representing Ring-Bridge Pairs" }},
 
                { &hf_tr_rif_ring,
-               { "RIF Ring",           "tr.rif.ring", FT_UINT16, NULL }},
+               { "RIF Ring",           "tr.rif.ring", FT_UINT16, BASE_HEX, NULL, 0x0,
+                       "" }},
 
                { &hf_tr_rif_bridge,
-               { "RIF Bridge",         "tr.rif.bridge", FT_UINT8, NULL }}
+               { "RIF Bridge",         "tr.rif.bridge", FT_UINT8, BASE_HEX, NULL, 0x0,
+                       "" }},
+       };
+       static gint *ett[] = {
+               &ett_token_ring,
+               &ett_token_ring_ac,
+               &ett_token_ring_fc,
        };
 
        proto_tr = proto_register_protocol("Token-Ring", "tr");
        proto_register_field_array(proto_tr, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
 }