diff options
-rw-r--r-- | epan/dissectors/packet-cip.c | 30 | ||||
-rw-r--r-- | epan/dissectors/packet-cip.h | 5 | ||||
-rw-r--r-- | epan/dissectors/packet-cipmotion.c | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-cipsafety.c | 11 | ||||
-rw-r--r-- | epan/dissectors/packet-enip.c | 160 | ||||
-rw-r--r-- | epan/dissectors/packet-enip.h | 5 |
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}; |