Ethereal-dev: Re: [ethereal-dev] Plugin for Cisco ISL

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Sat, 22 Jan 2000 21:31:29 -0800
> so the Ethernet dissector can check the destination address and
> special-case it.

The attached patch does exactly that, and the attached "packet-isl.c"
contains the ISL dissector.  The resulting program was able to dissect
the frames in "trunk.gz" without having to be told that the frames were
ISL; it also dissects regular Ethernet frames correctly.
? errs
? packet-isl.c
? ethereal.core
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/ethereal/Makefile.am,v
retrieving revision 1.157
diff -c -r1.157 Makefile.am
*** Makefile.am	2000/01/18 20:35:40	1.157
--- Makefile.am	2000/01/23 05:32:01
***************
*** 84,89 ****
--- 84,90 ----
  	packet-isis-lsp.c \
  	packet-isis-snp.h \
  	packet-isis-snp.c \
+ 	packet-isl.c   \
  	packet-l2tp.c  \
  	packet-lapb.c  \
  	packet-lapd.c  \
Index: packet-eth.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-eth.c,v
retrieving revision 1.25
diff -c -r1.25 packet-eth.c
*** packet-eth.c	1999/11/30 23:56:35	1.25
--- packet-eth.c	2000/01/23 05:32:01
***************
*** 148,153 ****
--- 148,162 ----
        ethhdr_type = ETHERNET_802_2;
      }
  
