CIP: Use a struct for connection triad

1. Connection Serial Number, Vendor ID, and Device Serial Number are always
used as a group. Group these as a struct to make them easier to manage.
2. Pull out common code into dissect_connection_triad()

No functional changes.

Change-Id: Ide126f8d0ea6ab8e2de5abf20e12643d5a35924d
Reviewed-on: https://code.wireshark.org/review/27926
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Dylan Ulis 2018-05-31 07:24:26 -04:00 committed by Anders Broman
parent a7c244e4f1
commit c9ba7c95df
5 changed files with 132 additions and 144 deletions

View File

@ -2,6 +2,10 @@
* Routines for Common Industrial Protocol (CIP) dissection
* CIP Home: www.odva.org
*
* This dissector includes items from:
* CIP Volume 1: Common Industrial Protocol
* CIP Volume 5: CIP Safety
*
* Copyright 2004
* Magnus Hansson <mah@hms.se>
* Joakim Wiberg <jow@hms.se>
@ -6278,14 +6282,33 @@ dissect_cip_cm_timeout(proto_tree *cmd_tree, tvbuff_t *tvb, int offset)
proto_tree_add_uint(cmd_tree, hf_cip_cm_timeout, tvb, offset, 2, timeout);
}
static void dissect_connection_triad(tvbuff_t *tvb, int offset, proto_tree *tree,
int hf_conn_serial, int hf_vendor, int hf_orig_serial,
cip_connection_triad_t *triad)
{
guint32 ConnSerialNumber;
guint32 VendorID;
guint32 DeviceSerialNumber;
proto_tree_add_item_ret_uint(tree, hf_conn_serial, tvb, offset, 2, ENC_LITTLE_ENDIAN, &ConnSerialNumber);
proto_tree_add_item_ret_uint(tree, hf_vendor, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN, &VendorID);
proto_tree_add_item_ret_uint(tree, hf_orig_serial, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &DeviceSerialNumber);
if (triad)
{
triad->ConnSerialNumber = ConnSerialNumber;
triad->VendorID = VendorID;
triad->DeviceSerialNumber = DeviceSerialNumber;
}
}
static void
dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvbuff_t *tvb, int offset, gboolean large_fwd_open, packet_info *pinfo)
{
proto_item *pi;
proto_tree *epath_tree;
int conn_path_size, rpi, net_param_offset = 0;
guint32 O2TConnID, T2OConnID, DeviceSerialNumber;
guint16 ConnSerialNumber, VendorID;
guint32 O2TConnID, T2OConnID;
guint8 TransportClass_trigger, O2TType, T2OType;
cip_simple_request_info_t connection_path;
cip_safety_epath_info_t safety_fwdopen;
@ -6296,12 +6319,11 @@ dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvb
proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_ot_connid, tvb, offset+2, 4, ENC_LITTLE_ENDIAN, &O2TConnID);
proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_to_connid, tvb, offset+6, 4, ENC_LITTLE_ENDIAN, &T2OConnID);
ConnSerialNumber = tvb_get_letohs( tvb, offset+10 );
proto_tree_add_item( cmd_tree, hf_cip_cm_conn_serial_num, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
VendorID = tvb_get_letohs( tvb, offset+12 );
proto_tree_add_item( cmd_tree, hf_cip_cm_vendor, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
cip_connection_triad_t conn_triad;
dissect_connection_triad(tvb, offset + 10, cmd_tree,
hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
&conn_triad);
proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_orig_serial_num, tvb, offset+14, 4, ENC_LITTLE_ENDIAN, &DeviceSerialNumber);
proto_tree_add_item( cmd_tree, hf_cip_cm_timeout_multiplier, tvb, offset+18, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item( cmd_tree, hf_cip_reserved24, tvb, offset+19, 3, ENC_LITTLE_ENDIAN);
@ -6369,7 +6391,7 @@ dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvb
{
/* "Connection" is created during ForwardOpen reply (which will be after ForwardOpen request),
so ForwardOpen request can only be marked after the first pass */
enip_mark_connection_triad(pinfo, ConnSerialNumber, VendorID, DeviceSerialNumber);
enip_mark_connection_triad(pinfo, &conn_triad);
}
else
{
@ -6378,9 +6400,7 @@ dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvb
DISSECTOR_ASSERT(preq_info->connInfo == NULL);
preq_info->connInfo = wmem_new0(wmem_file_scope(), cip_conn_info_t);
preq_info->connInfo->ConnSerialNumber = ConnSerialNumber;
preq_info->connInfo->VendorID = VendorID;
preq_info->connInfo->DeviceSerialNumber = DeviceSerialNumber;
preq_info->connInfo->triad = conn_triad;
preq_info->connInfo->forward_open_frame = pinfo->num;
preq_info->connInfo->O2T.connID = O2TConnID;
preq_info->connInfo->T2O.connID = T2OConnID;
@ -6400,10 +6420,11 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
{
int temp_data;
unsigned char app_rep_size;
guint32 O2TConnID, T2OConnID, DeviceSerialNumber, target_device_sn = 0;
guint16 ConnSerialNumber, VendorID, init_rollover_value = 0, init_timestamp_value = 0,
target_conn_sn = 0, target_vendorID = 0;
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));
/* Display originator to target connection ID */
O2TConnID = tvb_get_letohl( tvb, offset );
@ -6413,17 +6434,10 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
T2OConnID = tvb_get_letohl( tvb, offset+4 );
proto_tree_add_item( tree, hf_cip_cm_to_connid, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
/* Display connection serial number */
ConnSerialNumber = tvb_get_letohs( tvb, offset+8 );
proto_tree_add_item( tree, hf_cip_cm_conn_serial_num, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
/* Display the originator vendor id */
VendorID = tvb_get_letohs( tvb, offset+10 );
proto_tree_add_item( tree, hf_cip_cm_vendor, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
/* Display the originator serial number */
DeviceSerialNumber = tvb_get_letohl( tvb, offset+12 );
proto_tree_add_item( tree, hf_cip_cm_orig_serial_num, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
cip_connection_triad_t conn_triad;
dissect_connection_triad(tvb, offset + 8, tree,
hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
&conn_triad);
/* Display originator to target actual packet interval */
temp_data = tvb_get_letohl( tvb, offset+16 );
@ -6452,10 +6466,12 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
proto_tree_add_item( safety_tree, hf_cip_cm_consumer_number, tvb, offset+26, 2, ENC_LITTLE_ENDIAN);
pid_tree = proto_tree_add_subtree( safety_tree, tvb, offset+28, 8, ett_cip_cm_pid, NULL, "PID/CID");
proto_tree_add_item( pid_tree, hf_cip_cm_targ_vendor_id, tvb, offset+28, 2, ENC_LITTLE_ENDIAN);
target_vendorID = tvb_get_letohs(tvb, offset+28);
proto_tree_add_item_ret_uint( pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset+30, 4, ENC_LITTLE_ENDIAN, &target_device_sn);
target_triad.VendorID = tvb_get_letohs(tvb, offset+28);
proto_tree_add_item_ret_uint( pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset+30, 4, ENC_LITTLE_ENDIAN, &target_triad.DeviceSerialNumber);
proto_tree_add_item( pid_tree, hf_cip_cm_targ_conn_serial_num, tvb, offset+34, 2, ENC_LITTLE_ENDIAN);
target_conn_sn = tvb_get_letohs(tvb, offset+34);
target_triad.ConnSerialNumber = tvb_get_letohs(tvb, offset+34);
if (app_rep_size > 10)
proto_tree_add_item(tree, hf_cip_cm_app_reply_data, tvb, offset+36, app_rep_size-10, ENC_NA );
@ -6466,10 +6482,12 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
proto_tree_add_item( safety_tree, hf_cip_cm_consumer_number, tvb, offset+26, 2, ENC_LITTLE_ENDIAN);
pid_tree = proto_tree_add_subtree( safety_tree, tvb, offset+28, 12, ett_cip_cm_pid, NULL, "PID/CID");
proto_tree_add_item( pid_tree, hf_cip_cm_targ_vendor_id, tvb, offset+28, 2, ENC_LITTLE_ENDIAN);
target_vendorID = tvb_get_letohs(tvb, offset+28);
proto_tree_add_item_ret_uint( pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset+30, 4, ENC_LITTLE_ENDIAN, &target_device_sn);
target_triad.VendorID = tvb_get_letohs(tvb, offset+28);
proto_tree_add_item_ret_uint( pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset+30, 4, ENC_LITTLE_ENDIAN, &target_triad.DeviceSerialNumber);
proto_tree_add_item( pid_tree, hf_cip_cm_targ_conn_serial_num, tvb, offset+34, 2, ENC_LITTLE_ENDIAN);
target_conn_sn = tvb_get_letohs(tvb, offset+34);
target_triad.ConnSerialNumber = tvb_get_letohs(tvb, offset+34);
proto_tree_add_item( pid_tree, hf_cip_cm_initial_timestamp, tvb, offset+36, 2, ENC_LITTLE_ENDIAN);
init_timestamp_value = tvb_get_letohs(tvb, offset+36);
@ -6489,9 +6507,9 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
if ((preq_info != NULL) && (preq_info->connInfo != NULL))
{
/* Ensure the connection triad matches before updating the connection IDs */
if ((preq_info->connInfo->ConnSerialNumber == ConnSerialNumber) &&
(preq_info->connInfo->VendorID == VendorID) &&
(preq_info->connInfo->DeviceSerialNumber == DeviceSerialNumber))
if ((preq_info->connInfo->triad.ConnSerialNumber == conn_triad.ConnSerialNumber) &&
(preq_info->connInfo->triad.VendorID == conn_triad.VendorID) &&
(preq_info->connInfo->triad.DeviceSerialNumber == conn_triad.DeviceSerialNumber))
{
/* Update the connection IDs as ForwardOpen reply is allowed to update them from
the ForwardOpen request */
@ -6501,9 +6519,7 @@ dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree,
{
preq_info->connInfo->safety.running_rollover_value = init_rollover_value;
preq_info->connInfo->safety.running_timestamp_value = init_timestamp_value;
preq_info->connInfo->safety.target_conn_sn = target_conn_sn;
preq_info->connInfo->safety.target_vendorID = target_vendorID;
preq_info->connInfo->safety.target_device_sn = target_device_sn;
preq_info->connInfo->safety.target_triad = target_triad;
}
}
}
@ -6550,8 +6566,6 @@ dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_
int i, msg_req_siz;
cip_req_info_t *preq_info;
cip_req_info_t *pembedded_req_info;
guint16 ConnSerialNumber, VendorID;
guint32 DeviceSerialNumber;
service = tvb_get_guint8( tvb, offset );
@ -6730,18 +6744,10 @@ dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_
case SC_CM_FWD_CLOSE:
{
/* Forward close response (Success) */
/* Display connection serial number */
ConnSerialNumber = tvb_get_letohs( tvb, offset+4+add_stat_size );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_conn_serial_num, tvb, offset+4+add_stat_size, 2, ENC_LITTLE_ENDIAN);
/* Display the originator vendor id */
VendorID = tvb_get_letohs( tvb, offset+4+add_stat_size+2 );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_vendor, tvb, offset+4+add_stat_size+2, 2, ENC_LITTLE_ENDIAN);
/* Display the originator serial number */
DeviceSerialNumber = tvb_get_letohl( tvb, offset+4+add_stat_size+4 );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_orig_serial_num, tvb, offset+4+add_stat_size+4, 4, ENC_LITTLE_ENDIAN);
cip_connection_triad_t conn_triad;
dissect_connection_triad(tvb, offset + 4 + add_stat_size, cmd_data_tree,
hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
&conn_triad);
/* Display the application reply size */
app_rep_size = tvb_get_guint8( tvb, offset+4+add_stat_size+8 ) * 2;
@ -6759,7 +6765,7 @@ dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_
proto_tree_add_item(cmd_data_tree, hf_cip_cm_app_reply_data, tvb, offset+4+add_stat_size+10,app_rep_size, ENC_NA);
}
enip_close_cip_connection( pinfo, ConnSerialNumber, VendorID, DeviceSerialNumber );
enip_close_cip_connection( pinfo, &conn_triad);
} /* End of if forward close response */
break;
@ -6778,9 +6784,10 @@ dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_
proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_coo_conn, tvb, offset+4+add_stat_size+1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_roo_conn, tvb, offset+4+add_stat_size+2, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_last_action, tvb, offset+4+add_stat_size+3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_conn_serial_num, tvb, offset+4+add_stat_size+4, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_vendor, tvb, offset+4+add_stat_size+6, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_orig_serial_num, tvb, offset+4+add_stat_size+8, 4, ENC_LITTLE_ENDIAN);
dissect_connection_triad(tvb, offset + 4 + add_stat_size + 4, cmd_data_tree,
hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
NULL);
}
break;
default:
@ -6797,26 +6804,26 @@ dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_
case SC_CM_FWD_OPEN:
case SC_CM_LARGE_FWD_OPEN:
case SC_CM_FWD_CLOSE:
{
/* Forward open and forward close error response look the same */
ConnSerialNumber = tvb_get_letohs( tvb, offset+4+add_stat_size );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_conn_serial_num, tvb, offset+4+add_stat_size, 2, ENC_LITTLE_ENDIAN);
VendorID = tvb_get_letohs( tvb, offset+4+add_stat_size+2 );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_vendor, tvb, offset+4+add_stat_size+2, 2, ENC_LITTLE_ENDIAN);
DeviceSerialNumber = tvb_get_letohl( tvb, offset+4+add_stat_size+4 );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_orig_serial_num, tvb, offset+4+add_stat_size+4, 4, ENC_LITTLE_ENDIAN);
cip_connection_triad_t conn_triad;
dissect_connection_triad(tvb, offset + 4 + add_stat_size, cmd_data_tree,
hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
&conn_triad);
proto_tree_add_item(cmd_data_tree, hf_cip_cm_remain_path_size, tvb, offset+4+add_stat_size+8, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+4+add_stat_size+9, 1, ENC_LITTLE_ENDIAN);
/* With an error reply the connection will either never be established or it has since already closed
That means the conversation should end too */
enip_close_cip_connection(pinfo, ConnSerialNumber, VendorID, DeviceSerialNumber);
enip_close_cip_connection(pinfo, &conn_triad);
if (preq_info != NULL)
{
/* Remove any connection information */
preq_info->connInfo = NULL;
}
break;
}
case SC_CM_UNCON_SEND:
/* Unconnected send response (Unsuccess) */
proto_tree_add_item(cmd_data_tree, hf_cip_cm_remain_path_size, tvb, offset+4+add_stat_size, 1, ENC_LITTLE_ENDIAN);
@ -6862,15 +6869,14 @@ dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_
/* Forward Close Request */
dissect_cip_cm_timeout( cmd_data_tree, tvb, offset+2+req_path_size);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_conn_serial_num, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
ConnSerialNumber = tvb_get_letohs( tvb, offset+2+req_path_size+2);
proto_tree_add_item( cmd_data_tree, hf_cip_cm_vendor, tvb, offset+2+req_path_size+4, 2, ENC_LITTLE_ENDIAN);
VendorID = tvb_get_letohs( tvb, offset+2+req_path_size+4 );
proto_tree_add_item( cmd_data_tree, hf_cip_cm_orig_serial_num, tvb, offset+2+req_path_size+6, 4, ENC_LITTLE_ENDIAN);
DeviceSerialNumber = tvb_get_letohl( tvb, offset+2+req_path_size+6 );
cip_connection_triad_t conn_triad;
dissect_connection_triad(tvb, offset + 2 + req_path_size + 2, cmd_data_tree,
hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
&conn_triad);
if (!pinfo->fd->flags.visited)
enip_mark_connection_triad(pinfo, ConnSerialNumber, VendorID, DeviceSerialNumber);
enip_mark_connection_triad(pinfo, &conn_triad);
/* Add the path size */
conn_path_size = tvb_get_guint8( tvb, offset+2+req_path_size+10 )*2;

