CIP: Use a struct for connection triad
authorDylan Ulis <daulis0@gmail.com>
Thu, 31 May 2018 11:24:26 +0000 (07:24 -0400)
committerAnders Broman <a.broman58@gmail.com>
Fri, 1 Jun 2018 05:53:13 +0000 (05:53 +0000)
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>
epan/dissectors/packet-cip.c
epan/dissectors/packet-cip.h
epan/dissectors/packet-cipsafety.c
epan/dissectors/packet-enip.c
epan/dissectors/packet-enip.h

index ae5a517733835f6692e8afdcdb45c12db3c5dc56..9e2c603c0a076fb3018a78bbc412f38d5ee1dfe6 100644 (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;
index b22b70cf4b3ba2d923c2ed0c8e363891c2e9ab5c..9009a3fb54af5edb198593b3d0173431410627e2 100644 (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;
index 02d0ea93ce64af215c5909fdd86bdf151946c7b5..bcf76231e8d22944f6d93eda5a353666b571fa18 100644 (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);
index bd760570d12e7854f5d51bbaaa827aea6e9b824a..ec0b987335ebb10cadb9c6455e24e000acde3239 100644 (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;
 
index 19a4ad7c58ee5bad349579f9c228853048c9d46e..cc129c3ef6000f0b514326c61756053b202a4782 100644 (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];