Convert token-ring dissector to use tvbuffs.

Modify ethernet dissector to catch BoundsError if the attempt to
create next_tvb with the length specified in the ethernet header throws
an exception. In that case, next_tv is created with as many bytes as
are available in the frame.

Both dissect_tr() and dissect_eth() now have TRY blocks, which means
I had to fiddle with 'volatile' and 'static' storage options to get
things right (at least according to gcc).

svn path=/trunk/; revision=1962
This commit is contained in:
Gilbert Ramirez 2000-05-15 06:22:07 +00:00
parent 6c2a7af1f6
commit ec3337ed07
6 changed files with 227 additions and 168 deletions

View File

@ -1,7 +1,7 @@
/* packet-atm.c /* packet-atm.c
* Routines for ATM packet disassembly * Routines for ATM packet disassembly
* *
* $Id: packet-atm.c,v 1.15 2000/05/11 22:04:15 gram Exp $ * $Id: packet-atm.c,v 1.16 2000/05/15 06:22:05 gram Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org> * By Gerald Combs <gerald@zing.org>
@ -373,6 +373,10 @@ dissect_le_control(const u_char *pd, int offset, frame_data *fd, proto_tree *tre
static void static void
dissect_lane(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) dissect_lane(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{ {
tvbuff_t *next_tvb;
next_tvb = tvb_new_subset(pi.compat_top_tvb, offset, -1);
if (check_col(fd, COL_PROTOCOL)) if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "ATM LANE"); col_add_str(fd, COL_PROTOCOL, "ATM LANE");
if (check_col(fd, COL_INFO)) if (check_col(fd, COL_INFO))
@ -400,12 +404,12 @@ dissect_lane(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
offset += 2; offset += 2;
/* Dissect as Token-Ring */ /* Dissect as Token-Ring */
dissect_tr(pd, offset, fd, tree); dissect_tr(next_tvb, &pi, tree);
break; break;
default: default:
/* Dump it as raw data. */ /* Dump it as raw data. */
dissect_data(pd, offset, fd, tree); dissect_data_tvb(next_tvb, &pi, tree);
break; break;
} }
} }

View File

