CIP Safety: Minor Refactoring, Part 1

This commit is contained in:
Dylan Ulis 2022-04-13 20:48:41 +00:00 committed by A Wireshark GitLab Utility
parent 3c25b69ff6
commit 943c38d606
1 changed files with 111 additions and 87 deletions

View File

@ -4,7 +4,7 @@
*
* This dissector includes items from:
* CIP Volume 1: Common Industrial Protocol, Edition 3.24
* CIP Volume 5: CIP Safety, Edition 2.17
* CIP Volume 5: CIP Safety, Edition 2.22
*
* Copyright 2011
* Michael Mann <mmann@pyramidsolutions.com>
@ -1501,6 +1501,103 @@ dissect_mcast_byte( proto_tree *tree, tvbuff_t *tvb, int offset)
proto_tree_add_bitmask(tree, tvb, offset, hf_cipsafety_mcast_byte, ett_cipsafety_mcast_byte, bits, ENC_LITTLE_ENDIAN);
}
// Base Format Time Correction Message
static void dissect_base_format_time_correction_message(proto_tree* tree, tvbuff_t* tvb, int offset)
{
dissect_mcast_byte(tree, tvb, offset);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
// TODO: Validate CRC S3.
}
// Extended Format Time Correction Message
static void dissect_extended_format_time_correction_message(proto_tree* tree, tvbuff_t* tvb, int offset)
{
dissect_mcast_byte(tree, tvb, offset);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
// TODO: Validate CRC S5.
}
// Base Format, Time Stamp Section Format
static void dissect_base_format_time_stamp_section(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, int offset,
gboolean compute_crc, guint8 mode_byte, const cip_connection_triad_t* connection_triad)
{
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, offset, 2, ENC_LITTLE_ENDIAN);
guint16 timestamp = tvb_get_letohs(tvb, offset);
if (compute_crc)
{
guint8 computed_crc_s1 = compute_crc_s1_timestamp(compute_crc_s1_pid(connection_triad),
(mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
timestamp);
proto_tree_add_checksum(tree, tvb, offset + 2,
hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
computed_crc_s1, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
else
{
proto_tree_add_checksum(tree, tvb, offset + 2,
hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
}
// Base Format Time Coordination Message
// Note: All data starts from the beginning of the tvb buffer.
static void dissect_base_format_time_coordination_message(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb,
gboolean compute_crc, const cip_connection_triad_t* connection_triad)
{
dissect_ack_byte(tree, tvb, 0);
guint8 ack_byte = tvb_get_guint8(tvb, 0);
proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
guint16 timestamp = tvb_get_letohs(tvb, 1);
proto_tree_add_item(tree, hf_cipsafety_ack_byte2, tvb, 3, 1, ENC_LITTLE_ENDIAN);
if (compute_crc)
{
guint16 computed_crc_s3 = compute_crc_s3_time(compute_crc_s3_pid(connection_triad), ack_byte, timestamp);
proto_tree_add_checksum(tree, tvb, 4,
hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
computed_crc_s3, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
else
{
proto_tree_add_checksum(tree, tvb, 4,
hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
}
// Extended Format Time Coordination Message
// Note: All data starts from the beginning of the tvb buffer.
static void dissect_extended_format_time_coordination_message(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb,
gboolean compute_crc, const cip_connection_triad_t* connection_triad)
{
dissect_ack_byte(tree, tvb, 0);
guint8 ack_byte = tvb_get_guint8(tvb, 0);
proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
guint16 timestamp = tvb_get_letohs(tvb, 1);
guint32 crc_s5_0, crc_s5_1, crc_s5_2;
proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, 3, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, 4, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, 5, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
guint32 computed_crc_s5 = compute_crc_s5_time(compute_crc_s5_pid(connection_triad),
ack_byte,
timestamp);
validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
}
static void
dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int item_length, packet_info *pinfo, cip_safety_info_t* safety_info)
{
@ -1552,45 +1649,16 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
}
/* consumer data */
dissect_ack_byte(tree, tvb, 0);
proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
timestamp = tvb_get_letohs(tvb, 1);
switch (format)
{
case CIP_SAFETY_BASE_FORMAT:
proto_tree_add_item(tree, hf_cipsafety_ack_byte2, tvb, 3, 1, ENC_LITTLE_ENDIAN);
if (compute_crc)
{
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(&connection_triad),
tvb_get_guint8(tvb, 0), /* ack byte */
timestamp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
else
{
proto_tree_add_checksum(tree, tvb, 4,
hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
dissect_base_format_time_coordination_message(pinfo, tree, tvb, compute_crc, &connection_triad);
break;
case CIP_SAFETY_EXTENDED_FORMAT:
{
guint32 crc_s5_0, crc_s5_1, crc_s5_2;
proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, 3, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, 4, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, 5, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
guint32 computed_crc_s5 = compute_crc_s5_time(compute_crc_s5_pid(&connection_triad),
tvb_get_guint8(tvb, 0), /* ack byte */
timestamp);
validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
dissect_extended_format_time_coordination_message(pinfo, tree, tvb, compute_crc, &connection_triad);
break;
}
}
}
else if (((conn_type == ECIDT_O2T) && (server_dir == TRUE)) ||
((conn_type == ECIDT_T2O) && (server_dir == FALSE)))
@ -1649,35 +1717,16 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
hf_cipsafety_crc_s2, hf_cipsafety_crc_s2_status, &ei_cipsafety_crc_s2,
pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, io_data_size+3, 2, ENC_LITTLE_ENDIAN);
timestamp = tvb_get_letohs(tvb, io_data_size+3);
if (compute_crc)
{
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(&connection_triad),
(mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
timestamp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
else
{
proto_tree_add_checksum(tree, tvb, io_data_size+5,
hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
dissect_base_format_time_stamp_section(pinfo, tree, tvb, io_data_size + 3, compute_crc, mode_byte, &connection_triad);
if (multicast)
{
dissect_mcast_byte(tree, tvb, item_length-6);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, item_length-5, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, item_length-3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, item_length-2, 2, ENC_LITTLE_ENDIAN);
dissect_base_format_time_correction_message(tree, tvb, item_length - 6);
}
}
else
{
/* Long Format (3-250 bytes I/O data) */
/* 3 to 250 Byte Data section, Base Format */
if (item_length%2 == 1)
{
/* Malformed packet */
@ -1725,34 +1774,16 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
hf_cipsafety_complement_crc_s3, hf_cipsafety_complement_crc_s3_status, &ei_cipsafety_complement_crc_s3,
pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, (io_data_size*2)+5, 2, ENC_LITTLE_ENDIAN);
timestamp = tvb_get_letohs(tvb, (io_data_size*2)+5);
if (compute_crc)
{
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(&connection_triad),
(mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
timestamp),
ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
}
else
{
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, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
dissect_base_format_time_stamp_section(pinfo, tree, tvb, (io_data_size * 2) + 5, compute_crc, mode_byte, &connection_triad);
if (multicast)
{
dissect_mcast_byte(tree, tvb, (io_data_size*2)+5);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, (io_data_size*2)+6, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, (io_data_size*2)+8, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, (io_data_size*2)+9, 2, ENC_LITTLE_ENDIAN);
dissect_base_format_time_correction_message(tree, tvb, (io_data_size * 2) + 5);
}
}
break;
case CIP_SAFETY_EXTENDED_FORMAT:
{
if (short_format)
{
io_data_size = item_length-base_length;
@ -1815,16 +1846,12 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
if (multicast)
{
dissect_mcast_byte(tree, tvb, item_length-6);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, item_length-5, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, item_length-3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, item_length-2, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, item_length-1, 1, ENC_LITTLE_ENDIAN);
dissect_extended_format_time_correction_message(tree, tvb, item_length - 6);
}
}
else
{
/* Long Format (3-250 bytes I/O data) */
/* 3 to 250 Byte Data section, Extended Format */
if (item_length%2 == 1)
{
/* Malformed packet */
@ -1899,15 +1926,12 @@ dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int
if (multicast)
{
dissect_mcast_byte(tree, tvb, (io_data_size*2)+8);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, (io_data_size*2)+9, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, (io_data_size*2)+11, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, (io_data_size*2)+12, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, (io_data_size*2)+13, 1, ENC_LITTLE_ENDIAN);
dissect_extended_format_time_correction_message(tree, tvb, (io_data_size * 2) + 8);
}
}
break;
}
} // END case CIP_SAFETY_EXTENDED_FORMAT
} // END switch
}
else
{