aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-cip.c30
-rw-r--r--epan/dissectors/packet-cip.h5
-rw-r--r--epan/dissectors/packet-cipmotion.c2
-rw-r--r--epan/dissectors/packet-cipsafety.c11
-rw-r--r--epan/dissectors/packet-enip.c160
-rw-r--r--epan/dissectors/packet-enip.h5
6 files changed, 136 insertions, 77 deletions
diff --git a/epan/dissectors/packet-cip.c b/epan/dissectors/packet-cip.c
index 75e200aac5..41b84b5938 100644
--- a/epan/dissectors/packet-cip.c
+++ b/epan/dissectors/packet-cip.c
@@ -511,7 +511,6 @@ static int hf_port_min_node_num = -1;
static int hf_port_max_node_num = -1;
static int hf_port_name = -1;
static int hf_port_num_comm_object_entries = -1;
-static int hf_conn_path_class = -1;
static int hf_path_len_usint = -1;
static int hf_path_len_uint = -1;
@@ -6282,9 +6281,7 @@ dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvb
guint32 O2TConnID, T2OConnID;
guint8 TransportClass_trigger, O2TType, T2OType;
cip_simple_request_info_t connection_path;
- cip_safety_epath_info_t safety_fwdopen;
-
- memset(&safety_fwdopen, 0x0, sizeof(safety_fwdopen));
+ cip_safety_epath_info_t safety_fwdopen = {0};
dissect_cip_cm_timeout(cmd_tree, tvb, offset);
proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_ot_connid, tvb, offset+2, 4, ENC_LITTLE_ENDIAN, &O2TConnID);
@@ -6381,6 +6378,10 @@ dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvb
preq_info->connInfo->safety = safety_fwdopen;
preq_info->connInfo->ClassID = connection_path.iClass;
preq_info->connInfo->ConnPoint = connection_path.iConnPoint;
+
+ preq_info->connInfo->FwdOpenPathLenBytes = conn_path_size;
+ preq_info->connInfo->pFwdOpenPathData = wmem_alloc(wmem_file_scope(), conn_path_size);
+ tvb_memcpy(tvb, preq_info->connInfo->pFwdOpenPathData, offset + 26 + net_param_offset + 6, conn_path_size);
}
}
}
@@ -6388,13 +6389,11 @@ dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvb
static void
dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
- int temp_data;
unsigned char app_rep_size;
guint32 O2TConnID, T2OConnID;
guint16 init_rollover_value = 0, init_timestamp_value = 0;
proto_tree *pid_tree, *safety_tree;
- cip_connection_triad_t target_triad;
- memset(&target_triad, 0, sizeof(target_triad));
+ cip_connection_triad_t target_triad = {0};
/* Display originator to target connection ID */
O2TConnID = tvb_get_letohl( tvb, offset );
@@ -6410,12 +6409,12 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
&conn_triad);
/* Display originator to target actual packet interval */
- temp_data = tvb_get_letohl( tvb, offset+16 );
- proto_tree_add_uint_format_value(tree, hf_cip_cm_ot_api, tvb, offset+16, 4, temp_data, "%dms (0x%08X)", temp_data / 1000, temp_data);
+ guint32 O2TAPI = tvb_get_letohl( tvb, offset+16 );
+ proto_tree_add_uint_format_value(tree, hf_cip_cm_ot_api, tvb, offset+16, 4, O2TAPI, "%dms (0x%08X)", O2TAPI / 1000, O2TAPI);
/* Display originator to target actual packet interval */
- temp_data = tvb_get_letohl( tvb, offset+20 );
- proto_tree_add_uint_format_value(tree, hf_cip_cm_to_api, tvb, offset+20, 4, temp_data, "%dms (0x%08X)", temp_data / 1000, temp_data);
+ guint32 T2OAPI = tvb_get_letohl( tvb, offset+20 );
+ proto_tree_add_uint_format_value(tree, hf_cip_cm_to_api, tvb, offset+20, 4, T2OAPI, "%dms (0x%08X)", T2OAPI / 1000, T2OAPI);
/* Display the application reply size */
app_rep_size = tvb_get_guint8( tvb, offset+24 ) * 2;
@@ -6485,6 +6484,9 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
the ForwardOpen request */
preq_info->connInfo->O2T.connID = O2TConnID;
preq_info->connInfo->T2O.connID = T2OConnID;
+
+ preq_info->connInfo->O2T.api = O2TAPI;
+ preq_info->connInfo->T2O.api = T2OAPI;
if (preq_info->connInfo->safety.safety_seg == TRUE)
{
preq_info->connInfo->safety.running_rollover_value = init_rollover_value;
@@ -8010,7 +8012,6 @@ static int
dissect_cip_implicit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
proto_item *ti;
- proto_item *conn_path_class_item;
proto_tree *cip_tree;
guint32 ClassID = GPOINTER_TO_UINT(data);
@@ -8024,10 +8025,6 @@ dissect_cip_implicit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
ti = proto_tree_add_item(tree, proto_cip, tvb, 0, length, ENC_NA);
cip_tree = proto_item_add_subtree(ti, ett_cip);
- /* Display Class ID from the Forward Open Connection Path. */
- conn_path_class_item = proto_tree_add_uint(cip_tree, hf_conn_path_class, NULL, 0, 0, ClassID);
- PROTO_ITEM_SET_GENERATED(conn_path_class_item);
-
proto_tree_add_item(cip_tree, hf_cip_data, tvb, 0, length, ENC_NA);
col_append_fstr(pinfo->cinfo, COL_INFO, "Implicit Data - %s",
@@ -8319,7 +8316,6 @@ proto_register_cip(void)
{ &hf_port_max_node_num, { "Maximum Node Number", "cip.port.max_node", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
{ &hf_port_name, { "Port Name", "cip.port.name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
{ &hf_port_num_comm_object_entries, { "Number of entries", "cip.port.num_comm_object_entries", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
- { &hf_conn_path_class, { "CIP Connection Path Class", "cip.conn_path_class", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
{ &hf_path_len_usint, { "Path Length", "cip.path_len", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL } },
{ &hf_path_len_uint, { "Path Length", "cip.path_len", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL } },
diff --git a/epan/dissectors/packet-cip.h b/epan/dissectors/packet-cip.h
index 0eb8a3d929..9f48afa9cd 100644
--- a/epan/dissectors/packet-cip.h
+++ b/epan/dissectors/packet-cip.h
@@ -460,6 +460,9 @@ typedef struct cip_connID_info {
address ipaddress;
guint16 port;
guint8 type;
+
+ // Actual Packet Interval in microseconds.
+ guint32 api;
} cip_connID_info_t;
enum cip_safety_format_type {CIP_SAFETY_BASE_FORMAT, CIP_SAFETY_EXTENDED_FORMAT};
@@ -487,6 +490,8 @@ typedef struct cip_conn_info {
cip_safety_epath_info_t safety;
guint32 ClassID;
guint32 ConnPoint;
+ guint32 FwdOpenPathLenBytes;
+ void *pFwdOpenPathData;
} cip_conn_info_t;
typedef struct cip_req_info {
diff --git a/epan/dissectors/packet-cipmotion.c b/epan/dissectors/packet-cipmotion.c
index de0d94881a..b14bf0e6ac 100644
--- a/epan/dissectors/packet-cipmotion.c
+++ b/epan/dissectors/packet-cipmotion.c
@@ -1922,7 +1922,7 @@ dissect_cipmotion(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* dat
static int dissect_cipmotion3(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
{
- enip_conn_val_t conn_info;
+ enip_conn_val_t conn_info = {0};
conn_info.ConnPoint = 3;
cip_io_data_input io_data_input;
diff --git a/epan/dissectors/packet-cipsafety.c b/epan/dissectors/packet-cipsafety.c
index 07e0837243..c750800d1b 100644
--- a/epan/dissectors/packet-cipsafety.c
+++ b/epan/dissectors/packet-cipsafety.c
@@ -1477,8 +1477,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
proto_item *complement_item, *crc_s5_item, *crc_s5_status_item;
gboolean short_format = TRUE;
gboolean compute_crc = ((safety_info != NULL) && (safety_info->compute_crc == TRUE));
- cip_connection_triad_t connection_triad;
- memset(&connection_triad, 0, sizeof(connection_triad));
+ cip_connection_triad_t connection_triad = {0};
/* Make entries in Protocol column and Info column on summary display */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Safety");
@@ -1958,7 +1957,7 @@ dissect_cipsafety(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat
static int dissect_cipsafety_base_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
cip_safety_info_t safety_info;
- enip_conn_val_t eip_conn_info;
+ enip_conn_val_t eip_conn_info = {0};
safety_info.eip_conn_info = &eip_conn_info;
safety_info.compute_crc = FALSE;
@@ -1973,7 +1972,7 @@ static int dissect_cipsafety_base_data(tvbuff_t *tvb, packet_info *pinfo, proto_
static int dissect_cipsafety_extended_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
cip_safety_info_t safety_info;
- enip_conn_val_t eip_conn_info;
+ enip_conn_val_t eip_conn_info = {0};
safety_info.eip_conn_info = &eip_conn_info;
safety_info.compute_crc = FALSE;
@@ -1988,7 +1987,7 @@ static int dissect_cipsafety_extended_data(tvbuff_t *tvb, packet_info *pinfo, pr
static int dissect_cipsafety_base_time_coord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
cip_safety_info_t safety_info;
- enip_conn_val_t eip_conn_info;
+ enip_conn_val_t eip_conn_info = {0};
safety_info.eip_conn_info = &eip_conn_info;
safety_info.compute_crc = FALSE;
@@ -2003,7 +2002,7 @@ static int dissect_cipsafety_base_time_coord(tvbuff_t *tvb, packet_info *pinfo,
static int dissect_cipsafety_extended_time_coord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
cip_safety_info_t safety_info;
- enip_conn_val_t eip_conn_info;
+ enip_conn_val_t eip_conn_info = {0};
safety_info.eip_conn_info = &eip_conn_info;
safety_info.compute_crc = FALSE;
diff --git a/epan/dissectors/packet-enip.c b/epan/dissectors/packet-enip.c
index deb4c6fd4b..1715ee2064 100644
--- a/epan/dissectors/packet-enip.c
+++ b/epan/dissectors/packet-enip.c
@@ -148,6 +148,8 @@ static int hf_enip_cpf_itemcount = -1;
static int hf_enip_cpf_typeid = -1;
static int hf_enip_cpf_length = -1;
static int hf_cip_sequence_count = -1;
+static int hf_cip_cm_ot_api = -1;
+static int hf_cip_cm_to_api = -1;
static int hf_enip_cpf_cai_connid = -1;
static int hf_enip_cpf_sai_connid = -1;
static int hf_enip_cpf_sai_seqnum = -1;
@@ -347,6 +349,8 @@ static gint ett_eip_cert_capability_flags = -1;
static gint ett_eip_cert_num_certs = -1;
static gint ett_security_profiles = -1;
static gint ett_iana_port_state_flags = -1;
+static gint ett_connection_info = -1;
+static gint ett_connection_path_info = -1;
static expert_field ei_mal_tcpip_status = EI_INIT;
static expert_field ei_mal_tcpip_config_cap = EI_INIT;
@@ -745,9 +749,9 @@ enum enip_packet_type {ENIP_REQUEST_PACKET, ENIP_RESPONSE_PACKET, ENIP_CANNOT_CL
enum enip_packet_data_type { EPDT_UNKNOWN, EPDT_CONNECTED_TRANSPORT, EPDT_UNCONNECTED };
typedef struct enip_request_key {
+ guint32 session_handle;
enum enip_packet_type requesttype;
enum enip_packet_data_type type;
- guint32 session_handle;
guint64 sender_context;
guint32 conversation;
union {
@@ -1066,7 +1070,6 @@ enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
conversation_t *conversation, *conversationTO;
enip_conv_info_t *enip_info;
address dest_address;
- ws_in6_addr ipv6_zero;
if (pinfo->fd->flags.visited)
return;
@@ -1099,14 +1102,18 @@ enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
conn_val->close_frame = 0;
conn_val->connid = enip_unique_connid++;
+ conn_val->FwdOpenPathLenBytes = connInfo->FwdOpenPathLenBytes;
+ conn_val->pFwdOpenPathData = connInfo->pFwdOpenPathData;
+ conn_val->O2Tapi = connInfo->O2T.api;
+ conn_val->T2Oapi = connInfo->T2O.api;
+
wmem_map_insert(enip_conn_hashtable, conn_key, conn_val );
/* I/O connection */
if (((connInfo->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 0) ||
((connInfo->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1))
{
- /* zero out the ipv6 structure for comparison */
- memset(&ipv6_zero, 0, sizeof(ipv6_zero));
+ ws_in6_addr ipv6_zero = {0};
/* default some information if not included */
if ((connInfo->O2T.port == 0) || (connInfo->O2T.type == CONN_TYPE_MULTICAST))
@@ -1203,8 +1210,7 @@ enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
}
/* Save the connection info for the conversation filter */
- if (!pinfo->fd->flags.visited)
- p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
}
void
@@ -1226,8 +1232,7 @@ enip_close_cip_connection(packet_info *pinfo, const cip_connection_triad_t* tria
conn_val->close_frame = pinfo->num;
/* Save the connection info for the conversation filter */
- if (!pinfo->fd->flags.visited)
- p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
}
}
@@ -2294,6 +2299,52 @@ static void dissect_item_list_services_response(packet_info* pinfo, tvbuff_t* tv
tvb_format_stringzpad(tvb, offset + 4, 16));
}
+static void display_fwd_open_connection_path(enip_conn_val_t* conn_info, proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo)
+{
+ if (!conn_info->pFwdOpenPathData)
+ {
+ return;
+ }
+
+ tvbuff_t* tvbIOI = tvb_new_real_data((const guint8*)conn_info->pFwdOpenPathData, conn_info->FwdOpenPathLenBytes, conn_info->FwdOpenPathLenBytes);
+ if (tvbIOI)
+ {
+ proto_item* pi = NULL;
+ proto_tree* epath_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_path_info, &pi, "Connection Path: ");
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ dissect_epath(tvbIOI, pinfo, epath_tree, pi, 0, conn_info->FwdOpenPathLenBytes, TRUE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
+ tvb_free(tvbIOI);
+ }
+}
+
+static void display_connection_information(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree, enip_conn_val_t* conn_info, enum enip_connid_type connid_type)
+{
+ proto_item* pi = NULL;
+ proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &pi, "Connection Information");
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ if (connid_type == ECIDT_O2T)
+ {
+ proto_item_append_text(pi, ": O->T");
+ }
+ else if (connid_type == ECIDT_T2O)
+ {
+ proto_item_append_text(pi, ": T->O");
+ }
+
+ display_fwd_open_connection_path(conn_info, conn_info_tree, tvb, pinfo);
+
+ pi = proto_tree_add_uint_format_value(conn_info_tree, hf_cip_cm_ot_api, tvb, 0, 0, conn_info->O2Tapi, "%dms (0x%08X)", conn_info->O2Tapi / 1000, conn_info->O2Tapi);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ pi = proto_tree_add_uint_format_value(conn_info_tree, hf_cip_cm_to_api, tvb, 0, 0, conn_info->T2Oapi, "%dms (0x%08X)", conn_info->T2Oapi / 1000, conn_info->T2Oapi);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ pi = proto_tree_add_uint(conn_info_tree, hf_enip_fwd_open_in, tvb, 0, 0, conn_info->open_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+}
+
// This dissects Class 0 or Class 1 I/O.
// offset - Starts at the field after the Item Length field.
static int dissect_cip_io_generic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data)
@@ -2305,7 +2356,8 @@ static int dissect_cip_io_generic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_t
proto_item* ti = proto_tree_add_item(tree, proto_cipio, tvb, 0, -1, ENC_NA);
proto_tree* io_tree = proto_item_add_subtree(ti, ett_cip_io_generic);
- if (io_data_input != NULL) {
+ if (io_data_input != NULL)
+ {
if ((io_data_input->conn_info->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1)
{
proto_tree_add_item(io_tree, hf_cip_sequence_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
@@ -2368,10 +2420,6 @@ static void dissect_cip_class01_io(packet_info* pinfo, tvbuff_t* tvb, int offset
call_dissector_with_data(cip_io_generic_handle, next_tvb, pinfo, dissector_tree, &io_data_input);
}
}
-
- /* Save the connection info for the conversation filter */
- if (!pinfo->fd->flags.visited)
- p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_info);
}
else
{
@@ -2398,10 +2446,6 @@ static void dissect_cip_class23_data(packet_info* pinfo, tvbuff_t* tvb, int offs
request_info = enip_match_request(pinfo, tree, request_key);
}
- /* Save the connection info for the conversation filter */
- if ((!pinfo->fd->flags.visited) && (conn_info != NULL))
- p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_info);
-
/* Add sequence count ( Transport Class 2,3 ) */
proto_tree_add_item(item_tree, hf_cip_sequence_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
@@ -2475,29 +2519,31 @@ static void dissect_item_sockaddr_info(packet_info *pinfo, tvbuff_t* tvb, int of
// offset - Starts at the Connection ID
// Returns: connid_type, conn_info
static void dissect_item_sequenced_address(packet_info* pinfo, tvbuff_t* tvb, int offset,
- proto_tree* item_tree, proto_tree* tree,
- enum enip_connid_type* connid_type, enip_conn_val_t** conn_info)
+ proto_tree* item_tree, enum enip_connid_type* connid_type, enip_conn_val_t** conn_info)
{
- *conn_info = enip_get_io_connid(pinfo, tvb_get_letohl(tvb, offset), connid_type);
- proto_tree_add_item(item_tree, hf_enip_cpf_sai_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(item_tree, hf_enip_cpf_sai_seqnum, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
+ guint32 connection_id;
+ proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_sai_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &connection_id);
+
+ guint32 sequence_num;
+ proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_sai_seqnum, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &sequence_num);
- if (*conn_info)
+ *conn_info = enip_get_io_connid(pinfo, connection_id, connid_type);
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Connection: ID=0x%08X, SEQ=%010d", connection_id, sequence_num);
+ if (*connid_type == ECIDT_O2T)
{
- proto_item* it = proto_tree_add_uint(tree, hf_enip_fwd_open_in, tvb, 0, 0, (*conn_info)->open_frame);
- PROTO_ITEM_SET_GENERATED(it);
+ col_append_str(pinfo->cinfo, COL_INFO, ", O->T");
+ }
+ else if (*connid_type == ECIDT_T2O)
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", T->O");
}
-
- /* Add info to column */
- col_add_fstr(pinfo->cinfo, COL_INFO, "Connection: ID=0x%08X, SEQ=%010d",
- tvb_get_letohl(tvb, offset),
- tvb_get_letohl(tvb, offset + 4));
}
// offset - Starts at the Connection ID
// Returns: conn_info
static void dissect_item_connected_address(packet_info* pinfo, tvbuff_t* tvb, int offset,
- proto_tree* item_tree, proto_tree* tree, proto_item* enip_item,
+ proto_tree* item_tree, proto_item* enip_item,
enip_request_key_t* request_key, enip_conn_val_t** conn_info)
{
guint32 connection_id;
@@ -2511,18 +2557,12 @@ static void dissect_item_connected_address(packet_info* pinfo, tvbuff_t* tvb, in
}
/* Add Connection ID to Info col and tree */
- col_append_fstr(pinfo->cinfo, COL_INFO, ", CONID: 0x%08X", connection_id);
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Connection: ID=0x%08X", connection_id);
if (enip_item)
{
proto_item_append_text(enip_item, ", Connection ID: 0x%08X", connection_id);
}
-
- if (*conn_info)
- {
- proto_item* it = proto_tree_add_uint(tree, hf_enip_fwd_open_in, tvb, 0, 0, (*conn_info)->open_frame);
- PROTO_ITEM_SET_GENERATED(it);
- }
}
// offset - Starts at Unconn Msg Type
@@ -2570,7 +2610,7 @@ static void dissect_item_unconnected_message_over_udp(packet_info* pinfo, tvbuff
/* Dissect Common Packet Format */
static void
dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
- packet_info *pinfo, proto_tree *tree, proto_tree *dissector_tree,
+ packet_info *pinfo, proto_tree *tree, proto_tree *dissector_tree, proto_tree *enip_layer_tree,
proto_item *enip_item, int offset, guint32 ifacehndl)
{
proto_item *count_item;
@@ -2626,7 +2666,7 @@ dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
{
case CONNECTION_BASED: // 1st Item for: Class 3 Connected Messages
conn_info = NULL;
- dissect_item_connected_address(pinfo, tvb, offset, item_tree, tree, enip_item, request_key, &conn_info);
+ dissect_item_connected_address(pinfo, tvb, offset, item_tree, enip_item, request_key, &conn_info);
break;
case UNCONNECTED_MSG_DTLS: // Only item for: Unconnected messages over DTLS
@@ -2687,6 +2727,12 @@ dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
}
case CONNECTION_TRANSPORT: // 2nd item for: Connected messages (both Class 0/1 and Class 3)
+ // Save the connection info for the conversation filter
+ if (!pinfo->fd->flags.visited && conn_info)
+ {
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_info);
+ }
+
if (command == SEND_UNIT_DATA) // Class 2/3 over TCP.
{
dissect_cip_class23_data(pinfo, tvb, offset, tree, item_tree, item_length, request_key, conn_info, dissector_tree);
@@ -2696,6 +2742,11 @@ dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
dissect_cip_class01_io(pinfo, tvb, offset, item_length, conn_info, connid_type, dissector_tree);
}
+ if (conn_info)
+ {
+ display_connection_information(pinfo, tvb, enip_layer_tree, conn_info, connid_type);
+ }
+
break;
case LIST_IDENTITY_RESP:
@@ -2716,7 +2767,7 @@ dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
case SEQ_ADDRESS: // 1st item for: Class 0/1 connected data
conn_info = NULL;
- dissect_item_sequenced_address(pinfo, tvb, offset, item_tree, tree, &connid_type, &conn_info);
+ dissect_item_sequenced_address(pinfo, tvb, offset, item_tree, &connid_type, &conn_info);
break;
case LIST_SERVICES_RESP:
@@ -2799,7 +2850,6 @@ dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
guint16 encap_cmd, encap_data_length;
const char *pkt_type_str = "";
guint32 ifacehndl;
- enip_request_key_t request_key;
conversation_t *conversation;
/* Set up structures needed to add the protocol subtree and manage it */
@@ -2844,7 +2894,7 @@ dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
* Attach that information to the conversation, and add
* it to the list of information structures later before dissection.
*/
- memset( &request_key, 0, sizeof(enip_request_key_t) );
+ enip_request_key_t request_key = {0};
request_key.requesttype = packet_type;
request_key.type = EPDT_UNKNOWN;
request_key.session_handle = tvb_get_letohl( tvb, 4 );
@@ -2909,15 +2959,15 @@ dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
break;
case LIST_SERVICES:
- dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, NULL, 24, 0 );
+ dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
break;
case LIST_IDENTITY:
- dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, NULL, 24, 0 );
+ dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
break;
case LIST_INTERFACES:
- dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, NULL, 24, 0 );
+ dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
break;
case REGISTER_SESSION:
@@ -2933,7 +2983,7 @@ dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
proto_tree_add_item( csftree, hf_enip_timeout, tvb, 28, 2, ENC_LITTLE_ENDIAN );
ifacehndl = tvb_get_letohl( tvb, 24 );
- dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, NULL, 30, ifacehndl );
+ dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 30, ifacehndl );
break;
case SEND_UNIT_DATA:
@@ -2941,7 +2991,7 @@ dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
proto_tree_add_item( csftree, hf_enip_timeout, tvb, 28, 2, ENC_LITTLE_ENDIAN );
ifacehndl = tvb_get_letohl( tvb, 24 );
- dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, ti, 30, ifacehndl );
+ dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, ti, 30, ifacehndl );
break;
@@ -3004,10 +3054,10 @@ dissect_cipio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U
enip_tree = proto_item_add_subtree(ti, ett_enip);
- dissect_cpf( NULL, 0xFFFF, tvb, pinfo, enip_tree, tree, NULL, 0, 0 );
+ dissect_cpf( NULL, 0xFFFF, tvb, pinfo, enip_tree, tree, enip_tree, NULL, 0, 0 );
return tvb_captured_length(tvb);
-} /* end of dissect_enipio() */
+}
static gboolean
@@ -3152,7 +3202,7 @@ dissect_dlr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
static int dissect_cip_class1(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
{
- enip_conn_val_t conn_info;
+ enip_conn_val_t conn_info = {0};
conn_info.TransportClass_trigger = 1;
cip_io_data_input io_data_input;
@@ -3492,6 +3542,9 @@ proto_register_enip(void)
{ "Forward Open Request In", "enip.fwd_open_in",
FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
+ // Generated API data.
+ { &hf_cip_cm_ot_api, { "O->T API", "cip.cm.otapi", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_cip_cm_to_api, { "T->O API", "cip.cm.toapi", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
{ &hf_cip_io_data,
{ "Data", "cipio.data",
FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0x0,
@@ -4291,7 +4344,9 @@ proto_register_enip(void)
&ett_eip_cert_capability_flags,
&ett_eip_cert_num_certs,
&ett_security_profiles,
- &ett_iana_port_state_flags
+ &ett_iana_port_state_flags,
+ &ett_connection_info,
+ &ett_connection_path_info
};
static ei_register_info ei[] = {
@@ -4555,7 +4610,6 @@ proto_register_enip(void)
enip_tcp_handle = register_dissector("enip", dissect_enip_tcp, proto_enip);
cipio_handle = register_dissector("cipio", dissect_cipio, proto_cipio);
cip_class1_handle = register_dissector("cipio_class1", dissect_cip_class1, proto_cip_class1);
-
cip_io_generic_handle = register_dissector("cipgenericio", dissect_cip_io_generic, proto_cipio);
/* Required function calls to register the header fields and subtrees used */
diff --git a/epan/dissectors/packet-enip.h b/epan/dissectors/packet-enip.h
index 7808b614c4..3a2fc439af 100644
--- a/epan/dissectors/packet-enip.h
+++ b/epan/dissectors/packet-enip.h
@@ -103,6 +103,11 @@ typedef struct enip_conn_val {
cip_safety_epath_info_t safety;
guint32 ClassID;
guint32 ConnPoint;
+
+ guint32 FwdOpenPathLenBytes;
+ void *pFwdOpenPathData;
+ guint32 O2Tapi;
+ guint32 T2Oapi;
} enip_conn_val_t;
enum enip_connid_type {ECIDT_UNKNOWN, ECIDT_O2T, ECIDT_T2O};