@ -1,7 +1,7 @@
/* packet-eth.c /* packet-eth.c
* Routines for ethernet packet disassembly * Routines for ethernet packet disassembly
* *
* $Id: packet-eth.c,v 1.35 2000/05/12 19:15:53 gram Exp $ * $Id: packet-eth.c,v 1.36 2000/05/15 06:22:05 gram Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org> * By Gerald Combs <gerald@zing.org>
@ -139,29 +139,36 @@ capture_eth(const u_char *pd, int offset, packet_counts *ld)
void void
dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{ {
int orig_captured_len; int orig_captured_len;
guint16 etype, length; guint16 length;
proto_tree *fh_tree = NULL; volatile guint16 etype;
proto_item *ti; proto_item *ti;
int ethhdr_type; /* the type of ethernet frame */ volatile int ethhdr_type; /* the type of ethernet frame */
tvbuff_t *next_tvb;
if (!BYTES_ARE_IN_FRAME(offset, ETH_HEADER_SIZE)) { /* These are static because I need to modify them before the TRY block,
dissect_data(pd, offset, fd, tree); * and gcc says that they might get clobbered otherwise. */
static tvbuff_t *next_tvb = NULL;
static int eth_offset;
static proto_tree *fh_tree = NULL;
eth_offset = offset;
if (!BYTES_ARE_IN_FRAME(eth_offset, ETH_HEADER_SIZE)) {
dissect_data(pd, eth_offset, fd, tree);
return; return;
} }
pi.current_proto = "Ethernet";
orig_captured_len = pi.captured_len; orig_captured_len = pi.captured_len;
SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &pd[offset+6]); SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &pd[eth_offset+6]);
SET_ADDRESS(&pi.src, AT_ETHER, 6, &pd[offset+6]); SET_ADDRESS(&pi.src, AT_ETHER, 6, &pd[eth_offset+6]);
SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &pd[offset+0]); SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &pd[eth_offset+0]);
SET_ADDRESS(&pi.dst, AT_ETHER, 6, &pd[offset+0]); SET_ADDRESS(&pi.dst, AT_ETHER, 6, &pd[eth_offset+0]);
if (check_col(fd, COL_PROTOCOL)) if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "Ethernet"); col_add_str(fd, COL_PROTOCOL, "Ethernet");
etype = pntohs(&pd[offset+12]); etype = pntohs(&pd[eth_offset+12]);
/* either ethernet802.3 or ethernet802.2 */ /* either ethernet802.3 or ethernet802.2 */
if (etype <= IEEE_802_3_MAX_LEN) { if (etype <= IEEE_802_3_MAX_LEN) {
@ -173,7 +180,7 @@ dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
(IPX/SPX is they only thing that can be contained inside a (IPX/SPX is they only thing that can be contained inside a
straight 802.3 packet). A non-0xffff value means that there's an straight 802.3 packet). A non-0xffff value means that there's an
802.2 layer inside the 802.3 layer */ 802.2 layer inside the 802.3 layer */
if (pd[offset+14] == 0xff && pd[offset+15] == 0xff) { if (pd[eth_offset+14] == 0xff && pd[eth_offset+15] == 0xff) {
ethhdr_type = ETHERNET_802_3; ethhdr_type = ETHERNET_802_3;
} }
else { else {
@ -184,9 +191,9 @@ dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
destination address field; fortunately, they can be recognized by destination address field; fortunately, they can be recognized by
checking the first 5 octets of the destination address, which are checking the first 5 octets of the destination address, which are
01-00-0C-00-00 for ISL frames. */ 01-00-0C-00-00 for ISL frames. */
if (pd[offset] == 0x01 && pd[offset+1] == 0x00 && pd[offset+2] == 0x0C if (pd[eth_offset] == 0x01 && pd[eth_offset+1] == 0x00 && pd[eth_offset+2] == 0x0C
&& pd[offset+3] == 0x00 && pd[offset+4] == 0x00) { && pd[eth_offset+3] == 0x00 && pd[eth_offset+4] == 0x00) {
dissect_isl(pd, offset, fd, tree); dissect_isl(pd, eth_offset, fd, tree);
return; return;
} }
@ -196,19 +203,19 @@ dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
} }
if (tree) { if (tree) {
ti = proto_tree_add_protocol_format(tree, proto_eth, NullTVB, offset, ETH_HEADER_SIZE, ti = proto_tree_add_protocol_format(tree, proto_eth, NullTVB, eth_offset, ETH_HEADER_SIZE,
"IEEE 802.3 %s", (ethhdr_type == ETHERNET_802_3 ? "Raw " : "")); "IEEE 802.3 %s", (ethhdr_type == ETHERNET_802_3 ? "Raw " : ""));
fh_tree = proto_item_add_subtree(ti, ett_ieee8023); fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
proto_tree_add_item(fh_tree, hf_eth_dst, NullTVB, offset+0, 6, &pd[offset+0]); proto_tree_add_item(fh_tree, hf_eth_dst, NullTVB, eth_offset+0, 6, &pd[eth_offset+0]);
proto_tree_add_item(fh_tree, hf_eth_src, NullTVB, offset+6, 6, &pd[offset+6]); proto_tree_add_item(fh_tree, hf_eth_src, NullTVB, eth_offset+6, 6, &pd[eth_offset+6]);
/* add items for eth.addr filter */ /* add items for eth.addr filter */
proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 0, 6, &pd[offset+0]); proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, eth_offset + 0, 6, &pd[eth_offset+0]);
proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 6, 6, &pd[offset+6]); proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, eth_offset + 6, 6, &pd[eth_offset+6]);
proto_tree_add_item(fh_tree, hf_eth_len, NullTVB, offset+12, 2, length); proto_tree_add_item(fh_tree, hf_eth_len, NullTVB, eth_offset+12, 2, length);
} }
/* Convert the LLC length from the 802.3 header to a total /* Convert the LLC length from the 802.3 header to a total
@ -216,7 +223,7 @@ dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
the Ethernet header, and adding in the Ethernet header size, the Ethernet header, and adding in the Ethernet header size,
and set the payload and captured-payload lengths to the minima and set the payload and captured-payload lengths to the minima
of the total length and the frame lengths. */ of the total length and the frame lengths. */
length += offset + ETH_HEADER_SIZE; length += eth_offset + ETH_HEADER_SIZE;
if (pi.len > length) if (pi.len > length)
pi.len = length; pi.len = length;
if (pi.captured_len > length) if (pi.captured_len > length)
@ -227,37 +234,43 @@ dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
col_add_str(fd, COL_INFO, "Ethernet II"); col_add_str(fd, COL_INFO, "Ethernet II");
if (tree) { if (tree) {
ti = proto_tree_add_protocol_format(tree, proto_eth, NullTVB, offset, ETH_HEADER_SIZE, ti = proto_tree_add_protocol_format(tree, proto_eth, NullTVB, eth_offset, ETH_HEADER_SIZE,
"Ethernet II"); "Ethernet II");
fh_tree = proto_item_add_subtree(ti, ett_ether2); fh_tree = proto_item_add_subtree(ti, ett_ether2);
proto_tree_add_item(fh_tree, hf_eth_dst, NullTVB, offset+0, 6, &pd[offset+0]); proto_tree_add_item(fh_tree, hf_eth_dst, NullTVB, eth_offset+0, 6, &pd[eth_offset+0]);
proto_tree_add_item(fh_tree, hf_eth_src, NullTVB, offset+6, 6, &pd[offset+6]); proto_tree_add_item(fh_tree, hf_eth_src, NullTVB, eth_offset+6, 6, &pd[eth_offset+6]);
/* add items for eth.addr filter */ /* add items for eth.addr filter */
proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 0, 6, &pd[offset+0]); proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, eth_offset + 0, 6, &pd[eth_offset+0]);
proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 6, 6, &pd[offset+6]); proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, eth_offset + 6, 6, &pd[eth_offset+6]);
} }
} }
offset += ETH_HEADER_SIZE; eth_offset += ETH_HEADER_SIZE;
/* Give the next dissector only 'length' number of bytes */ /* Give the next dissector only 'length' number of bytes */
if (etype <= IEEE_802_3_MAX_LEN) { if (etype <= IEEE_802_3_MAX_LEN) {
next_tvb = tvb_new_subset(pi.compat_top_tvb, offset, etype); TRY {
next_tvb = tvb_new_subset(pi.compat_top_tvb, eth_offset, etype);
}
CATCH(BoundsError) {
next_tvb = tvb_new_subset(pi.compat_top_tvb, eth_offset, -1);
}
ENDTRY;
} }
else { else {
next_tvb = tvb_new_subset(pi.compat_top_tvb, offset, -1); next_tvb = tvb_new_subset(pi.compat_top_tvb, eth_offset, -1);
} }
switch (ethhdr_type) { switch (ethhdr_type) {
case ETHERNET_802_3: case ETHERNET_802_3:
dissect_ipx(pd, offset, fd, tree); dissect_ipx(pd, eth_offset, fd, tree);
break; break;
case ETHERNET_802_2: case ETHERNET_802_2:
dissect_llc(next_tvb, &pi, tree); dissect_llc(next_tvb, &pi, tree);
break; break;
case ETHERNET_II: case ETHERNET_II:
ethertype(etype, offset, pd, fd, tree, fh_tree, hf_eth_type); ethertype(etype, eth_offset, pd, fd, tree, fh_tree, hf_eth_type);
break; break;
} }

