diff --git a/epan/dissectors/packet-cip.c b/epan/dissectors/packet-cip.c index ae5a517733..9e2c603c0a 100644 --- a/epan/dissectors/packet-cip.c +++ b/epan/dissectors/packet-cip.c @@ -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 * Joakim Wiberg @@ -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; diff --git a/epan/dissectors/packet-cip.h b/epan/dissectors/packet-cip.h index b22b70cf4b..9009a3fb54 100644 --- a/epan/dissectors/packet-cip.h +++ b/epan/dissectors/packet-cip.h @@ -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; diff --git a/epan/dissectors/packet-cipsafety.c b/epan/dissectors/packet-cipsafety.c index 02d0ea93ce..bcf76231e8 100644 --- a/epan/dissectors/packet-cipsafety.c +++ b/epan/dissectors/packet-cipsafety.c @@ -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); diff --git a/epan/dissectors/packet-enip.c b/epan/dissectors/packet-enip.c index bd760570d1..ec0b987335 100644 --- a/epan/dissectors/packet-enip.c +++ b/epan/dissectors/packet-enip.c @@ -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; diff --git a/epan/dissectors/packet-enip.h b/epan/dissectors/packet-enip.h index 19a4ad7c58..cc129c3ef6 100644 --- a/epan/dissectors/packet-enip.h +++ b/epan/dissectors/packet-enip.h @@ -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];