aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/to_str.c7
-rw-r--r--packet-fc.c441
2 files changed, 318 insertions, 130 deletions
diff --git a/epan/to_str.c b/epan/to_str.c
index 69c01e6ca7..cd8e185640 100644
--- a/epan/to_str.c
+++ b/epan/to_str.c
@@ -1,7 +1,7 @@
/* to_str.c
* Routines for utilities to convert various other types to strings.
*
- * $Id: to_str.c,v 1.26 2003/06/23 09:15:08 sahlberg Exp $
+ * $Id: to_str.c,v 1.27 2003/06/24 15:37:31 sahlberg Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -587,8 +587,9 @@ fc_to_str(const guint8 *ad)
gchar *
fc32_to_str(const guint32 ad32)
{
- const guint8 *ad=(guint8 *)&ad32;
- return bytestring_to_str (ad, 3, '.');
+ static gchar str[9];
+ sprintf(str,"%02x.%02x.%02x", ad32&0xff, (ad32>>8)&0xff, (ad32>>16)&0xff);
+ return str;
}
/* FC Network Header Network Address Authority Identifiers */
diff --git a/packet-fc.c b/packet-fc.c
index 69e1be4ac9..588b29d538 100644
--- a/packet-fc.c
+++ b/packet-fc.c
@@ -2,7 +2,7 @@
* Routines for Fibre Channel Decoding (FC Header, Link Ctl & Basic Link Svc)
* Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
*
- * $Id: packet-fc.c,v 1.8 2003/06/23 13:09:12 sahlberg Exp $
+ * $Id: packet-fc.c,v 1.9 2003/06/24 15:37:29 sahlberg Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -25,6 +25,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
+
#endif
#include <stdio.h>
@@ -73,6 +74,9 @@
/* Initialize the protocol and registered fields */
static int proto_fc = -1;
+static int hf_fc_time = -1;
+static int hf_fc_exchange_first_frame = -1;
+static int hf_fc_exchange_last_frame = -1;
static int hf_fc_rctl = -1;
static int hf_fc_did = -1;
static int hf_fc_csctl = -1;
@@ -100,8 +104,6 @@ static int hf_fc_oxid = -1;
static int hf_fc_rxid = -1;
static int hf_fc_param = -1;
static int hf_fc_ftype = -1; /* Derived field, non-existent in FC hdr */
-static int hf_fc_exchg_orig = -1;
-static int hf_fc_exchg_resp = -1;
static int hf_fc_reassembled = -1;
/* Network_Header fields */
@@ -128,11 +130,135 @@ static gint ett_fcbls = -1;
static dissector_table_t fcftype_dissector_table;
static dissector_handle_t data_handle;
+
+#define FC_FCTL_EXCHANGE_RESPONDER 0x800000
+#define FC_FCTL_SEQ_RECIPIENT 0x400000
+#define FC_FCTL_EXCHANGE_FIRST 0x200000
+#define FC_FCTL_EXCHANGE_LAST 0x100000
+#define FC_FCTL_SEQ_LAST 0x080000
+#define FC_FCTL_PRIORITY 0x020000
+#define FC_FCTL_TRANSFER_SEQ_INITIATIVE 0x010000
+#define FC_FCTL_LAST_DATA_FRAME_MASK 0x00c000
+#define FC_FCTL_ACK_0_1_MASK 0x003000
+#define FC_FCTL_REXMITTED_SEQ 0x000200
+#define FC_FCTL_ABTS_MASK 0x000030
+#define FC_FCTL_REL_OFFSET 0x000008
+
+
/* Reassembly stuff */
static gboolean fc_reassemble = TRUE;
static guint32 fc_max_frame_size = 1024;
static GHashTable *fc_fragment_table = NULL;
+
+/* structure and functions to keep track of first/last exchange
+ frames and time deltas
+*/
+typedef struct _fc_exchange_data {
+ guint32 s_id;
+ guint32 d_id;
+ guint16 oxid;
+ guint32 first_exchange_frame;
+ guint32 last_exchange_frame;
+ nstime_t fc_time;
+} fc_exchange_data;
+static GHashTable *fc_exchange_unmatched = NULL;
+static GHashTable *fc_exchange_matched = NULL;
+static GMemChunk *fc_exchange_vals = NULL;
+static guint32 fc_exchange_init_count = 200;
+
+static guint
+fc_exchange_hash_unmatched(gconstpointer v)
+{
+ const fc_exchange_data *fced=(const fc_exchange_data *)v;
+
+ return fced->oxid;
+}
+static gint
+fc_exchange_equal_unmatched(gconstpointer v1, gconstpointer v2)
+{
+ const fc_exchange_data *fced1=(const fc_exchange_data *)v1;
+ const fc_exchange_data *fced2=(const fc_exchange_data *)v2;
+
+ /* oxid must match */
+ if(fced1->oxid!=fced2->oxid){
+ return 0;
+ }
+ /* compare s_id, d_id and treat the fc address
+ s_id==00.00.00 as a wildcard matching anything */
+ if( (fced1->s_id!=0) && (fced1->s_id!=fced2->s_id) ){
+ return 0;
+ }
+ if(fced1->d_id!=fced2->d_id){
+ return 0;
+ }
+
+ return 1;
+}
+
+static guint
+fc_exchange_hash_matched(gconstpointer v)
+{
+ const fc_exchange_data *fced=(const fc_exchange_data *)v;
+
+ return fced->oxid;
+}
+static gint
+fc_exchange_equal_matched(gconstpointer v1, gconstpointer v2)
+{
+ const fc_exchange_data *fced1=(const fc_exchange_data *)v1;
+ const fc_exchange_data *fced2=(const fc_exchange_data *)v2;
+ guint32 fef1, fef2, lef1, lef2;
+
+ /* oxid must match */
+ if(fced1->oxid!=fced2->oxid){
+ return 0;
+ }
+ fef1=fced1->first_exchange_frame;
+ fef2=fced2->first_exchange_frame;
+ lef1=fced1->last_exchange_frame;
+ lef2=fced2->last_exchange_frame;
+ if(!fef1)fef1=fef2;
+ if(!fef2)fef2=fef1;
+ if(!lef1)lef1=lef2;
+ if(!lef2)lef2=lef1;
+
+ if(fef1!=fef2){
+ return 0;
+ }
+ if(lef1!=lef2){
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+fc_exchange_init_protocol(void)
+{
+ if(fc_exchange_vals){
+ g_mem_chunk_destroy(fc_exchange_vals);
+ fc_exchange_vals=NULL;
+ }
+ if(fc_exchange_unmatched){
+ g_hash_table_destroy(fc_exchange_unmatched);
+ fc_exchange_unmatched=NULL;
+ }
+ if(fc_exchange_matched){
+ g_hash_table_destroy(fc_exchange_matched);
+ fc_exchange_matched=NULL;
+ }
+
+ fc_exchange_unmatched=g_hash_table_new(fc_exchange_hash_unmatched, fc_exchange_equal_unmatched);
+ fc_exchange_matched=g_hash_table_new(fc_exchange_hash_matched, fc_exchange_equal_matched);
+ fc_exchange_vals=g_mem_chunk_new("fc_exchange_vals", sizeof(fc_exchange_data), fc_exchange_init_count*sizeof(fc_exchange_data), G_ALLOC_AND_FREE);
+}
+
+
+
+
+
+
const value_string fc_fc4_val[] = {
{FC_TYPE_ELS , "Ext Link Svc"},
{FC_TYPE_LLCSNAP , "LLC_SNAP"},
@@ -186,6 +312,18 @@ static const value_string fc_iu_val[] = {
{0, NULL},
};
+typedef struct _fc_hdr {
+ guint32 s_id;
+ guint32 d_id;
+ guint32 fctl;
+ guint8 type;
+ guint16 seqcnt;
+ guint16 oxid;
+ guint16 rxid;
+ guint8 r_ctl;
+ guint8 cs_ctl;
+} fc_hdr;
+
static void fc_defragment_init(void)
{
fragment_table_init(&fc_fragment_table);
@@ -448,19 +586,6 @@ fc_get_ftype (guint8 r_ctl, guint8 type)
}
}
-#define FC_FCTL_EXCHANGE_RESPONDER 0x800000
-#define FC_FCTL_SEQ_RECIPIENT 0x400000
-#define FC_FCTL_EXCHANGE_FIRST 0x200000
-#define FC_FCTL_EXCHANGE_LAST 0x100000
-#define FC_FCTL_SEQ_LAST 0x080000
-#define FC_FCTL_PRIORITY 0x020000
-#define FC_FCTL_TRANSFER_SEQ_INITIATIVE 0x010000
-#define FC_FCTL_LAST_DATA_FRAME_MASK 0x00c000
-#define FC_FCTL_ACK_0_1_MASK 0x003000
-#define FC_FCTL_REXMITTED_SEQ 0x000200
-#define FC_FCTL_ABTS_MASK 0x000030
-#define FC_FCTL_REL_OFFSET 0x000008
-
static const value_string abts_ack_vals[] = {
{0x000000, "ABTS - Cont"},
{0x000010, "ABTS - Abort"},
@@ -531,15 +656,12 @@ static const true_false_string tfs_fc_fctl_rel_offset = {
/* code to dissect the F_CTL bitmask */
static void
-dissect_fc_fctl(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gboolean is_ack)
+dissect_fc_fctl(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gboolean is_ack, guint32 fctl)
{
- guint32 fctl;
proto_item *item;
proto_tree *tree;
gchar str[256];
- fctl=tvb_get_ntoh24(tvb,offset);
-
item=proto_tree_add_uint(parent_tree, hf_fc_fctl, tvb, offset, 3, fctl);
tree=proto_item_add_subtree(item, ett_fctl);
@@ -583,7 +705,7 @@ static void
dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
- proto_item *ti;
+ proto_item *ti=NULL;
proto_tree *fc_tree = NULL;
tvbuff_t *next_tvb;
int offset = 0, next_offset;
@@ -592,51 +714,56 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
fragment_data *fcfrag_head;
guint32 frag_id;
guint32 frag_size;
- guint8 r_ctl, type, df_ctl;
+ guint8 df_ctl;
guint32 param;
- guint16 seqcnt;
guint8 ftype;
gboolean is_ack;
- guint32 s_id;
- guint32 d_id;
+ fc_hdr fchdr;
+ fc_exchange_data *fc_ex=NULL;
/* Make entries in Protocol column and Info column on summary display */
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC");
- r_ctl = tvb_get_guint8 (tvb, offset);
+ fchdr.r_ctl = tvb_get_guint8 (tvb, offset);
/* If the R_CTL is the EISL field, skip the first 8 bytes to retrieve the
* real FC header. EISL is Cisco-proprietary and is not decoded.
*/
- if (r_ctl == FC_RCTL_EISL) {
+ if (fchdr.r_ctl == FC_RCTL_EISL) {
offset += 8;
- r_ctl = tvb_get_guint8 (tvb, offset);
+ fchdr.r_ctl = tvb_get_guint8 (tvb, offset);
}
- type = tvb_get_guint8 (tvb, offset+8);
- seqcnt = tvb_get_ntohs (tvb, offset+14);
+ fchdr.d_id=tvb_get_letoh24(tvb, offset+1);
+ fchdr.s_id=tvb_get_letoh24(tvb, offset+5);
+ fchdr.cs_ctl = tvb_get_guint8 (tvb, offset+4);
+ fchdr.type = tvb_get_guint8 (tvb, offset+8);
+ fchdr.fctl=tvb_get_ntoh24(tvb,offset+9);
+ fchdr.seqcnt = tvb_get_ntohs (tvb, offset+14);
+ fchdr.oxid=tvb_get_ntohs(tvb,offset+16);
+ fchdr.rxid=tvb_get_ntohs(tvb,offset+18);
param = tvb_get_ntohl (tvb, offset+20);
- SET_ADDRESS (&pinfo->dst, AT_FC, 3, tvb_get_ptr (tvb, offset+1, 3));
- SET_ADDRESS (&pinfo->src, AT_FC, 3, tvb_get_ptr (tvb, offset+5, 3));
- pinfo->oxid = tvb_get_ntohs (tvb, offset+16);
- pinfo->rxid = tvb_get_ntohs (tvb, offset+18);
+ SET_ADDRESS (&pinfo->dst, AT_FC, 3, tvb_get_ptr(tvb,offset+1,3));
+ SET_ADDRESS (&pinfo->src, AT_FC, 3, tvb_get_ptr(tvb,offset+5,3));
+ pinfo->oxid = fchdr.oxid;
+ pinfo->rxid = fchdr.rxid;
pinfo->ptype = PT_EXCHG;
- pinfo->r_ctl = r_ctl;
+ pinfo->r_ctl = fchdr.r_ctl;
- is_ack = ((r_ctl == 0xC0) || (r_ctl == 0xC1));
+ is_ack = ((fchdr.r_ctl == 0xC0) || (fchdr.r_ctl == 0xC1));
- ftype = fc_get_ftype (r_ctl, type);
+ ftype = fc_get_ftype (fchdr.r_ctl, fchdr.type);
if (check_col (pinfo->cinfo, COL_INFO)) {
col_add_str (pinfo->cinfo, COL_INFO, match_strval (ftype, fc_ftype_vals));
if (ftype == FC_FTYPE_LINKCTL)
col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
- match_strval ((r_ctl & 0x0F),
+ match_strval ((fchdr.r_ctl & 0x0F),
fc_lctl_proto_val));
}
@@ -646,103 +773,159 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
ti = proto_tree_add_protocol_format (tree, proto_fc, tvb, offset,
FC_HEADER_SIZE, "Fibre Channel");
fc_tree = proto_item_add_subtree (ti, ett_fc);
+ }
- if (ftype == FC_FTYPE_LINKCTL) {
- /* the lower 4 bits of R_CTL indicate the type of link ctl frame */
- proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
- FC_RCTL_SIZE, r_ctl,
- "R_CTL: 0x%x(%s)",
- r_ctl,
- val_to_str ((r_ctl & 0x0F),
- fc_lctl_proto_val, "0x%x"));
- }
- else if (ftype == FC_FTYPE_BLS) {
- /* the lower 4 bits of R_CTL indicate the type of BLS frame */
- proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
- FC_RCTL_SIZE, r_ctl,
- "R_CTL: 0x%x(%s)",
- r_ctl,
- val_to_str ((r_ctl & 0x0F),
- fc_bls_proto_val, "0x%x"));
- }
- else {
- proto_tree_add_item (fc_tree, hf_fc_rctl, tvb, offset, 1, FALSE);
+ /* match first exchange with last exchange */
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST){
+ if(!pinfo->fd->flags.visited){
+ fc_exchange_data fced, *old_fced;
+ /* first check if we already have seen this exchange and it
+ is still open/unmatched.
+ */
+ fced.oxid=fchdr.oxid;
+ fced.s_id=fchdr.s_id;
+ fced.d_id=fchdr.d_id;
+ old_fced=g_hash_table_lookup(fc_exchange_unmatched, &fced);
+ if(old_fced){
+ g_hash_table_remove(fc_exchange_unmatched, old_fced);
+ }
+ old_fced=g_mem_chunk_alloc(fc_exchange_vals);
+ old_fced->oxid=fchdr.oxid;
+ old_fced->s_id=fchdr.s_id;
+ old_fced->d_id=fchdr.d_id;
+old_fced->first_exchange_frame=pinfo->fd->num;
+ old_fced->fc_time.nsecs = pinfo->fd->abs_usecs*1000;
+ old_fced->fc_time.secs = pinfo->fd->abs_secs;
+ g_hash_table_insert(fc_exchange_unmatched, old_fced, old_fced);
+ } else {
+ fc_exchange_data fced, *old_fced;
+ fced.oxid=fchdr.oxid;
+ fced.first_exchange_frame=pinfo->fd->num;
+ fced.last_exchange_frame=0;
+ old_fced=g_hash_table_lookup(fc_exchange_matched, &fced);
+ if(old_fced){
+ fc_ex=old_fced;
+ }
}
-
- proto_tree_add_uint_hidden (fc_tree, hf_fc_ftype, tvb, offset, 1,
- ftype);
-
- d_id=tvb_get_letoh24(tvb, offset+1);
- proto_tree_add_string (fc_tree, hf_fc_did, tvb, offset+1, 3,
- fc32_to_str (d_id));
- proto_tree_add_string_hidden (fc_tree, hf_fc_id, tvb, offset+1, 3,
- fc32_to_str (d_id));
-
- proto_tree_add_item (fc_tree, hf_fc_csctl, tvb, offset+4, 1, FALSE);
-
- s_id=tvb_get_letoh24(tvb, offset+5);
- proto_tree_add_string (fc_tree, hf_fc_sid, tvb, offset+5, 3,
- fc32_to_str (s_id));
- proto_tree_add_string_hidden (fc_tree, hf_fc_id, tvb, offset+5, 3,
- fc32_to_str (s_id));
-
- if (ftype == FC_FTYPE_LINKCTL) {
- if (((r_ctl & 0x0F) == FC_LCTL_FBSYB) ||
- ((r_ctl & 0x0F) == FC_LCTL_FBSYL)) {
- /* for F_BSY frames, the upper 4 bits of the type field specify the
- * reason for the BSY.
- */
- proto_tree_add_uint_format (fc_tree, hf_fc_type, tvb,
- offset+8, FC_TYPE_SIZE,
- type, "Type: 0x%x(%s)", type,
- fclctl_get_typestr (r_ctl & 0x0F,
- type));
+ }
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_LAST){
+ if(!pinfo->fd->flags.visited){
+ fc_exchange_data fced, *old_fced;
+
+ fced.oxid=fchdr.oxid;
+ fced.s_id=fchdr.d_id;
+ fced.d_id=fchdr.s_id;
+ old_fced=g_hash_table_lookup(fc_exchange_unmatched, &fced);
+ if(old_fced){
+ g_hash_table_remove(fc_exchange_unmatched, old_fced);
+ old_fced->last_exchange_frame=pinfo->fd->num;
+ g_hash_table_insert(fc_exchange_matched, old_fced, old_fced);
}
- else {
- proto_tree_add_item (fc_tree, hf_fc_type, tvb, offset+8, 1, FALSE);
+ } else {
+ fc_exchange_data fced, *old_fced;
+ fced.oxid=fchdr.oxid;
+ fced.first_exchange_frame=0;
+ fced.last_exchange_frame=pinfo->fd->num;
+ old_fced=g_hash_table_lookup(fc_exchange_matched, &fced);
+ if(old_fced){
+ fc_ex=old_fced;
}
}
- else {
- proto_tree_add_item (fc_tree, hf_fc_type, tvb, offset+8, 1, FALSE);
+ }
+ if(fc_ex){
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST){
+ proto_tree_add_uint(fc_tree, hf_fc_exchange_last_frame, tvb, 0, 0, fc_ex->last_exchange_frame);
+ }
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_LAST){
+ nstime_t delta_time;
+ proto_tree_add_uint(fc_tree, hf_fc_exchange_first_frame, tvb, 0, 0, fc_ex->first_exchange_frame);
+ delta_time.secs = pinfo->fd->abs_secs - fc_ex->fc_time.secs;
+ delta_time.nsecs = pinfo->fd->abs_usecs*1000 - fc_ex->fc_time.nsecs;
+ if (delta_time.nsecs<0){
+ delta_time.nsecs+=1000000000;
+ delta_time.secs--;
+ }
+ proto_tree_add_time(ti, hf_fc_time, tvb, 0, 0, &delta_time);
}
+ }
- dissect_fc_fctl(pinfo, fc_tree, tvb, offset+9, is_ack);
+ if (ftype == FC_FTYPE_LINKCTL) {
+ /* the lower 4 bits of R_CTL indicate the type of link ctl frame */
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0x0F),
+ fc_lctl_proto_val, "0x%x"));
+ } else if (ftype == FC_FTYPE_BLS) {
+ /* the lower 4 bits of R_CTL indicate the type of BLS frame */
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0x0F),
+ fc_bls_proto_val, "0x%x"));
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_rctl, tvb, offset, 1, FALSE);
+ }
+
+ proto_tree_add_uint_hidden (fc_tree, hf_fc_ftype, tvb, offset, 1,
+ ftype);
+ proto_tree_add_string (fc_tree, hf_fc_did, tvb, offset+1, 3,
+ fc32_to_str (fchdr.d_id));
+ proto_tree_add_string_hidden (fc_tree, hf_fc_id, tvb, offset+1, 3,
+ fc32_to_str (fchdr.d_id));
- /* Bit 23 if set => this frame is from the exchange originator */
- if (tvb_get_guint8 (tvb, offset+9) & 0x80) {
- proto_tree_add_boolean (fc_tree, hf_fc_exchg_orig, tvb,
- offset+9, 1, 0);
- proto_tree_add_boolean (fc_tree, hf_fc_exchg_resp, tvb,
- offset+9, 1, 1);
- }
- else {
- proto_tree_add_boolean (fc_tree, hf_fc_exchg_orig, tvb,
- offset+9, 1, 1);
- proto_tree_add_boolean (fc_tree, hf_fc_exchg_resp, tvb,
- offset+9, 1, 0);
- }
+ proto_tree_add_uint (fc_tree, hf_fc_csctl, tvb, offset+4, 1, fchdr.cs_ctl);
+
+ proto_tree_add_string (fc_tree, hf_fc_sid, tvb, offset+5, 3,
+ fc32_to_str (fchdr.s_id));
+ proto_tree_add_string_hidden (fc_tree, hf_fc_id, tvb, offset+5, 3,
+ fc32_to_str (fchdr.s_id));
- proto_tree_add_item (fc_tree, hf_fc_seqid, tvb, offset+12, 1, FALSE);
+ if (ftype == FC_FTYPE_LINKCTL) {
+ if (((fchdr.r_ctl & 0x0F) == FC_LCTL_FBSYB) ||
+ ((fchdr.r_ctl & 0x0F) == FC_LCTL_FBSYL)) {
+ /* for F_BSY frames, the upper 4 bits of the type field specify the
+ * reason for the BSY.
+ */
+ proto_tree_add_uint_format (fc_tree, hf_fc_type, tvb,
+ offset+8, FC_TYPE_SIZE,
+ fchdr.type,"Type: 0x%x(%s)", fchdr.type,
+ fclctl_get_typestr (fchdr.r_ctl & 0x0F,
+ fchdr.type));
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_type, tvb, offset+8, 1, FALSE);
+ }
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_type, tvb, offset+8, 1, FALSE);
}
+
+
+ dissect_fc_fctl(pinfo, fc_tree, tvb, offset+9, is_ack, fchdr.fctl);
+
+
+ proto_tree_add_item (fc_tree, hf_fc_seqid, tvb, offset+12, 1, FALSE);
+
df_ctl = tvb_get_guint8(tvb, offset+13);
if (tree) {
proto_tree_add_uint (fc_tree, hf_fc_dfctl, tvb, offset+13, 1, df_ctl);
- proto_tree_add_item (fc_tree, hf_fc_seqcnt, tvb, offset+14, 2, FALSE);
- proto_tree_add_item (fc_tree, hf_fc_oxid, tvb, offset+16, 2, FALSE);
- proto_tree_add_item (fc_tree, hf_fc_rxid, tvb, offset+18, 2, FALSE);
+ proto_tree_add_uint (fc_tree, hf_fc_seqcnt, tvb, offset+14, 2, fchdr.seqcnt);
+ proto_tree_add_uint (fc_tree, hf_fc_oxid, tvb, offset+16, 2, fchdr.oxid);
+ proto_tree_add_uint (fc_tree, hf_fc_rxid, tvb, offset+18, 2, fchdr.rxid);
if (ftype == FC_FTYPE_LINKCTL) {
- if (((r_ctl & 0x0F) == FC_LCTL_FRJT) ||
- ((r_ctl & 0x0F) == FC_LCTL_PRJT) ||
- ((r_ctl & 0x0F) == FC_LCTL_PBSY)) {
+ if (((fchdr.r_ctl & 0x0F) == FC_LCTL_FRJT) ||
+ ((fchdr.r_ctl & 0x0F) == FC_LCTL_PRJT) ||
+ ((fchdr.r_ctl & 0x0F) == FC_LCTL_PBSY)) {
/* In all these cases of Link Ctl frame, the parameter field
* encodes the detailed error message
*/
proto_tree_add_uint_format (fc_tree, hf_fc_param, tvb,
offset+20, 4, param,
"Parameter: 0x%x(%s)", param,
- fclctl_get_paramstr ((r_ctl & 0x0F),
+ fclctl_get_paramstr ((fchdr.r_ctl & 0x0F),
param));
}
else {
@@ -750,7 +933,7 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
else if (ftype == FC_FTYPE_BLS) {
- if ((r_ctl & 0x0F) == FC_BLS_ABTS) {
+ if ((fchdr.r_ctl & 0x0F) == FC_BLS_ABTS) {
proto_tree_add_uint_format (fc_tree, hf_fc_param, tvb,
offset+20, 4, param,
"Parameter: 0x%x(%s)", param,
@@ -791,9 +974,9 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* problem
*/
is_lastframe_inseq = TRUE;
- }
- else {
- is_lastframe_inseq = tvb_get_guint8 (tvb, offset+9) & 0x08;
+ } else {
+ is_lastframe_inseq = fchdr.fctl & FC_FCTL_SEQ_LAST;
+ /* XXX is this right? offset 20, shouldnt it be offset 9? */
is_exchg_resp = ((tvb_get_guint8 (tvb, offset+20) & 0x80) == 0x80);
}
@@ -819,7 +1002,7 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* present, if we're configured to reassemble.
*/
if ((ftype != FC_FTYPE_LINKCTL) && (ftype != FC_FTYPE_BLS) &&
- (!is_lastframe_inseq || seqcnt) && fc_reassemble &&
+ (!is_lastframe_inseq || fchdr.seqcnt) && fc_reassemble &&
tvb_bytes_exist(tvb, FC_HEADER_SIZE, frag_size)) {
/* Add this to the list of fragments */
frag_id = (pinfo->oxid << 16) | is_exchg_resp;
@@ -827,7 +1010,7 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* We assume that all frames are of the same max size */
fcfrag_head = fragment_add (tvb, FC_HEADER_SIZE, pinfo, frag_id,
fc_fragment_table,
- seqcnt * fc_max_frame_size,
+ fchdr.seqcnt * fc_max_frame_size,
frag_size,
!is_lastframe_inseq);
@@ -870,10 +1053,10 @@ dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
else if (ftype == FC_FTYPE_BLS) {
- if ((r_ctl & 0x0F) == FC_BLS_BAACC) {
+ if ((fchdr.r_ctl & 0x0F) == FC_BLS_BAACC) {
dissect_fc_ba_acc (next_tvb, pinfo, tree);
}
- else if ((r_ctl & 0x0F) == FC_BLS_BARJT) {
+ else if ((fchdr.r_ctl & 0x0F) == FC_BLS_BARJT) {
dissect_fc_ba_rjt (next_tvb, pinfo, tree);
}
}
@@ -933,12 +1116,6 @@ proto_register_fc(void)
{"Parameter", "fc.parameter", FT_UINT32, BASE_HEX, NULL, 0x0, "Parameter",
HFILL}},
- { &hf_fc_exchg_orig,
- {"Exchange Originator", "fc.xchg_orig", FT_BOOLEAN, BASE_HEX, NULL,
- 0x0, "", HFILL}},
- { &hf_fc_exchg_resp,
- {"Exchange Responder", "fc.xchg_resp", FT_BOOLEAN, BASE_HEX, NULL,
- 0x0, "", HFILL}},
{ &hf_fc_reassembled,
{"Reassembled Frame", "fc.reassembled", FT_BOOLEAN, BASE_HEX, NULL,
0x0, "", HFILL}},
@@ -1014,6 +1191,15 @@ proto_register_fc(void)
{ &hf_fc_fctl_abts_not_ack,
{"AnA", "fc.fctl.abts_not_ack", FT_UINT24, BASE_HEX, VALS(abts_not_ack_vals),
FC_FCTL_ABTS_MASK, "ABTS not ACK vals", HFILL}},
+ { &hf_fc_exchange_first_frame,
+ { "Exchange First In", "fc.exchange_first_frame", FT_FRAMENUM, BASE_NONE, NULL,
+ 0, "The first frame of this exchange is in this frame", HFILL }},
+ { &hf_fc_exchange_last_frame,
+ { "Exchange Last In", "fc.exchange_last_frame", FT_FRAMENUM, BASE_NONE, NULL,
+ 0, "The last frame of this exchange is in this frame", HFILL }},
+ { &hf_fc_time,
+ { "Time from Exchange First", "fc.time", FT_RELATIVE_TIME, BASE_NONE, NULL,
+ 0, "Time since the first frame of the Exchange", HFILL }},
};
/* Setup protocol subtree array */
@@ -1052,6 +1238,7 @@ proto_register_fc(void)
&fc_max_frame_size);
register_init_routine(fc_defragment_init);
+ register_init_routine (fc_exchange_init_protocol);
}