aboutsummaryrefslogtreecommitdiffstats
path: root/packet-tr.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet-tr.c')
-rw-r--r--packet-tr.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/packet-tr.c b/packet-tr.c
new file mode 100644
index 0000000000..7615d87003
--- /dev/null
+++ b/packet-tr.c
@@ -0,0 +1,253 @@
+/* packet-tr.c
+ * Routines for Token-Ring packet disassembly
+ * Gilbert Ramirez <gram@verdict.uthscsa.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <pcap.h>
+
+#include "packet.h"
+#include "ethereal.h"
+#include "etypes.h"
+
+static void
+add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree);
+
+static char*
+sr_broadcast(u_char val) {
+
+ if (val < 4) {
+ return "Non-broadcast";
+ }
+ else if (val < 6) {
+ return "All-routes broadcast";
+ }
+ else {
+ return "Single-route broadcast";
+ }
+}
+
+static int
+sr_frame(u_char val) {
+
+ int rc_frame[7] = { 516, 1500, 2052, 4472, 8144, 11407, 17800 };
+
+ if (val > 6) {
+ return -1;
+ }
+ else return rc_frame[val];
+}
+
+void
+dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
+
+ GtkWidget *fh_tree, *ti;
+ int offset = 14;
+ int source_routed = 0;
+ int rif_bytes = 0;
+ guint8 nonsr_hwaddr[8];
+ int frame_type = (pd[1] & 192) >> 6; /* I use this value a lot */
+ #ifdef linux
+ int silly_linux = 0;
+ #endif
+
+ /* Token-Ring Strings */
+ char *fc[] = { "MAC", "LLC", "Reserved" };
+ char *fc_pcf[] = {
+ "Normal buffer", "Express buffer", "Purge",
+ "Claim Token", "Beacon", "Active Monitor Present",
+ "Standby Monitor Present" };
+ char *rc_arrow[] = { "-->", "<--" };
+ char *rc_direction[] = { "From originating station",
+ "To originating station" };
+
+ /* if the high bit on the first byte of src hwaddr is 1, then
+ this packet is source-routed */
+ source_routed = pd[8] & 128;
+
+ /* 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 ((pd[14] & 31) == 2 && pd[15] == 0x70) {
+ source_routed = 1;
+ }
+ }
+
+ if (source_routed) {
+ rif_bytes = pd[14] & 31;
+ }
+ /* this is a silly hack for Linux 2.0.x. Read the comment below,
+ in front of the other #ifdef linux */
+ #ifdef linux
+ if ((source_routed && 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) ) {
+ silly_linux = 1;
+ rif_bytes = 18;
+ }
+ }
+ #endif
+ offset += rif_bytes;
+
+ /* Make a copy of the src hwaddr, w/o source routing. I'll do this
+ for all packets, even non-sr packets */
+ memcpy(nonsr_hwaddr, &pd[8], 6);
+ nonsr_hwaddr[0] &= 127;
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[2], ether_to_str((guint8 *)&pd[2]));
+ strcpy(fd->win_info[1], ether_to_str(nonsr_hwaddr));
+ strcpy(fd->win_info[3], "TR");
+ sprintf(fd->win_info[4], "Token-Ring %s", fc[frame_type]);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), 0, 14 + rif_bytes,
+ "Token-Ring (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
+ fh_tree = gtk_tree_new();
+ add_subtree(ti, fh_tree, ETT_TOKEN_RING);
+ add_item_to_tree(fh_tree, 0, 1,
+ "Access Control: %s, Priority=%d, Monitor Count=%d, "
+ "Priority Reservation=%d",
+ ((pd[0] & 16) >> 4) ? "Frame" : "Token", /* frame/token */
+ ((pd[0] & 224) >> 5), /* priority */
+ ((pd[0] & 8) >> 3), /* monitor count */
+ ((pd[0] & 7))); /* priority reserv. */
+
+ add_item_to_tree(fh_tree, 1, 1,
+ "Frame Control: %s, Physical Control=%d (%s)",
+ fc[frame_type], (pd[1] & 15),
+ fc_pcf[(pd[1] & 15)]);
+
+ add_item_to_tree(fh_tree, 2, 6, "Destination: %s",
+ ether_to_str((guint8 *) &pd[2]));
+ add_item_to_tree(fh_tree, 8, 6, "Source: %s",
+ ether_to_str((guint8 *) &pd[8]));
+
+ if (source_routed) {
+ add_item_to_tree(fh_tree, 14, 1, "RIF length: %d bytes",
+ pd[14] & 31); /* not rif_bytes because of silly_linux */
+
+ add_item_to_tree(fh_tree, 15, 1,
+ "%s, up to %d bytes in frame (LF=%d)",
+ sr_broadcast((pd[14] & 224) >> 5),
+ sr_frame((pd[15] & 112) >> 4),
+ (pd[15] & 112) >> 4);
+
+ add_item_to_tree(fh_tree, 15, 1,
+ "Direction: %s (%s)",
+ rc_direction[(pd[15] & 128) >> 7],
+ rc_arrow[(pd[15] & 128) >> 7]);
+
+ /* if we have more than 2 bytes of RIF, then we have
+ ring/bridge pairs */
+ if ((pd[14] & 31) > 2) { /* not rif_bytes because of silly_linux */
+ add_ring_bridge_pairs(rif_bytes, pd, fh_tree);
+ }
+ }
+
+ /* Linux 2.0.x has a problem in that the 802.5 code creates
+ an emtpy full (18-byte) RIF area. It's up to the tr driver to
+ either fill it in or remove it before sending the bytes out
+ to the wire. If you run tcpdump on a Linux 2.0.x machine running
+ token-ring, tcpdump will capture these 18 filler bytes. They
+ are filled with garbage. The best way to detect this problem is
+ to know the src hwaddr of the machine from which you were running
+ 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 */
+ #ifdef linux
+ if ( (source_routed && ((pd[14] & 31) == 2) && silly_linux) ||
+ (!source_routed) && silly_linux ) {
+ add_item_to_tree(fh_tree, 14, 18,
+ "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
+ "is also running a protocol stack.");
+ }
+ #endif
+ }
+
+ /* The package is either MAC or LLC */
+ switch (frame_type) {
+ /* MAC */
+ case 0:
+ /* dissect_trmac(pd, offset, fd, tree) */
+ 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;
+ }
+}
+
+/* this routine is taken from the Linux net/802/tr.c code, which shows
+ring-bridge paires in the /proc/net/tr_rif virtual file. */
+static void
+add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree)
+{
+ int j, size;
+ int segment, brdgnmb;
+ char buffer[50];
+ int buff_offset=0;
+
+ rcf_len -= 2;
+
+ if (rcf_len)
+ rcf_len >>= 1;
+
+ for(j = 1; j < rcf_len; j++) {
+ if (j==1) {
+ segment=ntohs(*((unsigned short*)&pd[16])) >> 4;
+ size = sprintf(buffer,"%03X",segment);
+ buff_offset += size;
+ }
+ segment=ntohs(*((unsigned short*)&pd[17+j])) >> 4;
+ brdgnmb=pd[16+j] & 0x0f;
+ size = sprintf(buffer+buff_offset,"-%01X-%03X",brdgnmb,segment);
+ buff_offset += size;
+ }
+
+ add_item_to_tree(tree, 16, rcf_len << 1,
+ "Ring-Bridge Pairs: %s",
+ buffer);
+
+}
+