* 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>
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" },
static const value_string frame_vals[] = {
{ 0, "MAC" },
- { 64, "LLC" },
- { 128, "Reserved" },
+ { 1, "LLC" },
+ { 2, "Reserved" },
{ 0, NULL },
};
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 */
}
}
+ /* 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))
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);
/* 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);
}
}
}
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;
+ }
}
}
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) {
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
{
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));
}