View File

@ -461,20 +461,22 @@ typedef struct cip_connID_info {
enum cip_safety_format_type {CIP_SAFETY_BASE_FORMAT, CIP_SAFETY_EXTENDED_FORMAT};
typedef struct cip_connection_triad {
guint16 ConnSerialNumber;
guint16 VendorID;
guint32 DeviceSerialNumber;
} cip_connection_triad_t;
typedef struct cip_safety_epath_info {
gboolean safety_seg;
enum cip_safety_format_type format;
guint16 running_rollover_value; /* Keep track of the rollover value over the course of the connection */
guint16 running_timestamp_value; /* Keep track of the timestamp value over the course of the connection */
guint16 target_conn_sn;
guint16 target_vendorID;
guint32 target_device_sn;
cip_connection_triad_t target_triad;
} cip_safety_epath_info_t;
typedef struct cip_conn_info {
guint16 ConnSerialNumber;
guint16 VendorID;
guint32 DeviceSerialNumber;
cip_connection_triad_t triad;
guint32 forward_open_frame;
cip_connID_info_t O2T;
cip_connID_info_t T2O;

View File

@ -1255,12 +1255,12 @@ dissect_class_svalidator_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
* CRC handling
*
************************************************/
static guint8 compute_crc_s1_pid(guint16 conn_serial_number, guint16 vendor_id, guint32 device_serial_number)
static guint8 compute_crc_s1_pid(const cip_connection_triad_t* triad)
{
guint8 temp_buf[8];
memcpy(temp_buf, &vendor_id, 2);
memcpy(&temp_buf[2], &device_serial_number, 4);
memcpy(&temp_buf[6], &conn_serial_number, 2);
memcpy(temp_buf, &triad->VendorID, 2);
memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
return crc8_0x37(temp_buf, 8, 0);
}
@ -1291,12 +1291,12 @@ static guint8 compute_crc_s2_data(guint8 pid_seed, guint8 mode_byte_mask, guint8
return crc8_0x3B(comp_buf, len, mode_byte_crc);
}
static guint16 compute_crc_s3_pid(guint16 conn_serial_number, guint16 vendor_id, guint32 device_serial_number)
static guint16 compute_crc_s3_pid(const cip_connection_triad_t* triad)
{
guint8 temp_buf[8];
memcpy(temp_buf, &vendor_id, 2);
memcpy(&temp_buf[2], &device_serial_number, 4);
memcpy(&temp_buf[6], &conn_serial_number, 2);
memcpy(temp_buf, &triad->VendorID, 2);
memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
return crc16_0x080F_seed(temp_buf, 8, 0);
}
@ -1326,12 +1326,12 @@ static guint16 compute_crc_s3_time(guint16 pid_seed, guint8 ack_mcast_byte, guin
return timestamp_crc;
}
static guint32 compute_crc_s5_pid(guint16 conn_serial_number, guint16 vendor_id, guint32 device_serial_number)
static guint32 compute_crc_s5_pid(const cip_connection_triad_t* triad)
{
guint8 temp_buf[8];
memcpy(temp_buf, &vendor_id, 2);
memcpy(&temp_buf[2], &device_serial_number, 4);
memcpy(&temp_buf[6], &conn_serial_number, 2);
memcpy(temp_buf, &triad->VendorID, 2);
memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
return crc32_0x5D6DCB_seed(temp_buf, 8, 0);
}
@ -1470,14 +1470,15 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
gboolean server_dir = FALSE;
enum enip_connid_type conn_type = ECIDT_UNKNOWN;
enum cip_safety_format_type format = CIP_SAFETY_BASE_FORMAT;
guint16 timestamp, conn_sn = 0, vendorID = 0;
guint16 timestamp;
guint8 mode_byte;
guint32 device_sn = 0;
cip_safety_packet_data_t* packet_data = NULL;
guint32 test_crc_c5, value_c5 = 0, tmp_c5;
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));
/* Make entries in Protocol column and Info column on summary display */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Safety");
@ -1505,15 +1506,11 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
if ((conn_type == ECIDT_O2T) && (server_dir == FALSE))
{
conn_sn = safety_info->eip_conn_info->ConnSerialNumber;
vendorID = safety_info->eip_conn_info->VendorID;
device_sn = safety_info->eip_conn_info->DeviceSerialNumber;
connection_triad = safety_info->eip_conn_info->triad;
}
else
{
conn_sn = safety_info->eip_conn_info->safety.target_conn_sn;
vendorID = safety_info->eip_conn_info->safety.target_vendorID;
device_sn = safety_info->eip_conn_info->safety.target_device_sn;
connection_triad = safety_info->eip_conn_info->safety.target_triad;
}
}
@ -1530,7 +1527,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, 4,
hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
compute_crc_s3_time(compute_crc_s3_pid(conn_sn, vendorID, device_sn),
compute_crc_s3_time(compute_crc_s3_pid(&connection_triad),
tvb_get_guint8(tvb, 0), /* ack byte */
timestamp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
@ -1550,7 +1547,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
/* CRC-S5 doesn't use proto_tree_add_checksum because the checksum is broken up into multiple fields */
if (compute_crc)
{
test_crc_c5 = compute_crc_s5_time(compute_crc_s5_pid(conn_sn, vendorID, device_sn),
test_crc_c5 = compute_crc_s5_time(compute_crc_s5_pid(&connection_triad),
tvb_get_guint8(tvb, 0), /* ack byte */
timestamp);
@ -1589,15 +1586,11 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
if ((conn_type == ECIDT_O2T) && (server_dir == TRUE))
{
conn_sn = safety_info->eip_conn_info->ConnSerialNumber;
vendorID = safety_info->eip_conn_info->VendorID;
device_sn = safety_info->eip_conn_info->DeviceSerialNumber;
connection_triad = safety_info->eip_conn_info->triad;
}
else
{
conn_sn = safety_info->eip_conn_info->safety.target_conn_sn;
vendorID = safety_info->eip_conn_info->safety.target_vendorID;
device_sn = safety_info->eip_conn_info->safety.target_device_sn;
connection_triad = safety_info->eip_conn_info->safety.target_triad;
}
}
@ -1621,14 +1614,14 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, io_data_size+1,
hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
compute_crc_s1_data(compute_crc_s1_pid(conn_sn, vendorID, device_sn),
compute_crc_s1_data(compute_crc_s1_pid(&connection_triad),
(mode_byte & MODE_BYTE_CRC_S1_MASK),
tvb_get_ptr(tvb, 0, io_data_size), io_data_size),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
proto_tree_add_checksum(tree, tvb, io_data_size+2,
hf_cipsafety_crc_s2, hf_cipsafety_crc_s2_status, &ei_cipsafety_crc_s2, pinfo,
compute_crc_s2_data(compute_crc_s1_pid(conn_sn, vendorID, device_sn),
compute_crc_s2_data(compute_crc_s1_pid(&connection_triad),
((mode_byte ^ 0xFF) & MODE_BYTE_CRC_S1_MASK),
/* I/O data is duplicated because it will be complemented inline */
(guint8*)tvb_memdup(wmem_packet_scope(), tvb, 0, io_data_size), io_data_size),
@ -1649,7 +1642,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, io_data_size+5,
hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
compute_crc_s1_timestamp(compute_crc_s1_pid(conn_sn, vendorID, device_sn),
compute_crc_s1_timestamp(compute_crc_s1_pid(&connection_triad),
(mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
timestamp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
@ -1689,7 +1682,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, io_data_size+1,
hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
compute_crc_s3_base_data(compute_crc_s3_pid(conn_sn, vendorID, device_sn),
compute_crc_s3_base_data(compute_crc_s3_pid(&connection_triad),
mode_byte & MODE_BYTE_CRC_S3_MASK, tvb_get_ptr(tvb, 0, io_data_size), io_data_size),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
@ -1708,7 +1701,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, (io_data_size*2)+3,
hf_cipsafety_complement_crc_s3, hf_cipsafety_complement_crc_s3_status, &ei_cipsafety_complement_crc_s3, pinfo,
compute_crc_s3_base_data(compute_crc_s3_pid(conn_sn, vendorID, device_sn),
compute_crc_s3_base_data(compute_crc_s3_pid(&connection_triad),
((mode_byte ^ 0xFF) & MODE_BYTE_CRC_S3_MASK),
tvb_get_ptr(tvb, io_data_size+3, io_data_size), io_data_size),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
@ -1725,7 +1718,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, (io_data_size*2)+7,
hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
compute_crc_s1_timestamp(compute_crc_s1_pid(conn_sn, vendorID, device_sn),
compute_crc_s1_timestamp(compute_crc_s1_pid(&connection_triad),
(mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
timestamp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
@ -1797,7 +1790,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
/* CRC-S5 doesn't use proto_tree_add_checksum because the checksum is broken up in non-consecutive bytes */
if (compute_crc && (packet_data != NULL))
{
test_crc_c5 = compute_crc_s5_short_data(compute_crc_s5_pid(conn_sn, vendorID, device_sn),
test_crc_c5 = compute_crc_s5_short_data(compute_crc_s5_pid(&connection_triad),
((timestamp != 0) ? packet_data->rollover_value : 0), mode_byte & MODE_BYTE_CRC_S5_BASE_MASK, timestamp,
tvb_get_ptr(tvb, 0, io_data_size), io_data_size);
@ -1875,7 +1868,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
{
proto_tree_add_checksum(tree, tvb, io_data_size+1,
hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
compute_crc_s3_extended_data(compute_crc_s3_pid(conn_sn, vendorID, device_sn),
compute_crc_s3_extended_data(compute_crc_s3_pid(&connection_triad),
((timestamp != 0) ? packet_data->rollover_value : 0), mode_byte & MODE_BYTE_CRC_S3_MASK, tvb_get_ptr(tvb, 0, io_data_size), io_data_size),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
@ -1898,7 +1891,7 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
/* CRC-S5 doesn't use proto_tree_add_checksum because the checksum is broken up in non-consecutive bytes */
if (compute_crc && (packet_data != NULL))
{
test_crc_c5 = compute_crc_s5_long_data(compute_crc_s5_pid(conn_sn, vendorID, device_sn),
test_crc_c5 = compute_crc_s5_long_data(compute_crc_s5_pid(&connection_triad),
((timestamp != 0) ? packet_data->rollover_value : 0), mode_byte & MODE_BYTE_CRC_S5_EXTENDED_MASK, timestamp,
/* I/O data is duplicated because it will be complemented inline */
(guint8*)tvb_memdup(wmem_packet_scope(), tvb, 0, io_data_size), io_data_size);

View File

@ -894,9 +894,7 @@ enip_match_request( packet_info *pinfo, proto_tree *tree, enip_request_key_t *pr
}
typedef struct enip_conn_key {
guint16 ConnSerialNumber;
guint16 VendorID;
guint32 DeviceSerialNumber;
cip_connection_triad_t triad;
guint32 O2TConnID;
guint32 T2OConnID;
} enip_conn_key_t;
@ -938,7 +936,7 @@ enip_io_conv_filter(packet_info *pinfo)
"((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
conn->open_frame, conn->open_reply_frame, conn->close_frame,
conn->O2TConnID, conn->T2OConnID,
conn->ConnSerialNumber, conn->VendorID, conn->DeviceSerialNumber);
conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
}
else
{
@ -949,7 +947,7 @@ enip_io_conv_filter(packet_info *pinfo)
"((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
conn->open_frame, conn->open_reply_frame,
conn->O2TConnID, conn->T2OConnID,
conn->ConnSerialNumber, conn->VendorID, conn->DeviceSerialNumber);
conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
}
return buf;
@ -984,7 +982,7 @@ enip_exp_conv_filter(packet_info *pinfo)
"((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
conn->open_frame, conn->open_reply_frame, conn->close_frame,
conn->O2TConnID, conn->T2OConnID,
conn->ConnSerialNumber, conn->VendorID, conn->DeviceSerialNumber);
conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
}
else
{
@ -995,7 +993,7 @@ enip_exp_conv_filter(packet_info *pinfo)
"((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
conn->open_frame, conn->open_reply_frame,
conn->O2TConnID, conn->T2OConnID,
conn->ConnSerialNumber, conn->VendorID, conn->DeviceSerialNumber);
conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
}
return buf;
}
@ -1012,9 +1010,9 @@ enip_conn_equal(gconstpointer v, gconstpointer w)
const enip_conn_key_t *v1 = (const enip_conn_key_t *)v;
const enip_conn_key_t *v2 = (const enip_conn_key_t *)w;
if ((v1->ConnSerialNumber == v2->ConnSerialNumber) &&
(v1->VendorID == v2->VendorID) &&
(v1->DeviceSerialNumber == v2->DeviceSerialNumber) &&
if ((v1->triad.ConnSerialNumber == v2->triad.ConnSerialNumber) &&
(v1->triad.VendorID == v2->triad.VendorID) &&
(v1->triad.DeviceSerialNumber == v2->triad.DeviceSerialNumber) &&
((v1->O2TConnID == 0) || (v2->O2TConnID == 0) || (v1->O2TConnID == v2->O2TConnID)) &&
((v1->T2OConnID == 0) || (v2->T2OConnID == 0) || (v1->T2OConnID == v2->T2OConnID)))
return 1;
@ -1028,7 +1026,7 @@ enip_conn_hash (gconstpointer v)
const enip_conn_key_t *key = (const enip_conn_key_t *)v;
guint val;
val = (guint)( key->ConnSerialNumber + key->VendorID + key->DeviceSerialNumber );
val = (guint)( key->triad.ConnSerialNumber + key->triad.VendorID + key->triad.DeviceSerialNumber );
return val;
}
@ -1053,9 +1051,7 @@ enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
}
conn_key = wmem_new(wmem_file_scope(), enip_conn_key_t);
conn_key->ConnSerialNumber = connInfo->ConnSerialNumber;
conn_key->VendorID = connInfo->VendorID;
conn_key->DeviceSerialNumber = connInfo->DeviceSerialNumber;
conn_key->triad = connInfo->triad;
conn_key->O2TConnID = connInfo->O2T.connID;
conn_key->T2OConnID = connInfo->T2O.connID;
@ -1064,9 +1060,7 @@ enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
{
conn_val = wmem_new(wmem_file_scope(), enip_conn_val_t);
conn_val->ConnSerialNumber = connInfo->ConnSerialNumber;
conn_val->VendorID = connInfo->VendorID;
conn_val->DeviceSerialNumber = connInfo->DeviceSerialNumber;
conn_val->triad = connInfo->triad;
conn_val->O2TConnID = connInfo->O2T.connID;
conn_val->T2OConnID = connInfo->T2O.connID;
conn_val->TransportClass_trigger = connInfo->TransportClass_trigger;
@ -1188,8 +1182,7 @@ enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
}
void
enip_close_cip_connection(packet_info *pinfo, guint16 ConnSerialNumber,
guint16 VendorID, guint32 DeviceSerialNumber )
enip_close_cip_connection(packet_info *pinfo, const cip_connection_triad_t* triad)
{
enip_conn_key_t conn_key;
enip_conn_val_t *conn_val;
@ -1197,9 +1190,7 @@ enip_close_cip_connection(packet_info *pinfo, guint16 ConnSerialNumber,
if (pinfo->fd->flags.visited)
return;
conn_key.ConnSerialNumber = ConnSerialNumber;
conn_key.VendorID = VendorID;
conn_key.DeviceSerialNumber = DeviceSerialNumber;
conn_key.triad = *triad;
conn_key.O2TConnID = 0;
conn_key.T2OConnID = 0;
@ -1215,14 +1206,12 @@ enip_close_cip_connection(packet_info *pinfo, guint16 ConnSerialNumber,
}
/* Save the connection info for the conversation filter */
void enip_mark_connection_triad( packet_info *pinfo, guint16 ConnSerialNumber, guint16 VendorID, guint32 DeviceSerialNumber )
void enip_mark_connection_triad(packet_info *pinfo, const cip_connection_triad_t* triad)
{
enip_conn_key_t conn_key;
enip_conn_val_t *conn_val;
conn_key.ConnSerialNumber = ConnSerialNumber;
conn_key.VendorID = VendorID;
conn_key.DeviceSerialNumber = DeviceSerialNumber;
conn_key.triad = *triad;
conn_key.O2TConnID = 0;
conn_key.T2OConnID = 0;

View File

@ -92,9 +92,7 @@ typedef struct {
} enip_request_info_t;
typedef struct enip_conn_val {
guint16 ConnSerialNumber;
guint16 VendorID;
guint32 DeviceSerialNumber;
cip_connection_triad_t triad;
guint32 O2TConnID;
guint32 T2OConnID;
guint8 TransportClass_trigger;
@ -114,8 +112,8 @@ enum enip_connid_type {ECIDT_UNKNOWN, ECIDT_O2T, ECIDT_T2O};
#define ENIP_REQUEST_INFO 0
#define ENIP_CONNECTION_INFO 1
void enip_close_cip_connection( packet_info *pinfo, guint16 ConnSerialNumber, guint16 VendorID, guint32 DeviceSerialNumber );
void enip_mark_connection_triad( packet_info *pinfo, guint16 ConnSerialNumber, guint16 VendorID, guint32 DeviceSerialNumber );
void enip_close_cip_connection(packet_info *pinfo, const cip_connection_triad_t* triad);
void enip_mark_connection_triad(packet_info *pinfo, const cip_connection_triad_t* triad);
extern attribute_info_t enip_attribute_vals[99];