+     /* Oh, yuck.  Cisco ISL frames require special interpretation of the
+        destination address field; fortunately, they can be recognized by
+        checking the first 5 octets of the destination address, which are
+        01-00-0C-00-00 for ISL frames. */
+     if (pd[offset] == 0x01 && pd[offset+1] == 0x00 && pd[offset+2] == 0x0C
+ 	&& pd[offset+3] == 0x00 && pd[offset+4] == 0x00) {
+       dissect_isl(pd, offset, fd, tree);
+       return;
+     }
      if (check_col(fd, COL_INFO)) {
        col_add_fstr(fd, COL_INFO, "IEEE 802.3 %s",
  		(ethhdr_type == ETHERNET_802_3 ? "Raw " : ""));
Index: packet.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.h,v
retrieving revision 1.166
diff -c -r1.166 packet.h
*** packet.h	2000/01/20 21:34:14	1.166
--- packet.h	2000/01/23 05:32:03
***************
*** 356,361 ****
--- 356,362 ----
  void dissect_ipx(const u_char *, int, frame_data *, proto_tree *);
  void dissect_irc(const u_char *, int, frame_data *, proto_tree *);
  void dissect_isis(const u_char *, int, frame_data *, proto_tree *);
+ void dissect_isl(const u_char *, int, frame_data *, proto_tree *);
  void dissect_ldap(const u_char *, int, frame_data *, proto_tree *);
  void dissect_llc(const u_char *, int, frame_data *, proto_tree *);
  void dissect_lpd(const u_char *, int, frame_data *, proto_tree *);
/* packet-isl.c
 * Routines for Cisco ISL Ethernet header disassembly
 *
 * $Id$
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxx>
 * 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

#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif

#include <glib.h>
#include "packet.h"
#include "etypes.h"

/*
 * See
 *
 *	http://www.cisco.com/warp/public/741/4.html
 *
 * and
 *
 *	http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
 *
 * for information on ISL.
 */
static int proto_isl = -1;
static int hf_isl_dst = -1;
static int hf_isl_type = -1;
static int hf_isl_user_eth = -1;
static int hf_isl_user = -1;
static int hf_isl_src = -1;
static int hf_isl_len = -1;
static int hf_isl_hsa = -1;
static int hf_isl_vlan_id = -1;
static int hf_isl_bpdu = -1;
static int hf_isl_index = -1;
static int hf_isl_src_vlan_id = -1;
static int hf_isl_explorer = -1;
static int hf_isl_dst_route_descriptor = -1;
static int hf_isl_src_route_descriptor = -1;
static int hf_isl_fcs_not_incl = -1;
static int hf_isl_esize = -1;

static gint ett_isl = -1;

#if 0
void
capture_vlan(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld ) {
  guint32 encap_proto;
  if ( !BYTES_ARE_IN_FRAME(offset,5) ) {
    return; 
  }
  encap_proto = pntohs( &pd[offset+2] );
  if ( encap_proto <= IEEE_802_3_MAX_LEN) {
    if ( pd[offset+4] == 0xff && pd[offset+5] == 0xff ) {
      capture_ipx(pd,offset+4,cap_len,ld);
    } else {
      capture_llc(pd,offset+4,cap_len,ld);
    }
  } else {
    capture_ethertype(encap_proto, offset+4, pd, cap_len, ld);
  }
}
#endif

#define	ISL_HEADER_SIZE	26

#define	TYPE_ETHER	0x0
#define	TYPE_TR		0x1
#define	TYPE_FDDI	0x2
#define	TYPE_ATM	0x3

static const value_string type_vals[] = {
	{TYPE_ETHER, "Ethernet"},
	{TYPE_TR,    "Token-Ring"},
	{TYPE_FDDI,  "FDDI"},
	{TYPE_ATM,   "ATM"},
	{0,          NULL}
};

static const value_string ether_user_vals[] = {
	{0x0, "Normal priority"},
	{0x1, "Priority 1"},
	{0x2, "Priority 2"},
	{0x3, "Highest priority"},
	{0,   NULL}
};

static const true_false_string bpdu_tfs = {
	"Yes",
	"No"
};

static const true_false_string explorer_tfs = {
	"Explorer frame",
	"Data frame"
};

void
dissect_isl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{
  proto_tree *fh_tree = NULL;
  proto_item *ti;
  guint8 type;
  guint16 length;
  
  if (fd->cap_len < ISL_HEADER_SIZE) {
    dissect_data(pd, offset, fd, tree);
    return;
  }

  if (check_col(fd, COL_PROTOCOL))
    col_add_str(fd, COL_PROTOCOL, "ISL");

  if (tree) {
    ti = proto_tree_add_item_format(tree, proto_isl, offset, ISL_HEADER_SIZE,
		NULL, "ISL");
    fh_tree = proto_item_add_subtree(ti, ett_isl);
    proto_tree_add_item(fh_tree, hf_isl_dst, offset+0, 6, &pd[offset+0]);
    type = (pd[offset+5] >> 4)&0x0F;
    proto_tree_add_item(fh_tree, hf_isl_type, offset+5, 1, pd[offset+5]);
    switch (type) {

    case TYPE_ETHER:
      proto_tree_add_item(fh_tree, hf_isl_user_eth, offset+5, 1,
			pd[offset+5]&0x03);
      break;

    default:
      /* XXX - the spec appears to indicate that the "User" field is
         used for TYPE_TR to distinguish between types of packets. */
      proto_tree_add_item(fh_tree, hf_isl_user, offset+5, 1, pd[offset+5]);
      break;
    }
    proto_tree_add_item(fh_tree, hf_isl_src, offset+6, 6, &pd[offset+6]);
    length = pntohs(&pd[offset+12]);
    proto_tree_add_item(fh_tree, hf_isl_len, offset+12, 2, length);
    offset += 14;

    /* This part looks sort of like a SNAP-encapsulated LLC header... */
    proto_tree_add_text(fh_tree, offset, 1, "DSAP: 0x%X", pd[offset]);
    proto_tree_add_text(fh_tree, offset+1, 1, "SSAP: 0x%X", pd[offset+1]);
    proto_tree_add_text(fh_tree, offset+2, 1, "Control: 0x%X", pd[offset+2]);

    /* ...but this is the manufacturer's ID portion of the source address
       field (which is, admittedly, an OUI). */
    proto_tree_add_item(fh_tree, hf_isl_hsa, offset+3, 3,
		pd[offset+3] << 16 | pd[offset+4] << 8 | pd[offset+5]);
    proto_tree_add_item(fh_tree, hf_isl_vlan_id, offset+6, 2,
			pntohs(&pd[offset+6]));
    proto_tree_add_item(fh_tree, hf_isl_bpdu, offset+6, 2,
			pntohs(&pd[offset+6]));
    proto_tree_add_item(fh_tree, hf_isl_index, offset+8, 2,
	pntohs(&pd[offset+8]));

    switch (type) {

    case TYPE_ETHER:
      offset += 12;	/* skip the header */
      dissect_eth(pd, offset, fd, tree);
      break;

    case TYPE_TR:
      proto_tree_add_item(fh_tree, hf_isl_src_vlan_id, offset+10, 2,
			pntohs(&pd[offset+10]));
      proto_tree_add_item(fh_tree, hf_isl_explorer, offset+10, 2,
			pntohs(&pd[offset+10]));
      proto_tree_add_item(fh_tree, hf_isl_dst_route_descriptor, offset+12, 2,
			pntohs(&pd[offset+12]));
      proto_tree_add_item(fh_tree, hf_isl_src_route_descriptor, offset+14, 2,
			pntohs(&pd[offset+14]));
      proto_tree_add_item(fh_tree, hf_isl_fcs_not_incl, offset+16, 1,
			pd[offset+16]);
      proto_tree_add_item(fh_tree, hf_isl_esize, offset+16, 1,
			pd[offset+16]);
      dissect_tr(pd, offset, fd, tree);
      break;

    default:
      offset += 12;	/* skip the header */
      dissect_data(pd, offset, fd, tree);
      break;
    }
  }
}
    
void
proto_register_isl(void)
{
  static hf_register_info hf[] = {
	{ &hf_isl_dst,
	{ "Destination",	"isl.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
		"Destination Address" }},
	{ &hf_isl_type,
	{ "Type",		"isl.type", FT_UINT8, BASE_NONE,
		VALS(type_vals), 0xF0, "Type" }},
	{ &hf_isl_user_eth,
	{ "User",		"isl.user_eth", FT_UINT8, BASE_NONE,
		VALS(ether_user_vals), 0x0F, "Priority (for Ethernet)" }},
	{ &hf_isl_user,
	{ "User",		"isl.user", FT_UINT8, BASE_HEX, NULL, 0x0F,
		"User-defined bits" }},
	{ &hf_isl_src,
	{ "Source",		"isl.src", FT_ETHER, BASE_NONE, NULL, 0x0,
		"Source Hardware Address" }},
	{ &hf_isl_len,
	{ "Length",		"isl.len", FT_UINT16, BASE_DEC, NULL, 0x0,
		"" }},
	{ &hf_isl_hsa,
	{ "HSA",		"isl.hsa", FT_UINT24, BASE_HEX, NULL, 0x0,
		"High bits of source address" }},
	{ &hf_isl_vlan_id,
	{ "VLAN ID",		"isl.vlan_id", FT_UINT16, BASE_HEX, NULL,
		0xFFFE, "Virtual LAN ID" }},
	{ &hf_isl_bpdu,
	{ "BPDU",		"isl.bpdu", FT_BOOLEAN, 16,
		TFS(&bpdu_tfs), 0x0001, "BPDU indicator" }},
	{ &hf_isl_index,
	{ "Index",		"isl.index", FT_UINT16, BASE_DEC, NULL, 0x0,
		"Port index of packet source" }},
	{ &hf_isl_src_vlan_id,
	{ "Source VLAN ID",	"isl.src_vlan_id", FT_UINT16, BASE_HEX, NULL,
		0xFFFE, "Source Virtual LAN ID" }},
	{ &hf_isl_explorer,
	{ "Explorer",		"isl.explorer", FT_BOOLEAN, 16,
		TFS(&explorer_tfs), 0x0001, "Explorer" }},
	{ &hf_dst_route_descriptor,
	{ "Destination route descriptor",	"isl.dst_route_desc",
		FT_UINT16, BASE_HEX, NULL, 0x0,
		"Route descriptor to be used for forwarding" }},
	{ &hf_src_route_descriptor,
	{ "Source-route descriptor",	"isl.src_route_desc",
		FT_UINT16, BASE_HEX, NULL, 0x0,
		"Route descriptor to be used for source learning" }},
	{ &hf_isl_fcs_not_incl,
	{ "FCS Not Included",	"isl.fcs_not_incl", FT_BOOLEAN, 9,
		NULL, 0x40, "FCS not included" }},
	{ &hf_isl_esize,
	{ "Esize",	"isl.esize", FT_UINT8, BASE_DEC, NULL,
		0x3F, "Frame size for frames less than 64 bytes" }},
  };
  static gint *ett[] = {
	&ett_isl,
  };

  proto_isl = proto_register_protocol("Cisco ISL", "isl");
  proto_register_field_array(proto_isl, hf, array_length(hf));
  proto_register_subtree_array(ett, array_length(ett));
}