View File

@ -1,7 +1,7 @@
/* packet-isl.c /* packet-isl.c
* Routines for Cisco ISL Ethernet header disassembly * Routines for Cisco ISL Ethernet header disassembly
* *
* $Id: packet-isl.c,v 1.8 2000/05/11 08:15:17 gram Exp $ * $Id: packet-isl.c,v 1.9 2000/05/15 06:22:06 gram Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org> * By Gerald Combs <gerald@zing.org>
@ -144,6 +144,7 @@ dissect_isl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
proto_item *ti; proto_item *ti;
guint8 type; guint8 type;
guint16 length; guint16 length;
tvbuff_t *next_tvb;
if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) { if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
dissect_data(pd, offset, fd, tree); dissect_data(pd, offset, fd, tree);
@ -224,7 +225,8 @@ dissect_isl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
pd[offset+30]); pd[offset+30]);
proto_tree_add_item(fh_tree, hf_isl_esize, NullTVB, offset+16, 1, proto_tree_add_item(fh_tree, hf_isl_esize, NullTVB, offset+16, 1,
pd[offset+30]); pd[offset+30]);
dissect_tr(pd, offset+31, fd, tree); next_tvb = tvb_new_subset(pi.compat_top_tvb, offset+31, -1);
dissect_tr(next_tvb, &pi, tree);
break; break;
default: default:

View File

@ -2,7 +2,7 @@
* Routines for Token-Ring packet disassembly * Routines for Token-Ring packet disassembly
* Gilbert Ramirez <gram@xiexie.org> * Gilbert Ramirez <gram@xiexie.org>
* *
* $Id: packet-tr.c,v 1.39 2000/05/11 22:04:17 gram Exp $ * $Id: packet-tr.c,v 1.40 2000/05/15 06:22:06 gram Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org> * By Gerald Combs <gerald@zing.org>
@ -134,6 +134,29 @@ static const value_string direction_vals[] = {
* (And this real frame x bytes in looks like a proper TR frame that goes on the wire * (And this real frame x bytes in looks like a proper TR frame that goes on the wire
* with none of the Linux idiosyncrasies). * with none of the Linux idiosyncrasies).
*/ */
int check_for_old_linux_tvb(tvbuff_t *tvb)
{
guint8 *data;
int x, bytes;
/* Restrict our looping to the boundaries of the frame */
bytes = tvb_length(tvb);
if (bytes > 19) {
bytes = 19;
}
data = tvb_get_ptr(tvb, 0, bytes);
for(x = 1; x <= bytes-1 ;x++)
{
if (memcmp(&data[0], &data[x], x) == 0)
{
return x;
}
}
return 0;
}
int check_for_old_linux(const u_char * pd) int check_for_old_linux(const u_char * pd)
{ {
int x; int x;
@ -147,8 +170,9 @@ int check_for_old_linux(const u_char * pd)
return 0; return 0;
} }
static void static void
add_ring_bridge_pairs(int rcf_len, const u_char *pd, int offset, proto_tree *tree); add_ring_bridge_pairs(int rcf_len, tvbuff_t*, proto_tree *tree);
void void
capture_tr(const u_char *pd, int offset, packet_counts *ld) { capture_tr(const u_char *pd, int offset, packet_counts *ld) {
@ -251,7 +275,7 @@ capture_tr(const u_char *pd, int offset, packet_counts *ld) {
} }
} }
offset += actual_rif_bytes + 14; offset += actual_rif_bytes + TR_MIN_HEADER_LEN;
/* The package is either MAC or LLC */ /* The package is either MAC or LLC */
switch (frame_type) { switch (frame_type) {
@ -271,16 +295,25 @@ capture_tr(const u_char *pd, int offset, packet_counts *ld) {
void void
dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { dissect_tr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *tr_tree, *bf_tree; proto_tree *tr_tree, *bf_tree;
proto_item *ti; proto_item *ti;
int fixoffset = 0;
int source_routed = 0;
int frame_type; int frame_type;
guint8 trn_rif_bytes; guint8 rcf1, rcf2;
guint8 actual_rif_bytes;
tvbuff_t *next_tvb; tvbuff_t *next_tvb;
int next_offset;
const guint8* next_pd;
volatile int fixoffset = 0;
volatile int source_routed = 0;
volatile guint8 trn_rif_bytes;
volatile guint8 actual_rif_bytes;
/* I make tr_tvb static because I need to set it before any TRY block.
* If tr_tvb were not static, the possibility exists that the value
* I give to tr_tvb would be clobbered. */
static tvbuff_t *tr_tvb = NULL;
/* The trn_hdr struct, as separate variables */ /* The trn_hdr struct, as separate variables */
guint8 trn_ac; /* access control field */ guint8 trn_ac; /* access control field */
@ -295,33 +328,38 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
/* Token-Ring Strings */ /* Token-Ring Strings */
char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" }; char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
if (!BYTES_ARE_IN_FRAME(offset, TR_MIN_HEADER_LEN)) { pinfo->current_proto = "Token-Ring";
dissect_data(pd, offset, fd, tree);
return;
}
if ((x = check_for_old_linux(pd))) if (check_col(pinfo->fd, COL_PROTOCOL))
{ col_add_str(pinfo->fd, COL_PROTOCOL, "TR");
if ((x = check_for_old_linux_tvb((tvbuff_t*) tvb))) {
/* Actually packet starts x bytes into what we have got but with all /* Actually packet starts x bytes into what we have got but with all
source routing compressed. See comment above */ source routing compressed. See comment above */
offset += x; tr_tvb = tvb_new_subset((tvbuff_t*) tvb, x, -1);
/* pd = &pd[x]; */ }
else {
tr_tvb = tvb;
} }
/* get the data */ /* Get the data */
trn_fc = pd[offset+1]; trn_fc = tvb_get_guint8(tr_tvb, 1);
trn_dhost = &pd[offset+2]; trn_dhost = tvb_get_ptr(tr_tvb, 2, 6);
trn_shost = &pd[offset+8]; trn_shost = tvb_get_ptr(tr_tvb, 8, 6);
memcpy(trn_shost_nonsr, trn_shost, 6 * sizeof(guint8));
memcpy(trn_shost_nonsr, trn_shost, 6);
trn_shost_nonsr[0] &= 127; trn_shost_nonsr[0] &= 127;
frame_type = (trn_fc & 192) >> 6; frame_type = (trn_fc & 192) >> 6;
if (check_col(pinfo->fd, COL_INFO))
col_add_fstr(pinfo->fd, COL_INFO, "Token-Ring %s", fc[frame_type]);
/* if the high bit on the first byte of src hwaddr is 1, then /* if the high bit on the first byte of src hwaddr is 1, then
this packet is source-routed */ this packet is source-routed */
source_routed = trn_shost[0] & 128; source_routed = trn_shost[0] & 128;
trn_rif_bytes = pd[offset+14] & 31; trn_rif_bytes = tvb_get_guint8(tr_tvb, 14) & 31;
/* sometimes we have a RCF but no RIF... half source-routed? */ /* sometimes we have a RCF but no RIF... half source-routed? */
/* I'll check for 2 bytes of RIF and the 0x70 byte */ /* I'll check for 2 bytes of RIF and the 0x70 byte */
@ -336,23 +374,23 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
* see if there's a SNAP or IPX field right after * see if there's a SNAP or IPX field right after
* my RIF fields. * my RIF fields.
*/ */
else if ( ( else {
pd[offset + 0x0e + trn_rif_bytes] == 0xaa && TRY {
pd[offset + 0x0f + trn_rif_bytes] == 0xaa && if ( ( tvb_get_ntohs(tr_tvb, trn_rif_bytes + 0x0e) == 0xaaaa &&
pd[offset + 0x10 + trn_rif_bytes] == 0x03) || tvb_get_guint8(tr_tvb, trn_rif_bytes + 0x10) == 0x03) ||
(
pd[offset + 0x0e + trn_rif_bytes] == 0xe0 && tvb_get_ntohs(tr_tvb, trn_rif_bytes + 0x0e) == 0xe0e0 ) {
pd[offset + 0x0f + trn_rif_bytes] == 0xe0) ) {
source_routed = 1; source_routed = 1;
}
}
CATCH(BoundsError) {
/* We had no information beyond the TR header. Just assume
* this is a normal (non-Linux) TR header. */
;
}
ENDTRY;
} }
/* else {
printf("0e+%d = %02X 0f+%d = %02X\n", trn_rif_bytes,
pd[offset + 0x0e + trn_rif_bytes],
trn_rif_bytes,
pd[offset + 0x0f + trn_rif_bytes]);
} */
} }
if (source_routed) { if (source_routed) {
@ -366,36 +404,41 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
/* this is a silly hack for Linux 2.0.x. Read the comment below, /* 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, in front of the other #ifdef linux. If we're sniffing our own NIC,
we get a full RIF, sometimes with garbage */ we get a full RIF, sometimes with garbage */
if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) || TRY {
(!source_routed && frame_type == 1)) { if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
/* look for SNAP or IPX only */ (!source_routed && frame_type == 1)) {
if ( (pd[offset + 0x20] == 0xaa && /* look for SNAP or IPX only */
pd[offset + 0x21] == 0xaa && if (
pd[offset + 0x22] == 03) (tvb_get_ntohs(tr_tvb, 0x20) == 0xaaaa &&
|| tvb_get_guint8(tr_tvb, 0x22) == 0x03)
(pd[offset + 0x20] == 0xe0 && ||
pd[offset + 0x21] == 0xe0) ) { tvb_get_ntohs(tr_tvb, 0x20) == 0xe0e0 ) {
actual_rif_bytes = 18; actual_rif_bytes = 18;
} }
else if ( else if (
pd[0x23] == 0 && tvb_get_ntohl(tr_tvb, 0x23) == 0 &&
pd[0x24] == 0 && tvb_get_guint8(tr_tvb, 0x27) == 0x11) {
pd[0x25] == 0 &&
pd[0x26] == 0x00 &&
pd[0x27] == 0x11) {
actual_rif_bytes = 18; actual_rif_bytes = 18;
/* Linux 2.0.x also requires drivers pass up a fake SNAP and LLC header before th /* Linux 2.0.x also requires drivers pass up a fake SNAP and LLC header before th
real LLC hdr for all Token Ring frames that arrive with DSAP and SSAP != 0xAA real LLC hdr for all Token Ring frames that arrive with DSAP and SSAP != 0xAA
(i.e. for non SNAP frames e.g. for Netware frames) (i.e. for non SNAP frames e.g. for Netware frames)
the fake SNAP header has the ETH_P_TR_802_2 ether type (0x0011) and the protocol id the fake SNAP header has the ETH_P_TR_802_2 ether type (0x0011) and the protocol id
bytes as zero frame looks like :- bytes as zero frame looks like :-
TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data */ TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data */
fixoffset += 8; /* Skip fake LLC and SNAP */ fixoffset += 8; /* Skip fake LLC and SNAP */
} }
}
} }
CATCH(BoundsError) {
/* We had no information beyond the TR header. Just assume
* this is a normal (non-Linux) TR header. */
;
}
ENDTRY;
/* XXX - copy it to some buffer associated with "pi", rather than /* XXX - copy it to some buffer associated with "pi", rather than
just making "trn_shost_nonsr" static? */ just making "trn_shost_nonsr" static? */
@ -404,58 +447,53 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, trn_dhost); SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, trn_dhost);
SET_ADDRESS(&pi.dst, AT_ETHER, 6, trn_dhost); SET_ADDRESS(&pi.dst, AT_ETHER, 6, trn_dhost);
/* information window */
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 */ /* protocol analysis tree */
if (tree) { if (tree) {
/* Create Token-Ring Tree */ /* Create Token-Ring Tree */
ti = proto_tree_add_item(tree, proto_tr, NullTVB, offset, 14 + actual_rif_bytes, NULL); ti = proto_tree_add_item(tree, proto_tr, tr_tvb, 0, TR_MIN_HEADER_LEN + 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 */ /* Create the Access Control bitfield tree */
trn_ac = pd[offset+0]; trn_ac = tvb_get_guint8(tr_tvb, 0);
ti = proto_tree_add_item(tr_tree, hf_tr_ac, NullTVB, offset, 1, trn_ac); ti = proto_tree_add_item(tr_tree, hf_tr_ac, tr_tvb, 0, 1, trn_ac);
bf_tree = proto_item_add_subtree(ti, ett_token_ring_ac); bf_tree = proto_item_add_subtree(ti, ett_token_ring_ac);
proto_tree_add_item(bf_tree, hf_tr_priority, NullTVB, offset, 1, trn_ac); proto_tree_add_item(bf_tree, hf_tr_priority, tr_tvb, 0, 1, trn_ac);
proto_tree_add_item(bf_tree, hf_tr_frame, NullTVB, offset, 1, trn_ac); proto_tree_add_item(bf_tree, hf_tr_frame, tr_tvb, 0, 1, trn_ac);
proto_tree_add_item(bf_tree, hf_tr_monitor_cnt, NullTVB, offset, 1, trn_ac); proto_tree_add_item(bf_tree, hf_tr_monitor_cnt, tr_tvb, 0, 1, trn_ac);
proto_tree_add_item(bf_tree, hf_tr_priority_reservation, NullTVB, offset, 1, trn_ac); proto_tree_add_item(bf_tree, hf_tr_priority_reservation, tr_tvb, 0, 1, trn_ac);
/* Create the Frame Control bitfield tree */ /* Create the Frame Control bitfield tree */
ti = proto_tree_add_item(tr_tree, hf_tr_fc, NullTVB, offset + 1, 1, trn_fc); ti = proto_tree_add_item(tr_tree, hf_tr_fc, tr_tvb, 1, 1, trn_fc);
bf_tree = proto_item_add_subtree(ti, ett_token_ring_fc); bf_tree = proto_item_add_subtree(ti, ett_token_ring_fc);
proto_tree_add_item(bf_tree, hf_tr_fc_type, NullTVB, offset + 1, 1, trn_fc); proto_tree_add_item(bf_tree, hf_tr_fc_type, tr_tvb, 1, 1, trn_fc);
proto_tree_add_item(bf_tree, hf_tr_fc_pcf, NullTVB, offset + 1, 1, trn_fc); proto_tree_add_item(bf_tree, hf_tr_fc_pcf, tr_tvb, 1, 1, trn_fc);
proto_tree_add_item(tr_tree, hf_tr_dst, NullTVB, offset + 2, 6, trn_dhost); proto_tree_add_item(tr_tree, hf_tr_dst, tr_tvb, 2, 6, trn_dhost);
proto_tree_add_item(tr_tree, hf_tr_src, NullTVB, offset + 8, 6, trn_shost); proto_tree_add_item(tr_tree, hf_tr_src, tr_tvb, 8, 6, trn_shost);
proto_tree_add_item_hidden(tr_tree, hf_tr_addr, NullTVB, offset + 2, 6, trn_dhost); proto_tree_add_item_hidden(tr_tree, hf_tr_addr, tr_tvb, 2, 6, trn_dhost);
proto_tree_add_item_hidden(tr_tree, hf_tr_addr, NullTVB, offset + 8, 6, trn_shost); proto_tree_add_item_hidden(tr_tree, hf_tr_addr, tr_tvb, 8, 6, trn_shost);
proto_tree_add_item(tr_tree, hf_tr_sr, NullTVB, offset + 8, 1, source_routed); proto_tree_add_item(tr_tree, hf_tr_sr, tr_tvb, 8, 1, source_routed);
/* non-source-routed version of src addr */ /* non-source-routed version of src addr */
proto_tree_add_item_hidden(tr_tree, hf_tr_src, NullTVB, offset + 8, 6, trn_shost_nonsr); proto_tree_add_item_hidden(tr_tree, hf_tr_src, tr_tvb, 8, 6, trn_shost_nonsr);
if (source_routed) { if (source_routed) {
/* RCF Byte 1 */ /* RCF Byte 1 */
proto_tree_add_item(tr_tree, hf_tr_rif_bytes, NullTVB, offset + 14, 1, trn_rif_bytes); rcf1 = tvb_get_guint8(tr_tvb, 14);
proto_tree_add_item(tr_tree, hf_tr_broadcast, NullTVB, offset + 14, 1, pd[offset + 14] & 224); proto_tree_add_item(tr_tree, hf_tr_rif_bytes, tr_tvb, 14, 1, trn_rif_bytes);
proto_tree_add_item(tr_tree, hf_tr_broadcast, tr_tvb, 14, 1, rcf1 & 224);
/* RCF Byte 2 */ /* RCF Byte 2 */
proto_tree_add_item(tr_tree, hf_tr_max_frame_size, NullTVB, offset + 15, 1, pd[offset + 15] & 112); rcf2 = tvb_get_guint8(tr_tvb, 15);
proto_tree_add_item(tr_tree, hf_tr_direction, NullTVB, offset + 15, 1, pd[offset + 15] & 128); proto_tree_add_item(tr_tree, hf_tr_max_frame_size, tr_tvb, 15, 1, rcf2 & 112);
proto_tree_add_item(tr_tree, hf_tr_direction, tr_tvb, 15, 1, rcf2 & 128);
/* if we have more than 2 bytes of RIF, then we have /* if we have more than 2 bytes of RIF, then we have
ring/bridge pairs */ ring/bridge pairs */
if ((trn_rif_bytes > 2) && BYTES_ARE_IN_FRAME(offset + 14, trn_rif_bytes)) { if (trn_rif_bytes > 2) {
add_ring_bridge_pairs(trn_rif_bytes, add_ring_bridge_pairs(trn_rif_bytes, tr_tvb, tr_tree);
pd, offset, tr_tree);
} }
} }
@ -467,47 +505,49 @@ dissect_tr(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
are filled with garbage. The best way to detect this problem is 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 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 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 */ frame type is LLC. It's very much a hack. */
if (actual_rif_bytes > trn_rif_bytes) { if (actual_rif_bytes > trn_rif_bytes) {
proto_tree_add_text(tr_tree, NullTVB, 14 + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes, proto_tree_add_text(tr_tree, tr_tvb, TR_MIN_HEADER_LEN + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes,
"Empty RIF from Linux 2.0.x driver. The sniffing NIC " "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
"is also running a protocol stack."); "is also running a protocol stack.");
} }
if (fixoffset) { if (fixoffset) {
proto_tree_add_text(tr_tree, NullTVB, 14 + 18,8,"Linux 2.0.x fake LLC and SNAP header"); proto_tree_add_text(tr_tree, tr_tvb, TR_MIN_HEADER_LEN + 18,8,"Linux 2.0.x fake LLC and SNAP header");
} }
} }
offset += 14 + actual_rif_bytes + fixoffset;
if (IS_DATA_IN_FRAME(offset)) {
next_tvb = tvb_new_subset(pi.compat_top_tvb, offset, -1);
/* The package is either MAC or LLC */ next_tvb = tvb_new_subset(tr_tvb, TR_MIN_HEADER_LEN + actual_rif_bytes + fixoffset, -1);
switch (frame_type) { tvb_compat(next_tvb, &next_pd, &next_offset);
/* MAC */
case 0: /* The package is either MAC or LLC */
dissect_trmac(pd, offset, fd, tree); switch (frame_type) {
break; /* MAC */
case 1: case 0:
dissect_llc(next_tvb, &pi, tree); dissect_trmac(next_pd, next_offset, pinfo->fd, tree);
break; break;
default: case 1:
/* non-MAC, non-LLC, i.e., "Reserved" */ dissect_llc(next_tvb, pinfo, tree);
dissect_data_tvb(next_tvb, &pi, tree); break;
break; default:
} /* non-MAC, non-LLC, i.e., "Reserved" */
dissect_data_tvb(next_tvb, pinfo, tree);
break;
} }
} }
/* this routine is taken from the Linux net/802/tr.c code, which shows /* this routine is taken from the Linux net/802/tr.c code, which shows
ring-bridge pairs in the /proc/net/tr_rif virtual file. */ ring-bridge pairs in the /proc/net/tr_rif virtual file. */
static void static void
add_ring_bridge_pairs(int rcf_len, const u_char *pd, int offset, proto_tree *tree) add_ring_bridge_pairs(int rcf_len, tvbuff_t *tvb, proto_tree *tree)
{ {
int j, size; int j, size;
int segment, brdgnmb, unprocessed_rif; int segment, brdgnmb, unprocessed_rif;
int buff_offset=0; int buff_offset=0;
#define RIF_BYTES_TO_PROCESS 30 #define RIF_OFFSET 16
#define RIF_BYTES_TO_PROCESS 30
char buffer[3 + (RIF_BYTES_TO_PROCESS / 2) * 6 + 1]; char buffer[3 + (RIF_BYTES_TO_PROCESS / 2) * 6 + 1];
@ -521,22 +561,22 @@ add_ring_bridge_pairs(int rcf_len, const u_char *pd, int offset, proto_tree *tre
for(j = 1; j < rcf_len - 1; j += 2) { for(j = 1; j < rcf_len - 1; j += 2) {
if (j==1) { if (j==1) {
segment=pntohs(&pd[offset + 16]) >> 4; segment = tvb_get_ntohs(tvb, RIF_OFFSET) >> 4;
size = sprintf(buffer, "%03X",segment); size = sprintf(buffer, "%03X",segment);
proto_tree_add_item_hidden(tree, hf_tr_rif_ring, NullTVB, offset + 16, 2, segment); proto_tree_add_item_hidden(tree, hf_tr_rif_ring, tvb, TR_MIN_HEADER_LEN + 2, 2, segment);
buff_offset += size; buff_offset += size;
} }
segment=pntohs(&pd[offset+17+j]) >> 4; segment = tvb_get_ntohs(tvb, RIF_OFFSET + 1 + j) >> 4;
brdgnmb=pd[offset+16+j] & 0x0f; brdgnmb = tvb_get_guint8(tvb, RIF_OFFSET + j) & 0x0f;
size = sprintf(buffer+buff_offset, "-%01X-%03X",brdgnmb,segment); size = sprintf(buffer+buff_offset, "-%01X-%03X",brdgnmb,segment);
proto_tree_add_item_hidden(tree, hf_tr_rif_ring, NullTVB, offset+17+j, 2, segment); proto_tree_add_item_hidden(tree, hf_tr_rif_ring, tvb, TR_MIN_HEADER_LEN + 3 + j, 2, segment);
proto_tree_add_item_hidden(tree, hf_tr_rif_bridge, NullTVB, offset+16+j, 1, brdgnmb); proto_tree_add_item_hidden(tree, hf_tr_rif_bridge, tvb, TR_MIN_HEADER_LEN + 2 + j, 1, brdgnmb);
buff_offset += size; buff_offset += size;
} }
proto_tree_add_item(tree, hf_tr_rif, NullTVB, offset+16, rcf_len, buffer); proto_tree_add_item(tree, hf_tr_rif, tvb, TR_MIN_HEADER_LEN + 2, rcf_len, buffer);
if (unprocessed_rif > 0) { if (unprocessed_rif > 0) {
proto_tree_add_text(tree, NullTVB, offset+14+RIF_BYTES_TO_PROCESS, unprocessed_rif, proto_tree_add_text(tree, tvb, TR_MIN_HEADER_LEN + RIF_BYTES_TO_PROCESS, unprocessed_rif,
"Extra RIF bytes beyond spec: %d", unprocessed_rif); "Extra RIF bytes beyond spec: %d", unprocessed_rif);
} }
} }

View File

@ -1,6 +1,6 @@
/* packet-tr.h /* packet-tr.h
* *
* $Id: packet-tr.h,v 1.1 2000/02/15 21:03:21 gram Exp $ * $Id: packet-tr.h,v 1.2 2000/05/15 06:22:07 gram Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org> * By Gerald Combs <gerald@zing.org>
@ -23,4 +23,4 @@
*/ */
void capture_tr(const u_char *, int, packet_counts *); void capture_tr(const u_char *, int, packet_counts *);
void dissect_tr(const u_char *, int, frame_data *, proto_tree *); void dissect_tr(tvbuff_t *, packet_info *, proto_tree *);

View File

@ -1,7 +1,7 @@
/* packet.c /* packet.c
* Routines for packet disassembly * Routines for packet disassembly
* *
* $Id: packet.c,v 1.81 2000/05/11 22:04:18 gram Exp $ * $Id: packet.c,v 1.82 2000/05/15 06:22:07 gram Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org> * By Gerald Combs <gerald@zing.org>
@ -1182,7 +1182,7 @@ dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
dissect_fddi(tvb, &pi, tree, TRUE); dissect_fddi(tvb, &pi, tree, TRUE);
break; break;
case WTAP_ENCAP_TR : case WTAP_ENCAP_TR :
dissect_tr(pd, 0, fd, tree); dissect_tr(tvb, &pi, tree);
break; break;
case WTAP_ENCAP_NULL : case WTAP_ENCAP_NULL :
dissect_null(pd, fd, tree); dissect_null(pd, fd, tree);