diff options
-rw-r--r-- | epan/dissectors/packet-fcoib.c | 198 | ||||
-rw-r--r-- | epan/dissectors/packet-infiniband.c | 55 | ||||
-rw-r--r-- | epan/dissectors/packet-infiniband_sdp.c | 208 | ||||
-rw-r--r-- | epan/dissectors/packet-iser.c | 142 | ||||
-rw-r--r-- | epan/dissectors/packet-rpcrdma.c | 27 | ||||
-rw-r--r-- | epan/dissectors/packet-smb-direct.c | 32 | ||||
-rw-r--r-- | epan/dissectors/packet-smcr.c | 13 |
7 files changed, 257 insertions, 418 deletions
diff --git a/epan/dissectors/packet-fcoib.c b/epan/dissectors/packet-fcoib.c index 81a6bca433..849b43001a 100644 --- a/epan/dissectors/packet-fcoib.c +++ b/epan/dissectors/packet-fcoib.c @@ -34,7 +34,6 @@ #include <epan/crc32-tvb.h> #include <epan/expert.h> #include <epan/addr_resolv.h> -#include "packet-infiniband.h" #include "packet-fc.h" void proto_register_fcoib(void); @@ -104,44 +103,7 @@ static expert_field ei_fcoib_crc = EI_INIT; static dissector_handle_t fc_handle; -/* global preferences */ -static gboolean gPREF_HEUR_EN = TRUE; -static gboolean gPREF_MAN_EN = FALSE; -static gint gPREF_TYPE[2] = {0}; -static const char *gPREF_ID[2] = {NULL}; -static guint gPREF_QP[2] = {0}; - -/* source/destination addresses from preferences menu (parsed from gPREF_TYPE[?], gPREF_ID[?]) */ -static address manual_addr[2]; -static void *manual_addr_data[2]; - -static const enum_val_t pref_address_types[] = { - {"lid", "LID", 0}, - {"gid", "GID", 1}, - {NULL, NULL, -1} -}; - -/* checks if a packet matches the source/destination manually-configured in preferences */ -static gboolean -manual_addr_match(packet_info *pinfo) { - if (gPREF_MAN_EN) { - /* If the manual settings are enabled see if this fits - in which case we can skip - the following checks entirely and go straight to dissecting */ - if ( (addresses_equal(&pinfo->src, &manual_addr[0]) && - addresses_equal(&pinfo->dst, &manual_addr[1]) && - (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[0]) && - (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[1])) || - (addresses_equal(&pinfo->src, &manual_addr[1]) && - addresses_equal(&pinfo->dst, &manual_addr[0]) && - (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[1]) && - (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[0])) ) - return TRUE; - } - - return FALSE; -} - -static gboolean +static int dissect_fcoib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { gint crc_offset; @@ -164,7 +126,6 @@ dissect_fcoib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U gboolean crc_exists; guint32 crc_computed = 0; guint32 crc = 0; - gboolean packet_match_manual; fc_data_t fc_data; frame_len = tvb_reported_length_remaining(tvb, 0) - @@ -174,33 +135,7 @@ dissect_fcoib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U sof_offset = FCOIB_HEADER_LEN - 1; if (frame_len <= 0) - return FALSE; /* this packet isn't even long enough to contain the header+trailer w/o FC payload! */ - - packet_match_manual = manual_addr_match(pinfo); - - if (!packet_match_manual && !gPREF_HEUR_EN) - return FALSE; /* user doesn't want us trying to automatically identify FCoIB packets */ - - /* we start off with some basic heuristics checks to make sure this could be a FCoIB packet */ - - if (tvb_bytes_exist(tvb, 0, 1)) - sig = tvb_get_guint8(tvb, 0) >> 6; - if (tvb_bytes_exist(tvb, eof_offset, 1)) - eof = tvb_get_guint8(tvb, eof_offset); - if (tvb_bytes_exist(tvb, sof_offset, 1)) - sof = tvb_get_guint8(tvb, sof_offset); - - if (!packet_match_manual) { - if (sig != 1) - return FALSE; /* the sig field in the FCoIB Encap. header MUST be 2'b01*/ - if (!tvb_bytes_exist(tvb, eof_offset + 1, 3) || tvb_get_ntoh24(tvb, eof_offset + 1) != 0) - return FALSE; /* 3 bytes of RESERVED field immediately after eEOF MUST be 0 */ - if (!try_val_to_str(sof, fcoib_sof_vals)) - return FALSE; /* invalid value for SOF */ - if (!try_val_to_str(eof, fcoib_eof_vals)) - return FALSE; /* invalid value for EOF */ - } - + return 0; /* this packet isn't even long enough to contain the header+trailer w/o FC payload! */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCoIB"); bytes_remaining = tvb_captured_length_remaining(tvb, FCOIB_HEADER_LEN); @@ -299,6 +234,48 @@ dissect_fcoib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U call_data_dissector(next_tvb, pinfo, tree); } + return tvb_captured_length(tvb); +} + +static gboolean +dissect_fcoib_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + gint crc_offset; + gint eof_offset; + gint sof_offset; + gint frame_len; + guint8 sof = 0; + guint8 eof = 0; + guint8 sig = 0; + + frame_len = tvb_reported_length_remaining(tvb, 0) - + FCOIB_HEADER_LEN - FCOIB_TRAILER_LEN; + crc_offset = FCOIB_HEADER_LEN + frame_len; + eof_offset = crc_offset + 4; + sof_offset = FCOIB_HEADER_LEN - 1; + + if (frame_len <= 0) + return FALSE; /* this packet isn't even long enough to contain the header+trailer w/o FC payload! */ + + /* we start off with some basic heuristics checks to make sure this could be a FCoIB packet */ + + if (tvb_bytes_exist(tvb, 0, 1)) + sig = tvb_get_guint8(tvb, 0) >> 6; + if (tvb_bytes_exist(tvb, eof_offset, 1)) + eof = tvb_get_guint8(tvb, eof_offset); + if (tvb_bytes_exist(tvb, sof_offset, 1)) + sof = tvb_get_guint8(tvb, sof_offset); + + if (sig != 1) + return FALSE; /* the sig field in the FCoIB Encap. header MUST be 2'b01*/ + if (!tvb_bytes_exist(tvb, eof_offset + 1, 3) || tvb_get_ntoh24(tvb, eof_offset + 1) != 0) + return FALSE; /* 3 bytes of RESERVED field immediately after eEOF MUST be 0 */ + if (!try_val_to_str(sof, fcoib_sof_vals)) + return FALSE; /* invalid value for SOF */ + if (!try_val_to_str(eof, fcoib_eof_vals)) + return FALSE; /* invalid value for EOF */ + + dissect_fcoib(tvb, pinfo, tree, data); return TRUE; } @@ -348,80 +325,33 @@ proto_register_fcoib(void) fcoib_module = prefs_register_protocol(proto_fcoib, proto_reg_handoff_fcoib); - prefs_register_bool_preference(fcoib_module, "heur_en", "Enable heuristic identification of FCoIB packets", - "When this option is enabled Wireshark will attempt to identify FCoIB packets automatically " - "based on some common features (may generate false positives)", - &gPREF_HEUR_EN); - - prefs_register_bool_preference(fcoib_module, "manual_en", "Enable manual settings", - "Enables dissecting packets between the manually configured source/destination as FCoIB traffic", - &gPREF_MAN_EN); - - prefs_register_static_text_preference(fcoib_module, "addr_a", "Address A", - "Side A of the manually-configured connection"); - prefs_register_enum_preference(fcoib_module, "addr_a_type", "Address Type", - "Type of address specified", &gPREF_TYPE[0], pref_address_types, FALSE); - prefs_register_string_preference(fcoib_module, "addr_a_id", "ID", - "LID/GID of address A", &gPREF_ID[0]); - prefs_register_uint_preference(fcoib_module, "addr_a_qp", "QP Number", - "QP Number for address A", 10, &gPREF_QP[0]); - - prefs_register_static_text_preference(fcoib_module, "addr_b", "Address B", - "Side B of the manually-configured connection"); - prefs_register_enum_preference(fcoib_module, "addr_b_type", "Address Type", - "Type of address specified", &gPREF_TYPE[1], pref_address_types, FALSE); - prefs_register_string_preference(fcoib_module, "addr_b_id", "ID", - "LID/GID of address B", &gPREF_ID[1]); - prefs_register_uint_preference(fcoib_module, "addr_b_qp", "QP Number", - "QP Number for address B", 10, &gPREF_QP[1]); + prefs_register_static_text_preference(fcoib_module, "use_decode_as", + "Heuristic matching preferences removed. Use Infiniband protocol preferences or Decode As.", + "Simple heuristics can still be enable (may generate false positives) through Infiniband protocol preferences." + "To force FCoIB dissection use Decode As"); + + prefs_register_obsolete_preference(fcoib_module, "heur_en"); + prefs_register_obsolete_preference(fcoib_module, "manual_en"); + + prefs_register_obsolete_preference(fcoib_module, "addr_a"); + prefs_register_obsolete_preference(fcoib_module, "addr_a_type"); + prefs_register_obsolete_preference(fcoib_module, "addr_a_id"); + prefs_register_obsolete_preference(fcoib_module, "addr_a_qp"); + + prefs_register_obsolete_preference(fcoib_module, "addr_b"); + prefs_register_obsolete_preference(fcoib_module, "addr_b_type"); + prefs_register_obsolete_preference(fcoib_module, "addr_b_id"); + prefs_register_obsolete_preference(fcoib_module, "addr_b_qp"); } void proto_reg_handoff_fcoib(void) { - static gboolean initialized = FALSE; - - if (!initialized) { - heur_dissector_add("infiniband.payload", dissect_fcoib, "Fibre Channel over Infiniband", "fc_infiniband", proto_fcoib, HEURISTIC_ENABLE); + heur_dissector_add("infiniband.payload", dissect_fcoib_heur, "Fibre Channel over Infiniband", "fc_infiniband", proto_fcoib, HEURISTIC_ENABLE); - fc_handle = find_dissector_add_dependency("fc", proto_fcoib); - - initialized = TRUE; - } + dissector_add_for_decode_as("infiniband", create_dissector_handle( dissect_fcoib, proto_fcoib ) ); - if (gPREF_MAN_EN) { - /* the manual setting is enabled, so parse the settings into the address type */ - gboolean error_occured = FALSE; - char *not_parsed; - int i; - - for (i = 0; i < 2; i++) { - if (gPREF_ID[i][0] == '\0') { - error_occured = TRUE; - } else if (gPREF_TYPE[i] == 0) { /* LID */ - errno = 0; /* reset any previous error indicators */ - *((guint16*)manual_addr_data[i]) = (guint16)strtoul(gPREF_ID[i], ¬_parsed, 0); - if (errno || *not_parsed != '\0') { - error_occured = TRUE; - } else { - set_address(&manual_addr[i], AT_IB, sizeof(guint16), manual_addr_data[i]); - } - } else { /* GID */ - if (!str_to_ip6( gPREF_ID[i], manual_addr_data[i])) { - error_occured = TRUE; - } else { - set_address(&manual_addr[i], AT_IB, GID_SIZE, manual_addr_data[i]); - } - } - - if (error_occured) { - /* an invalid id was specified - disable manual settings until it's fixed */ - gPREF_MAN_EN = FALSE; - break; - } - } - - } + fc_handle = find_dissector_add_dependency("fc", proto_fcoib); } /* diff --git a/epan/dissectors/packet-infiniband.c b/epan/dissectors/packet-infiniband.c index f775864638..70038a8ed4 100644 --- a/epan/dissectors/packet-infiniband.c +++ b/epan/dissectors/packet-infiniband.c @@ -31,6 +31,7 @@ #include <epan/prefs.h> #include <epan/etypes.h> #include <epan/show_exception.h> +#include <epan/decode_as.h> #include <wiretap/erf.h> #include "packet-infiniband.h" @@ -116,6 +117,8 @@ static dissector_handle_t ipv6_handle; static dissector_handle_t eth_handle; static dissector_table_t ethertype_dissector_table; +static dissector_table_t subdissector_table; + /* MAD_Data * Structure to hold information from the common MAD header. * This is necessary because the MAD header contains information which significantly changes the dissection algorithm. */ @@ -1504,6 +1507,7 @@ static guint32 opCode_PAYLD[] = { /* settings to be set by the user via the preferences dialog */ static guint pref_rroce_udp_port = DEFAULT_RROCE_UDP_PORT; +static gboolean try_heuristic_first = TRUE; /* saves information about connections that have been/are in the process of being negotiated via ConnectionManagement packets */ @@ -1527,6 +1531,15 @@ static heur_dissector_list_t heur_dissectors_payload; static heur_dissector_list_t heur_dissectors_cm_private; /* ----- This sections contains various utility functions indirectly related to Infiniband dissection ---- */ +static void infiniband_payload_prompt(packet_info *pinfo _U_, gchar* result) +{ + g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Dissect Infiniband payload as"); +} + +static gpointer infiniband_payload_value(packet_info *pinfo _U_) +{ + return 0; +} static void table_destroy_notify(gpointer data) { g_free(data); @@ -2410,6 +2423,7 @@ static void parse_PAYLOAD(proto_tree *parentTree, tvbuff_t *volatile next_tvb; gint reported_length; heur_dtbl_entry_t *hdtbl_entry; + gboolean dissector_found = FALSE; if (!tvb_bytes_exist(tvb, *offset, length)) /* previously consumed bytes + offset was all the data - none or corrupt payload */ { @@ -2501,8 +2515,32 @@ static void parse_PAYLOAD(proto_tree *parentTree, reported_length -= crclen; next_tvb = tvb_new_subset_length(tvb, local_offset, reported_length); - /* Try any heuristic dissectors that requested a chance to try and dissect IB payloads */ - if (!dissector_try_heuristic(heur_dissectors_payload, next_tvb, pinfo, top_tree, &hdtbl_entry, info)) { + if (try_heuristic_first) + { + if (dissector_try_heuristic(heur_dissectors_payload, next_tvb, pinfo, top_tree, &hdtbl_entry, info)) + dissector_found = TRUE; + } + + if (dissector_found == FALSE) + { + /* Functionality for choosing subdissector is controlled through Decode As as there + isn't a unique identifier to determine subdissector */ + if (dissector_try_uint_new(subdissector_table, 0, next_tvb, pinfo, top_tree, TRUE, info)) + { + dissector_found = TRUE; + } + else + { + if (!try_heuristic_first) + { + if (dissector_try_heuristic(heur_dissectors_payload, next_tvb, pinfo, top_tree, &hdtbl_entry, info)) + dissector_found = TRUE; + } + } + } + + if (dissector_found == FALSE) + { /* No sub-dissector found. Label rest of packet as "Data" */ call_data_dissector(next_tvb, pinfo, top_tree); @@ -7913,6 +7951,12 @@ void proto_register_infiniband(void) &ett_eoib }; + /* Decode As handling */ + static build_valid_func infiniband_payload_da_build_value[1] = {infiniband_payload_value}; + static decode_as_value_t infiniband_payload_da_values = {infiniband_payload_prompt, 1, infiniband_payload_da_build_value}; + static decode_as_t infiniband_payload_da = {"infiniband", "Network", "infiniband", 1, 0, &infiniband_payload_da_values, NULL, NULL, + decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; + proto_infiniband = proto_register_protocol("InfiniBand", "IB", "infiniband"); ib_handle = register_dissector("infiniband", dissect_infiniband, proto_infiniband); @@ -7922,6 +7966,7 @@ void proto_register_infiniband(void) /* register the subdissector tables */ heur_dissectors_payload = register_heur_dissector_list("infiniband.payload", proto_infiniband); heur_dissectors_cm_private = register_heur_dissector_list("infiniband.mad.cm.private", proto_infiniband); + subdissector_table = register_dissector_table("infiniband", "Infiniband Payload", proto_infiniband, FT_UINT16, BASE_DEC); /* register dissection preferences */ infiniband_module = prefs_register_protocol(proto_infiniband, proto_reg_handoff_infiniband); @@ -7931,6 +7976,10 @@ void proto_register_infiniband(void) prefs_register_uint_preference(infiniband_module, "rroce.port", "RRoce UDP Port(Default 1021)", "when set " "the Analyser will consider this as RRoce UDP Port and parse it accordingly", 10, &pref_rroce_udp_port); + prefs_register_bool_preference(infiniband_module, "try_heuristic_first", + "Try heuristic sub-dissectors first", + "Try to decode a packet using an heuristic sub-dissector before using Decode As", + &try_heuristic_first); proto_infiniband_link = proto_register_protocol("InfiniBand Link", "InfiniBand Link", "infiniband_link"); ib_link_handle = register_dissector("infiniband_link", dissect_infiniband_link, proto_infiniband_link); @@ -7945,6 +7994,8 @@ void proto_register_infiniband(void) /* initialize the hash table */ CM_context_table = g_hash_table_new_full(g_int64_hash, g_int64_equal, table_destroy_notify, table_destroy_notify); + + register_decode_as(&infiniband_payload_da); } /* Reg Handoff. Register dissectors we'll need for IPoIB and RoCE */ diff --git a/epan/dissectors/packet-infiniband_sdp.c b/epan/dissectors/packet-infiniband_sdp.c index ecf6018894..426c82776f 100644 --- a/epan/dissectors/packet-infiniband_sdp.c +++ b/epan/dissectors/packet-infiniband_sdp.c @@ -41,7 +41,7 @@ void proto_reg_handoff_ib_sdp(void); this is SDP traffic */ #define SERVICE_ID_MASK 0x0000000000010000 -static int proto_infiniband = -1; /* we'll need the Infiniband protocol index sometimes, so keep it here */ +static int proto_infiniband = -1; /* we'll need the Infiniband protocol index for conversation data */ /* Initialize the protocol and registered fields... */ static int proto_ib_sdp = -1; @@ -90,22 +90,6 @@ static gint ett_ib_sdp = -1; static gint ett_ib_sdp_bsdh = -1; static gint ett_ib_sdp_hh = -1; -/* global preferences */ -static gboolean gPREF_MAN_EN = FALSE; -static gint gPREF_TYPE[2] = {0}; -static const char *gPREF_ID[2] = {NULL}; -static guint gPREF_QP[2] = {0}; - -/* source/destination addresses from preferences menu (parsed from gPREF_TYPE[?], gPREF_ID[?]) */ -address manual_addr[2]; -void *manual_addr_data[2]; - -static const enum_val_t pref_address_types[] = { - {"lid", "LID", 0}, - {"gid", "GID", 1}, - {NULL, NULL, -1} -}; - typedef enum { Hello = 0x0, HelloAck, @@ -157,67 +141,17 @@ static int dissect_ib_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { int local_offset = 0; - proto_item *SDP_header_item = NULL; - proto_tree *SDP_header_tree = NULL; - proto_item *SDP_BSDH_header_item = NULL; - proto_tree *SDP_BSDH_header_tree = NULL; - proto_item *SDP_EH_header_item = NULL; - proto_tree *SDP_EH_header_tree = NULL; + proto_item *SDP_header_item; + proto_tree *SDP_header_tree; + proto_item *SDP_BSDH_header_item; + proto_tree *SDP_BSDH_header_tree; + proto_item *SDP_EH_header_item; + proto_tree *SDP_EH_header_tree; guint8 mid; - conversation_t *conv; - conversation_infiniband_data *convo_data = NULL; - dissector_handle_t infiniband_handle; if (tvb_captured_length(tvb) < 16) /* check this has at least enough bytes for the BSDH */ return 0; - if (gPREF_MAN_EN) { - /* If the manual settings are enabled see if this fits - in which case we can skip - the following checks entirely and go straight to dissecting */ - if ( (addresses_equal(&pinfo->src, &manual_addr[0]) && - addresses_equal(&pinfo->dst, &manual_addr[1]) && - (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[0]) && - (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[1])) || - (addresses_equal(&pinfo->src, &manual_addr[1]) && - addresses_equal(&pinfo->dst, &manual_addr[0]) && - (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[1]) && - (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[0])) ) - goto manual_override; - } - - /* first try to find a conversation between the two current hosts. in most cases this - will not work since we do not have the source QP. this WILL succeed when we're still - in the process of CM negotiations */ - conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, - PT_IBQP, pinfo->srcport, pinfo->destport, 0); - - if (!conv) { - /* if not, try to find an established RC channel. recall Infiniband conversations are - registered with one side of the channel. since the packet is only guaranteed to - contain the qpn of the destination, we'll use this */ - conv = find_conversation(pinfo->num, &pinfo->dst, &pinfo->dst, - PT_IBQP, pinfo->destport, pinfo->destport, NO_ADDR_B|NO_PORT_B); - - if (!conv) - return 0; /* nothing to do with no conversation context */ - } - - if (proto_infiniband < 0) { /* first time - get the infiniband protocol index*/ - infiniband_handle = find_dissector("infiniband"); - if (!infiniband_handle) - return 0; /* no infiniband handle? can't get our proto-data; sorry, can't help you without this */ - proto_infiniband = dissector_handle_get_protocol_index(infiniband_handle); - } - convo_data = (conversation_infiniband_data *)conversation_get_proto_data(conv, proto_infiniband); - - if (!convo_data) - return 0; - - if (!(convo_data->service_id & SERVICE_ID_MASK)) - return 0; /* the service id doesn't match that of SDP - nothing for us to do here */ - -manual_override: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDP"); SDP_header_item = proto_tree_add_item(tree, proto_ib_sdp, tvb, local_offset, -1, ENC_NA); @@ -229,6 +163,9 @@ manual_override: mid = tvb_get_guint8(tvb, local_offset); proto_tree_add_item(SDP_BSDH_header_tree, hf_ib_sdp_mid, tvb, local_offset, 1, ENC_BIG_ENDIAN); local_offset += 1; + col_append_fstr(pinfo->cinfo, COL_INFO, "(SDP %s)", + rval_to_str(mid, mid_meanings, "Unknown")); + proto_tree_add_item(SDP_BSDH_header_tree, hf_ib_sdp_flags, tvb, local_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(SDP_BSDH_header_tree, hf_ib_sdp_flags_oobpres, tvb, local_offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(SDP_BSDH_header_tree, hf_ib_sdp_flags_oob_pend, tvb, local_offset, 4, ENC_BIG_ENDIAN); @@ -308,12 +245,47 @@ manual_override: break; } - col_append_fstr(pinfo->cinfo, COL_INFO, "(SDP %s)", - rval_to_str(mid, mid_meanings, "Unknown")); - return tvb_captured_length(tvb); } +static gboolean +dissect_ib_sdp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + conversation_t *conv; + conversation_infiniband_data *convo_data = NULL; + + if (tvb_captured_length(tvb) < 16) /* check this has at least enough bytes for the BSDH */ + return FALSE; + + /* first try to find a conversation between the two current hosts. in most cases this + will not work since we do not have the source QP. this WILL succeed when we're still + in the process of CM negotiations */ + conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, + PT_IBQP, pinfo->srcport, pinfo->destport, 0); + + if (!conv) { + /* if not, try to find an established RC channel. recall Infiniband conversations are + registered with one side of the channel. since the packet is only guaranteed to + contain the qpn of the destination, we'll use this */ + conv = find_conversation(pinfo->num, &pinfo->dst, &pinfo->dst, + PT_IBQP, pinfo->destport, pinfo->destport, NO_ADDR_B|NO_PORT_B); + + if (!conv) + return FALSE; /* nothing to do with no conversation context */ + } + + convo_data = (conversation_infiniband_data *)conversation_get_proto_data(conv, proto_infiniband); + + if (!convo_data) + return FALSE; + + if (!(convo_data->service_id & SERVICE_ID_MASK)) + return FALSE; /* the service id doesn't match that of SDP - nothing for us to do here */ + + dissect_ib_sdp(tvb, pinfo, tree, data); + return TRUE; +} + void proto_register_ib_sdp(void) { @@ -478,77 +450,33 @@ proto_register_ib_sdp(void) /* Register preferences */ ib_sdp_module = prefs_register_protocol(proto_ib_sdp, proto_reg_handoff_ib_sdp); - prefs_register_bool_preference(ib_sdp_module, "manual_en", "Enable manual settings", - "Check to treat all traffic between the configured source/destination as SDP", - &gPREF_MAN_EN); - - prefs_register_static_text_preference(ib_sdp_module, "addr_a", "Address A", - "Side A of the manually-configured connection"); - prefs_register_enum_preference(ib_sdp_module, "addr_a_type", "Address Type", - "Type of address specified", &gPREF_TYPE[0], pref_address_types, FALSE); - prefs_register_string_preference(ib_sdp_module, "addr_a_id", "ID", - "LID/GID of address A", &gPREF_ID[0]); - prefs_register_uint_preference(ib_sdp_module, "addr_a_qp", "QP Number", - "QP Number for address A", 10, &gPREF_QP[0]); - - prefs_register_static_text_preference(ib_sdp_module, "addr_b", "Address B", - "Side B of the manually-configured connection"); - prefs_register_enum_preference(ib_sdp_module, "addr_b_type", "Address Type", - "Type of address specified", &gPREF_TYPE[1], pref_address_types, FALSE); - prefs_register_string_preference(ib_sdp_module, "addr_b_id", "ID", - "LID/GID of address B", &gPREF_ID[1]); - prefs_register_uint_preference(ib_sdp_module, "addr_b_qp", "QP Number", - "QP Number for address B", 10, &gPREF_QP[1]); + prefs_register_static_text_preference(ib_sdp_module, "use_decode_as", + "Heuristic matching preferences removed. Use Infiniband protocol preferences or Decode As.", + "Simple heuristics can still be enable (may generate false positives) through Infiniband protocol preferences." + "To force Infiniband SDP dissection use Decode As"); + + prefs_register_obsolete_preference(ib_sdp_module, "manual_en"); + + prefs_register_obsolete_preference(ib_sdp_module, "addr_a"); + prefs_register_obsolete_preference(ib_sdp_module, "addr_a_type"); + prefs_register_obsolete_preference(ib_sdp_module, "addr_a_id"); + prefs_register_obsolete_preference(ib_sdp_module, "addr_a_qp"); + + prefs_register_obsolete_preference(ib_sdp_module, "addr_b"); + prefs_register_obsolete_preference(ib_sdp_module, "addr_b_type"); + prefs_register_obsolete_preference(ib_sdp_module, "addr_b_id"); + prefs_register_obsolete_preference(ib_sdp_module, "addr_b_qp"); } void proto_reg_handoff_ib_sdp(void) { - static gboolean initialized = FALSE; - - if (!initialized) { - heur_dissector_add("infiniband.payload", dissect_ib_sdp, "Infiniband SDP", "sdp_infiniband", proto_ib_sdp, HEURISTIC_ENABLE); - heur_dissector_add("infiniband.mad.cm.private", dissect_ib_sdp, "Infiniband SDP in PrivateData of CM packets", "sdp_ib_private", proto_ib_sdp, HEURISTIC_ENABLE); + heur_dissector_add("infiniband.payload", dissect_ib_sdp_heur, "Infiniband SDP", "sdp_infiniband", proto_ib_sdp, HEURISTIC_ENABLE); + heur_dissector_add("infiniband.mad.cm.private", dissect_ib_sdp_heur, "Infiniband SDP in PrivateData of CM packets", "sdp_ib_private", proto_ib_sdp, HEURISTIC_ENABLE); - /* allocate enough space in the addresses to store the largest address (a GID) */ - manual_addr_data[0] = wmem_alloc(wmem_epan_scope(), GID_SIZE); - manual_addr_data[1] = wmem_alloc(wmem_epan_scope(), GID_SIZE); + dissector_add_for_decode_as("infiniband", create_dissector_handle( dissect_ib_sdp, proto_ib_sdp ) ); - initialized = TRUE; - } - - if (gPREF_MAN_EN) { - /* the manual setting is enabled, so parse the settings into the address type */ - gboolean error_occured = FALSE; - char *not_parsed; - int i; - - for (i = 0; i < 2; i++) { - if (gPREF_ID[i][0] == '\0') { - error_occured = TRUE; - } else if (gPREF_TYPE[i] == 0) { /* LID */ - errno = 0; /* reset any previous error indicators */ - *((guint16*)manual_addr_data[i]) = (guint16)strtoul(gPREF_ID[i], ¬_parsed, 0); - if (errno || *not_parsed != '\0') { - error_occured = TRUE; - } else { - set_address(&manual_addr[i], AT_IB, sizeof(guint16), manual_addr_data[i]); - } - } else { /* GID */ - if (!str_to_ip6(gPREF_ID[i], manual_addr_data[i])) { - error_occured = TRUE; - } else { - set_address(&manual_addr[i], AT_IB, GID_SIZE, manual_addr_data[i]); - } - } - - if (error_occured) { - /* an invalid id was specified - disable manual settings until it's fixed */ - gPREF_MAN_EN = FALSE; - break; - } - } - } + proto_infiniband = proto_get_id_by_filter_name( "infiniband" ); } /* diff --git a/epan/dissectors/packet-iser.c b/epan/dissectors/packet-iser.c index 511926e121..f5edbebb7d 100644 --- a/epan/dissectors/packet-iser.c +++ b/epan/dissectors/packet-iser.c @@ -66,7 +66,7 @@ void proto_register_iser(void); static int proto_iser = -1; static dissector_handle_t iscsi_handler; -static dissector_handle_t ib_handler; + static int proto_ib = -1; /* iSER Header */ @@ -87,22 +87,8 @@ static gint ett_iser = -1; static gint ett_iser_flags = -1; /* global preferences */ -static gboolean gPREF_MAN_EN = FALSE; -static gint gPREF_TYPE[2] = {0}; -static const char *gPREF_ID[2] = {NULL}; -static guint gPREF_QP[2] = {0}; static range_t *gPORT_RANGE; -/* source/destination addresses from preferences menu (parsed from gPREF_TYPE[?], gPREF_ID[?]) */ -static address manual_addr[2]; -static void *manual_addr_data[2]; - -static const enum_val_t pref_address_types[] = { - {"lid", "LID", 0}, - {"gid", "GID", 1}, - {NULL, NULL, -1} -}; - static const value_string iser_flags_opcode[] = { { ISER_ISCSI_CTRL >> 4, "iSCSI Control-Type PDU"}, { ISER_HELLO >> 4, "Hello Message"}, @@ -126,16 +112,20 @@ static const int *hellorply_flags_fields[] = { NULL }; -static int dissect_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int dissect_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { tvbuff_t *next_tvb; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *iser_tree; guint offset = 0; - guint8 flags = tvb_get_guint8(tvb, 0); - guint8 vers; - guint8 opcode = flags & ISER_OPCODE_MASK; + guint8 flags, vers, opcode; + + if (tvb_reported_length(tvb) < ISER_ISCSI_HDR_SZ) + return 0; + + flags = tvb_get_guint8(tvb, 0); + opcode = flags & ISER_OPCODE_MASK; /* Check if the opcode is valid */ switch (opcode) { @@ -238,21 +228,7 @@ dissect_iser(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, conversation_infiniband_data *convo_data = NULL; if (tvb_reported_length(tvb) < ISER_ISCSI_HDR_SZ) - return 0; - - if (gPREF_MAN_EN) { - /* If the manual settings are enabled see if this fits - in which case we can skip - the following checks entirely and go straight to dissecting */ - if ( (addresses_equal(&pinfo->src, &manual_addr[0]) && - addresses_equal(&pinfo->dst, &manual_addr[1]) && - (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[0]) && - (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[1])) || - (addresses_equal(&pinfo->src, &manual_addr[1]) && - addresses_equal(&pinfo->dst, &manual_addr[0]) && - (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[1]) && - (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[0])) ) - return dissect_packet(tvb, pinfo, tree); - } + return FALSE; /* first try to find a conversation between the two current hosts. in most cases this will not work since we do not have the source QP. this WILL succeed when we're still @@ -268,21 +244,22 @@ dissect_iser(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, PT_IBQP, pinfo->destport, pinfo->destport, NO_ADDR_B|NO_PORT_B); if (!conv) - return 0; /* nothing to do with no conversation context */ + return FALSE; /* nothing to do with no conversation context */ } convo_data = (conversation_infiniband_data *)conversation_get_proto_data(conv, proto_ib); if (!convo_data) - return 0; + return FALSE; if ((convo_data->service_id & SID_MASK) != SID_ULP_TCP) - return 0; /* the service id doesn't match that of TCP ULP - nothing for us to do here */ + return FALSE; /* the service id doesn't match that of TCP ULP - nothing for us to do here */ if (!(value_is_in_range(gPORT_RANGE, (guint32)(convo_data->service_id & SID_PORT_MASK)))) - return 0; /* the port doesn't match that of iSER - nothing for us to do here */ + return FALSE; /* the port doesn't match that of iSER - nothing for us to do here */ - return dissect_packet(tvb, pinfo, tree); + dissect_packet(tvb, pinfo, tree, data); + return TRUE; } void @@ -354,27 +331,22 @@ proto_register_iser(void) /* Register preferences */ iser_module = prefs_register_protocol(proto_iser, proto_reg_handoff_iser); - prefs_register_bool_preference(iser_module, "manual_en", "Enable manual settings", - "Check to treat all traffic between the configured source/destination as iSER", - &gPREF_MAN_EN); - - prefs_register_static_text_preference(iser_module, "addr_a", "Address A", - "Side A of the manually-configured connection"); - prefs_register_enum_preference(iser_module, "addr_a_type", "Address Type", - "Type of address specified", &gPREF_TYPE[0], pref_address_types, FALSE); - prefs_register_string_preference(iser_module, "addr_a_id", "ID", - "LID/GID of address A", &gPREF_ID[0]); - prefs_register_uint_preference(iser_module, "addr_a_qp", "QP Number", - "QP Number for address A", 10, &gPREF_QP[0]); - - prefs_register_static_text_preference(iser_module, "addr_b", "Address B", - "Side B of the manually-configured connection"); - prefs_register_enum_preference(iser_module, "addr_b_type", "Address Type", - "Type of address specified", &gPREF_TYPE[1], pref_address_types, FALSE); - prefs_register_string_preference(iser_module, "addr_b_id", "ID", - "LID/GID of address B", &gPREF_ID[1]); - prefs_register_uint_preference(iser_module, "addr_b_qp", "QP Number", - "QP Number for address B", 10, &gPREF_QP[1]); + prefs_register_static_text_preference(iser_module, "use_decode_as", + "Heuristic matching preferences removed. Use Infiniband protocol preferences or Decode As.", + "Simple heuristics can still be enable (may generate false positives) through Infiniband protocol preferences." + "To force iSER dissection use Decode As"); + + prefs_register_obsolete_preference(iser_module, "manual_en"); + + prefs_register_obsolete_preference(iser_module, "addr_a"); + prefs_register_obsolete_preference(iser_module, "addr_a_type"); + prefs_register_obsolete_preference(iser_module, "addr_a_id"); + prefs_register_obsolete_preference(iser_module, "addr_a_qp"); + + prefs_register_obsolete_preference(iser_module, "addr_b"); + prefs_register_obsolete_preference(iser_module, "addr_b_type"); + prefs_register_obsolete_preference(iser_module, "addr_b_id"); + prefs_register_obsolete_preference(iser_module, "addr_b_qp"); range_convert_str(&gPORT_RANGE, TCP_PORT_ISER_RANGE, MAX_TCP_PORT); prefs_register_range_preference(iser_module, @@ -388,53 +360,13 @@ proto_register_iser(void) void proto_reg_handoff_iser(void) { - static gboolean initialized = FALSE; - - if (!initialized) { - heur_dissector_add("infiniband.payload", dissect_iser, "iSER Infiniband", "iser_infiniband", proto_iser, HEURISTIC_ENABLE); - heur_dissector_add("infiniband.mad.cm.private", dissect_iser, "iSER in PrivateData of CM packets", "iser_ib_private", proto_iser, HEURISTIC_ENABLE); + heur_dissector_add("infiniband.payload", dissect_iser, "iSER Infiniband", "iser_infiniband", proto_iser, HEURISTIC_ENABLE); + heur_dissector_add("infiniband.mad.cm.private", dissect_iser, "iSER in PrivateData of CM packets", "iser_ib_private", proto_iser, HEURISTIC_ENABLE); - /* allocate enough space in the addresses to store the largest address (a GID) */ - manual_addr_data[0] = wmem_alloc(wmem_epan_scope(), GID_SIZE); - manual_addr_data[1] = wmem_alloc(wmem_epan_scope(), GID_SIZE); + dissector_add_for_decode_as("infiniband", create_dissector_handle( dissect_packet, proto_iser ) ); - iscsi_handler = find_dissector_add_dependency("iscsi", proto_iser); - ib_handler = find_dissector_add_dependency("infiniband", proto_iser); - proto_ib = dissector_handle_get_protocol_index(ib_handler); - - initialized = TRUE; - } - - if (gPREF_MAN_EN) { - /* the manual setting is enabled, so parse the settings into the address type */ - gboolean error_occured = FALSE; - char *not_parsed; - int i; - - for (i = 0; i < 2; i++) { - if (gPREF_TYPE[i] == 0) { /* LID */ - errno = 0; /* reset any previous error indicators */ - *((guint16*)manual_addr_data[i]) = (guint16)strtoul(gPREF_ID[i], ¬_parsed, 0); - if (errno || *not_parsed != '\0') { - error_occured = TRUE; - } else { - set_address(&manual_addr[i], AT_IB, sizeof(guint16), manual_addr_data[i]); - } - } else { /* GID */ - if (!str_to_ip6(gPREF_ID[i], manual_addr_data[i]) ) { - error_occured = TRUE; - } else { - set_address(&manual_addr[i], AT_IB, GID_SIZE, manual_addr_data[i]); - } - } - - if (error_occured) { - /* an invalid id was specified - disable manual settings until it's fixed */ - gPREF_MAN_EN = FALSE; - break; - } - } - } + iscsi_handler = find_dissector_add_dependency("iscsi", proto_iser); + proto_ib = proto_get_id_by_filter_name( "infiniband" ); } /* diff --git a/epan/dissectors/packet-rpcrdma.c b/epan/dissectors/packet-rpcrdma.c index 12346ee7a7..826604cc92 100644 --- a/epan/dissectors/packet-rpcrdma.c +++ b/epan/dissectors/packet-rpcrdma.c @@ -475,7 +475,7 @@ packet_is_rpcordma(tvbuff_t *tvb) } static int -dissect_rpcrdma(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +dissect_rpcrdma(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { tvbuff_t *next_tvb; proto_item *ti; @@ -599,7 +599,7 @@ dissect_rpcrdma_ib_heur(tvbuff_t *tvb, packet_info *pinfo, if (!packet_is_rpcordma(tvb)) return FALSE; - dissect_rpcrdma(tvb, pinfo, tree); + dissect_rpcrdma(tvb, pinfo, tree, NULL); return TRUE; } @@ -623,7 +623,7 @@ dissect_rpcrdma_iwarp_heur(tvbuff_t *tvb, packet_info *pinfo, if (!packet_is_rpcordma(tvb)) return FALSE; - dissect_rpcrdma(tvb, pinfo, tree); + dissect_rpcrdma(tvb, pinfo, tree, NULL); return TRUE; } @@ -757,23 +757,14 @@ proto_register_rpcordma(void) void proto_reg_handoff_rpcordma(void) { - static gboolean initialized = FALSE; + heur_dissector_add("infiniband.payload", dissect_rpcrdma_ib_heur, "RPC-over-RDMA on Infiniband", + "rpcrdma_infiniband", proto_rpcordma, HEURISTIC_ENABLE); + dissector_add_for_decode_as("infiniband", create_dissector_handle( dissect_rpcrdma, proto_rpcordma ) ); - if (!initialized) { - heur_dissector_add("infiniband.payload", dissect_rpcrdma_ib_heur, "RPC-over-RDMA on Infiniband", - "rpcrdma_infiniband", proto_rpcordma, HEURISTIC_ENABLE); - heur_dissector_add("iwarp_ddp_rdmap", dissect_rpcrdma_iwarp_heur, "RPC-over-RDMA on iWARP", - "rpcrdma_iwarp", proto_rpcordma, HEURISTIC_ENABLE); + heur_dissector_add("iwarp_ddp_rdmap", dissect_rpcrdma_iwarp_heur, "RPC-over-RDMA on iWARP", + "rpcrdma_iwarp", proto_rpcordma, HEURISTIC_ENABLE); - /* The following is never used: there are no known implementations, and no specification */ - heur_dissector_add("infiniband.mad.cm.private", dissect_rpcrdma_ib_heur, - "RPC over RDMA in PrivateData of CM packets", - "rpcordma_ib_private", proto_rpcordma, HEURISTIC_ENABLE); - - rpc_handler = find_dissector_add_dependency("rpc", proto_rpcordma); - - initialized = TRUE; - } + rpc_handler = find_dissector_add_dependency("rpc", proto_rpcordma); } /* diff --git a/epan/dissectors/packet-smb-direct.c b/epan/dissectors/packet-smb-direct.c index 5344835587..29ccbdd9d6 100644 --- a/epan/dissectors/packet-smb-direct.c +++ b/epan/dissectors/packet-smb-direct.c @@ -514,15 +514,15 @@ dissect_smb_direct_iwarp_heur(tvbuff_t *tvb, packet_info *pinfo, return TRUE; } -static gboolean -dissect_smb_direct_infiniband_heur(tvbuff_t *tvb, packet_info *pinfo, +static int +dissect_smb_direct_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data) { struct infinibandinfo *info = (struct infinibandinfo *)data; enum SMB_DIRECT_HDR_TYPE hdr_type; if (info == NULL) { - return FALSE; + return 0; } switch (info->opCode) { @@ -536,16 +536,23 @@ dissect_smb_direct_infiniband_heur(tvbuff_t *tvb, packet_info *pinfo, case RC_SEND_ONLY_INVAL: break; default: - return FALSE; + return 0; } hdr_type = is_smb_direct(tvb, pinfo); if (hdr_type == SMB_DIRECT_HDR_UNKNOWN) { - return FALSE; + return 0; } dissect_smb_direct(tvb, pinfo, parent_tree, hdr_type); - return TRUE; + return tvb_captured_length(tvb); +} + +static gboolean +dissect_smb_direct_infiniband_heur(tvbuff_t *tvb, packet_info *pinfo, + proto_tree *parent_tree, void *data) +{ + return (dissect_smb_direct_infiniband(tvb, pinfo, parent_tree, data) > 0); } void proto_register_smb_direct(void) @@ -700,13 +707,14 @@ void proto_reg_handoff_smb_direct(void) { heur_dissector_add("iwarp_ddp_rdmap", - dissect_smb_direct_iwarp_heur, - "SMB Direct over iWARP", "smb_direct_iwarp", - proto_smb_direct, HEURISTIC_ENABLE); + dissect_smb_direct_iwarp_heur, + "SMB Direct over iWARP", "smb_direct_iwarp", + proto_smb_direct, HEURISTIC_ENABLE); heur_dissector_add("infiniband.payload", - dissect_smb_direct_infiniband_heur, - "SMB Direct Infiniband", "smb_direct_infiniband", - proto_smb_direct, HEURISTIC_ENABLE); + dissect_smb_direct_infiniband_heur, + "SMB Direct Infiniband", "smb_direct_infiniband", + proto_smb_direct, HEURISTIC_ENABLE); + dissector_add_for_decode_as("infiniband", create_dissector_handle( dissect_smb_direct_infiniband, proto_smb_direct ) ); } diff --git a/epan/dissectors/packet-smcr.c b/epan/dissectors/packet-smcr.c index f92910786f..bbdf7ad0c9 100644 --- a/epan/dissectors/packet-smcr.c +++ b/epan/dissectors/packet-smcr.c @@ -794,8 +794,8 @@ dissect_smcr_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, return tvb_reported_length(tvb); } -static void -dissect_smcr_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int +dissect_smcr_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { guint16 msg_len; llc_message llc_msgid; @@ -814,9 +814,6 @@ dissect_smcr_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) (tvb_get_guint8(tvb, LLC_CMD_RSP_OFFSET) & LLC_FLAG_RESP)) col_append_str(pinfo->cinfo, COL_INFO, "(Resp)"); - if (!tree) - return; - ti = proto_tree_add_item(tree, proto_smcr, tvb, 0, msg_len, ENC_NA); smcr_tree = proto_item_add_subtree(ti, ett_smcr); proto_tree_add_item(smcr_tree, hf_smcr_llc_msg, tvb, 0, 1, @@ -863,7 +860,8 @@ dissect_smcr_infiniband(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* Unknown Command */ break; } - return; + + return tvb_captured_length(tvb); } static guint @@ -925,7 +923,7 @@ dissect_smcr_infiniband_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree if (msg_len != tvb_reported_length_remaining(tvb, LLC_CMD_OFFSET)) return FALSE; - dissect_smcr_infiniband(tvb, pinfo, tree); + dissect_smcr_infiniband(tvb, pinfo, tree, data); return TRUE; } @@ -1433,6 +1431,7 @@ proto_reg_handoff_smcr(void) { heur_dissector_add("tcp", dissect_smcr_tcp_heur, "Shared Memory Communications over TCP", "smcr_tcp", proto_smcr, HEURISTIC_ENABLE); heur_dissector_add("infiniband.payload", dissect_smcr_infiniband_heur, "Shared Memory Communications Infiniband", "smcr_infiniband", proto_smcr, HEURISTIC_ENABLE); + dissector_add_for_decode_as("infiniband", create_dissector_handle( dissect_smcr_infiniband, proto_smcr ) ); } /* |