Преглед изворни кода

Merge branch 'master' into CIPSecurity_develop

# Conflicts:
#	source/src/cip/cipconnectionmanager.c
#	source/src/ports/MINGW/sample_application/ethlinkcbs.c
#	source/src/ports/POSIX/sample_application/ethlinkcbs.c
#	source/src/ports/WIN32/sample_application/ethlinkcbs.c
micsat пре 2 година
родитељ
комит
2d487b3e13

+ 1 - 1
source/CMakeLists.txt

@@ -1,7 +1,7 @@
 #######################################
 # Required CMake version              #
 #######################################
-cmake_minimum_required( VERSION 3.3 )
+cmake_minimum_required( VERSION 3.18 )
 
 #######################################
 # Project name                        #

+ 1 - 1
source/src/cip/cipassembly.c

@@ -95,7 +95,7 @@ void ShutdownAssemblies(void) {
   }
 }
 
-CipInstance *CreateAssemblyObject(const EipUint32 instance_id,
+CipInstance *CreateAssemblyObject(const CipInstanceNum instance_id,
                                   EipByte *const data,
                                   const EipUint16 data_length) {
   CipClass *assembly_class = GetCipClass(kCipAssemblyClassCode);

+ 1 - 1
source/src/cip/cipclass3connection.c

@@ -24,7 +24,7 @@ void Class3ConnectionTimeoutHandler(CipConnectionObject *connection_object) {
 
 /**** Implementation ****/
 CipError EstablishClass3Connection(
-  const CipConnectionObject *RESTRICT const connection_object,
+  CipConnectionObject *RESTRICT const connection_object,
   EipUint16 *const extended_error) {
   CipError cip_error = kCipErrorSuccess;
 

+ 1 - 1
source/src/cip/cipclass3connection.h

@@ -50,7 +50,7 @@ EipStatus CipClass3ConnectionObjectStateEstablishedHandler(
  *    - On an error the general status code to be put into the response
  */
 CipError EstablishClass3Connection(
-  const CipConnectionObject *RESTRICT const connection_object,
+  CipConnectionObject *RESTRICT const connection_object,
   EipUint16 *const extended_error);
 
 /** @brief Initializes the explicit connections mechanism

+ 50 - 47
source/src/cip/cipcommon.c

@@ -105,7 +105,7 @@ EipStatus NotifyClass(const CipClass *RESTRICT const cip_class,
                       const int encapsulation_session) {
 
   /* find the instance: if instNr==0, the class is addressed, else find the instance */
-  EipUint16 instance_number =
+  CipInstanceNum instance_number =
     message_router_request->request_path.instance_number;                           /* get the instance number */
   CipInstance *instance = GetCipInstance(cip_class, instance_number); /* look up the instance (note that if inst==0 this will be the class itself) */
   if(instance) /* if instance is found */
@@ -165,10 +165,10 @@ CipUint GetMaxInstanceNumber(CipClass *RESTRICT const cip_class) {
 }
 
 CipInstance *AddCipInstances(CipClass *RESTRICT const cip_class,
-                             const int number_of_instances) {
+                             const CipInstanceNum number_of_instances) {
   CipInstance **next_instance = NULL;
   CipInstance *first_instance = NULL; /* Initialize to error result */
-  EipUint32 instance_number = 1; /* the first instance is number 1 */
+  CipInstanceNum instance_number = 1; /* the first instance is number 1 */
   int new_instances = 0;
 
   OPENER_TRACE_INFO("adding %d instances to class %s\n",
@@ -250,7 +250,7 @@ CipInstance *AddCipInstances(CipClass *RESTRICT const cip_class,
 }
 
 CipInstance *AddCipInstance(CipClass *RESTRICT const cip_class,
-                            const EipUint32 instance_id) {
+                            const CipInstanceNum instance_id) {
   CipInstance *instance = GetCipInstance(cip_class, instance_id);
 
   if(NULL == instance) { /*we have no instance with given id*/
@@ -270,7 +270,7 @@ CipClass *CreateCipClass(const CipUdint class_code,
                          const int number_of_instance_attributes,
                          const EipUint32 highest_instance_attribute_number,
                          const int number_of_instance_services,
-                         const int number_of_instances,
+                         const CipInstanceNum number_of_instances,
                          const char *const name,
                          const EipUint16 revision,
                          InitializeCipClass initializer) {
@@ -333,7 +333,7 @@ CipClass *CreateCipClass(const CipUdint class_code,
   cip_class->class_instance.cip_class = meta_class; /* the class's class is the metaclass (like SmallTalk)*/
   cip_class->class_instance.next = 0; /* the next link will always be zero, since there is only one instance of any particular class object */
 
-  meta_class->class_instance.instance_number = 0xffffffff; /*the metaclass object does not really have a valid instance number*/
+  meta_class->class_instance.instance_number = 0xffff; /*the metaclass object does not really have a valid instance number*/
   meta_class->class_instance.attributes = NULL;/* the metaclass has no attributes*/
   meta_class->class_instance.cip_class = NULL; /* the metaclass has no class*/
   meta_class->class_instance.next = NULL; /* the next link will always be zero, since there is only one instance of any particular metaclass object*/
@@ -579,82 +579,82 @@ EipStatus GetAttributeSingle(CipInstance *RESTRICT const instance,
   return kEipStatusOkSend;
 }
 
-void EncodeCipBool(const CipBool *const data,
+void EncodeCipBool(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddSintToMessage(*(EipUint8 *) (data), outgoing_message);
 }
 
-void EncodeCipByte(const CipByte *const data,
+void EncodeCipByte(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddSintToMessage(*(EipUint8 *) (data), outgoing_message);
 }
 
-void EncodeCipWord(const CipWord *const data,
+void EncodeCipWord(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddIntToMessage(*(EipUint16 *) (data), outgoing_message);
 }
 
-void EncodeCipDword(const CipDword *const data,
+void EncodeCipDword(const void *const data,
                     ENIPMessage *const outgoing_message) {
   AddDintToMessage(*(EipUint32 *) (data), outgoing_message);
 }
 
-void EncodeCipLword(const CipLword *const data,
+void EncodeCipLword(const void *const data,
                     ENIPMessage *const outgoing_message) {
   AddLintToMessage(*(EipUint64 *) (data), outgoing_message);
 }
 
-void EncodeCipUsint(const CipUsint *const data,
+void EncodeCipUsint(const void *const data,
                     ENIPMessage *const outgoing_message) {
   AddSintToMessage(*(EipUint8 *) (data), outgoing_message);
 }
 
-void EncodeCipUint(const CipUint *const data,
+void EncodeCipUint(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddIntToMessage(*(EipUint16 *) (data), outgoing_message);
 }
 
-void EncodeCipUdint(const CipUdint *const data,
+void EncodeCipUdint(const void *const data,
                     ENIPMessage *const outgoing_message) {
   AddDintToMessage(*(EipUint32 *) (data), outgoing_message);
 }
 
-void EncodeCipUlint(const CipUlint *const data,
+void EncodeCipUlint(const void *const data,
                     ENIPMessage *const outgoing_message) {
   AddLintToMessage(*(EipUint64 *) (data), outgoing_message);
 }
 
-void EncodeCipSint(const CipSint *const data,
+void EncodeCipSint(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddSintToMessage(*(EipUint8 *) (data), outgoing_message);
 }
 
-void EncodeCipInt(const CipInt *const data,
+void EncodeCipInt(const void *const data,
                   ENIPMessage *const outgoing_message) {
   AddIntToMessage(*(EipUint16 *) (data), outgoing_message);
 }
 
-void EncodeCipDint(const CipDint *const data,
+void EncodeCipDint(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddDintToMessage(*(EipUint32 *) (data), outgoing_message);
 }
 
-void EncodeCipLint(const CipLint *const data,
+void EncodeCipLint(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddLintToMessage(*(EipUint64 *) (data), outgoing_message);
 }
 
-void EncodeCipReal(const CipReal *const data,
+void EncodeCipReal(const void *const data,
                    ENIPMessage *const outgoing_message) {
   AddDintToMessage(*(EipUint32 *) (data), outgoing_message);
 }
 
-void EncodeCipLreal(const CipLreal *const data,
+void EncodeCipLreal(const void *const data,
                     ENIPMessage *const outgoing_message) {
   AddLintToMessage(*(EipUint64 *) (data), outgoing_message);
 }
 
-void EncodeCipShortString(const CipShortString *const data,
+void EncodeCipShortString(const void *const data,
                           ENIPMessage *const outgoing_message) {
   CipShortString *const short_string = (CipShortString *) data;
 
@@ -667,7 +667,7 @@ void EncodeCipShortString(const CipShortString *const data,
   outgoing_message->used_message_length += short_string->length;
 }
 
-void EncodeCipString(const CipString *const data,
+void EncodeCipString(const void *const data,
                      ENIPMessage *const outgoing_message) {
   CipString *const string = (CipString *) data;
 
@@ -686,7 +686,7 @@ void EncodeCipString(const CipString *const data,
   }
 }
 
-void EncodeCipString2(const CipString2 *const data,
+void EncodeCipString2(const void *const data,
                       ENIPMessage *const outgoing_message) {
   /* Suppress unused parameter compiler warning. */
   (void)data;
@@ -695,7 +695,7 @@ void EncodeCipString2(const CipString2 *const data,
   OPENER_ASSERT(false); /* Not implemented yet */
 }
 
-void EncodeCipStringN(const CipStringN *const data,
+void EncodeCipStringN(const void *const data,
                       ENIPMessage *const outgoing_message) {
   /* Suppress unused parameter compiler warning. */
   (void)data;
@@ -713,7 +713,7 @@ static void CipStringIHeaderEncoding(const CipStringIStruct *const string,
   EncodeCipUint(&(string->character_set), outgoing_message);
 }
 
-void EncodeCipStringI(const CipStringI *const data,
+void EncodeCipStringI(const void *const data,
                       ENIPMessage *const outgoing_message) {
   const CipStringI *const string_i = data;
   EncodeCipUsint(&(string_i->number_of_strings), outgoing_message);
@@ -744,7 +744,7 @@ void EncodeCipStringI(const CipStringI *const data,
   }
 }
 
-void EncodeCipByteArray(const CipByteArray *const data,
+void EncodeCipByteArray(const void *const data,
                         ENIPMessage *const outgoing_message) {
   OPENER_TRACE_INFO(" -> get attribute byte array\r\n");
   CipByteArray *cip_byte_array = (CipByteArray *) data;
@@ -755,9 +755,9 @@ void EncodeCipByteArray(const CipByteArray *const data,
   outgoing_message->used_message_length += cip_byte_array->length;
 }
 
-void EncodeCipEPath(const CipEpath *const data,
+void EncodeCipEPath(const void *const data,
                     ENIPMessage *const outgoing_message) {
-  AddIntToMessage(data->path_size, outgoing_message);
+  AddIntToMessage( ( (CipEpath *)data )->path_size, outgoing_message );
   EncodeEPath( (CipEpath *) data, outgoing_message );
 }
 
@@ -846,7 +846,7 @@ EipStatus SetAttributeSingle(CipInstance *RESTRICT const instance,
 }
 
 int DecodeCipBool(CipBool *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetBoolFromMessage(&message_router_request->data);
@@ -855,7 +855,7 @@ int DecodeCipBool(CipBool *const data,
 }
 
 int DecodeCipByte(CipByte *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetByteFromMessage(&message_router_request->data);
@@ -895,7 +895,7 @@ int DecodeCipByteArray(CipByteArray *const data,
 }
 
 int DecodeCipWord(CipWord *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetWordFromMessage(&message_router_request->data);
@@ -904,7 +904,7 @@ int DecodeCipWord(CipWord *const data,
 }
 
 int DecodeCipDword(CipDword *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response) {
 
   *data = GetDintFromMessage(&message_router_request->data);
@@ -913,7 +913,7 @@ int DecodeCipDword(CipDword *const data,
 }
 
 int DecodeCipLword(CipLword *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response) {
 
   *data = GetLintFromMessage(&message_router_request->data);
@@ -922,7 +922,7 @@ int DecodeCipLword(CipLword *const data,
 }
 
 int DecodeCipUsint(CipUsint *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response) {
 
   *data = GetUsintFromMessage(&message_router_request->data);
@@ -931,7 +931,7 @@ int DecodeCipUsint(CipUsint *const data,
 }
 
 int DecodeCipUint(CipUint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetUintFromMessage(&message_router_request->data);
@@ -940,7 +940,7 @@ int DecodeCipUint(CipUint *const data,
 }
 
 int DecodeCipUdint(CipUdint *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response) {
 
   *data = GetUdintFromMessage(&message_router_request->data);
@@ -949,7 +949,7 @@ int DecodeCipUdint(CipUdint *const data,
 }
 
 int DecodeCipUlint(CipUlint *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response) {
 
   *data = GetLintFromMessage(&message_router_request->data);
@@ -958,7 +958,7 @@ int DecodeCipUlint(CipUlint *const data,
 }
 
 int DecodeCipSint(CipSint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetSintFromMessage(&message_router_request->data);
@@ -967,7 +967,7 @@ int DecodeCipSint(CipSint *const data,
 }
 
 int DecodeCipInt(CipInt *const data,
-                 const CipMessageRouterRequest *const message_router_request,
+                 CipMessageRouterRequest *const message_router_request,
                  CipMessageRouterResponse *const message_router_response) {
 
   *data = GetIntFromMessage(&message_router_request->data);
@@ -976,7 +976,7 @@ int DecodeCipInt(CipInt *const data,
 }
 
 int DecodeCipDint(CipDint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetDintFromMessage(&message_router_request->data);
@@ -985,7 +985,7 @@ int DecodeCipDint(CipDint *const data,
 }
 
 int DecodeCipLint(CipLint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetLintFromMessage(&message_router_request->data);
@@ -994,7 +994,7 @@ int DecodeCipLint(CipLint *const data,
 }
 
 int DecodeCipReal(CipReal *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response) {
 
   *data = GetDintFromMessage(&message_router_request->data);
@@ -1003,7 +1003,7 @@ int DecodeCipReal(CipReal *const data,
 }
 
 int DecodeCipLreal(CipLreal *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response) {
 
   *data = GetLintFromMessage(&message_router_request->data);
@@ -1338,8 +1338,9 @@ EipStatus SetAttributeList(CipInstance *instance,
   return kEipStatusOkSend;
 }
 
-void EncodeEPath(const CipEpath *const epath,
+void EncodeEPath(const void *const data,
                  ENIPMessage *const message) {
+  const CipEpath *const epath = (CipEpath *)data;
   unsigned int length = epath->path_size;
   size_t start_length = message->used_message_length;
 
@@ -1357,7 +1358,7 @@ void EncodeEPath(const CipEpath *const epath,
   if(0 < length) {
     if(epath->instance_number < 256) {
       AddSintToMessage(0x24, message); /*8Bit Instance Id */
-      AddSintToMessage(epath->instance_number, message);
+      AddSintToMessage( (EipUint8)epath->instance_number, message );
       length -= 1;
     } else {
       AddSintToMessage(0x25, message); /*16Bit Instance Id */
@@ -1380,8 +1381,10 @@ void EncodeEPath(const CipEpath *const epath,
     }
   }
 
+  /* path size is in 16 bit chunks according to the specification */
   OPENER_ASSERT(
-    epath->path_size * 2 == message->used_message_length - start_length);             /* path size is in 16 bit chunks according to the specification */
+    epath->path_size * sizeof(CipWord) ==
+    message->used_message_length - start_length);
 }
 
 int DecodePaddedEPath(CipEpath *epath,

+ 129 - 126
source/src/cip/cipconnectionmanager.c

@@ -193,7 +193,7 @@ CipUdint GetConnectionId(void) {
 #else
   CipUint connection_id = NextXorShiftUint32();
 #endif
-  return ( g_incarnation_id | (connection_id & 0x0000FFFF) );
+  return (g_incarnation_id | (connection_id & 0x0000FFFF) );
 }
 
 void InitializeConnectionManager(CipClass *class) {
@@ -285,9 +285,8 @@ EipStatus HandleReceivedConnectedData(const EipUint8 *const data,
                                       int data_length,
                                       struct sockaddr_in *from_address) {
 
-  if( ( CreateCommonPacketFormatStructure(data, data_length,
-                                          &g_common_packet_format_data_item) )
-      ==
+  if( (CreateCommonPacketFormatStructure(data, data_length,
+                                         &g_common_packet_format_data_item) ) ==
       kEipStatusError ) {
     return kEipStatusError;
   } else {
@@ -456,9 +455,9 @@ EipStatus HandleNonNullNonMatchingForwardOpenRequest(
   EipUint16 connection_status = kConnectionManagerExtendedStatusCodeSuccess;
 
   /*check if the trigger type value is invalid or ok */
-  if( kConnectionObjectTransportClassTriggerProductionTriggerInvalid ==
-      ConnectionObjectGetTransportClassTriggerProductionTrigger(&
-                                                                g_dummy_connection_object) )
+  if(kConnectionObjectTransportClassTriggerProductionTriggerInvalid ==
+     ConnectionObjectGetTransportClassTriggerProductionTrigger(&
+                                                               g_dummy_connection_object) )
   {
     return AssembleForwardOpenResponse(&g_dummy_connection_object,
                                        message_router_response,
@@ -483,7 +482,7 @@ EipStatus HandleNonNullNonMatchingForwardOpenRequest(
   if(NULL != connection_management_entry) {
     if (NULL != connection_management_entry->open_connection_function) {
       temp = connection_management_entry->open_connection_function(
-        &g_dummy_connection_object, &connection_status);
+          &g_dummy_connection_object, &connection_status);
     } else {
       connection_status = kConnectionManagerExtendedStatusCodeMiscellaneous;
     }
@@ -595,9 +594,9 @@ EipStatus ForwardOpenRoutine(CipInstance *instance,
   g_dummy_connection_object.associated_encapsulation_session =
     encapsulation_session;
 
-  memcpy( &(g_dummy_connection_object.originator_address),
-          originator_address,
-          sizeof(g_dummy_connection_object.originator_address) );
+  memcpy(&(g_dummy_connection_object.originator_address),
+         originator_address,
+         sizeof(g_dummy_connection_object.originator_address) );
 
   ConnectionObjectConnectionType o_to_t_connection_type =
     ConnectionObjectGetOToTConnectionType(&g_dummy_connection_object);
@@ -644,7 +643,7 @@ EipStatus ForwardOpenRoutine(CipInstance *instance,
   }
 
   /* Check if we have a matching or non matching request */
-  if( NULL != CheckForExistingConnection(&g_dummy_connection_object) ) {
+  if(NULL != CheckForExistingConnection(&g_dummy_connection_object) ) {
     OPENER_TRACE_INFO("We have a Matching request\n");
     is_matching_request = true;
 
@@ -695,10 +694,10 @@ EipStatus ForwardClose(CipInstance *instance,
   while(NULL != node) {
     /* this check should not be necessary as only established connections should be in the active connection list */
     CipConnectionObject *connection_object = node->data;
-    if( ( kConnectionObjectStateEstablished ==
-          ConnectionObjectGetState(connection_object) )
-        || ( kConnectionObjectStateTimedOut ==
-             ConnectionObjectGetState(connection_object) ) ) {
+    if( (kConnectionObjectStateEstablished ==
+         ConnectionObjectGetState(connection_object) )
+        || (kConnectionObjectStateTimedOut ==
+            ConnectionObjectGetState(connection_object) ) ) {
       if( (connection_object->connection_serial_number ==
            connection_serial_number) &&
           (connection_object->originator_vendor_id == originator_vendor_id)
@@ -933,11 +932,11 @@ EipStatus ManageConnections(MilliSeconds elapsed_time) {
   while(NULL != node) {
     //OPENER_TRACE_INFO("Entering Connection Object loop\n");
     CipConnectionObject *connection_object = node->data;
-    if( kConnectionObjectStateEstablished ==
-        ConnectionObjectGetState(connection_object) ) {
+    if(kConnectionObjectStateEstablished ==
+       ConnectionObjectGetState(connection_object) ) {
       if( (NULL != connection_object->consuming_instance) || /* we have a consuming connection check inactivity watchdog timer */
-          ( kConnectionObjectTransportClassTriggerDirectionServer ==
-            ConnectionObjectGetTransportClassTriggerDirection(connection_object) ) ) /* all server connections have to maintain an inactivity watchdog timer */
+          (kConnectionObjectTransportClassTriggerDirectionServer ==
+           ConnectionObjectGetTransportClassTriggerDirection(connection_object) ) ) /* all server connections have to maintain an inactivity watchdog timer */
       {
         if(elapsed_time >= connection_object->inactivity_watchdog_timer) {
           /* we have a timed out connection perform watchdog time out action*/
@@ -951,16 +950,16 @@ EipStatus ManageConnections(MilliSeconds elapsed_time) {
         }
       }
       /* only if the connection has not timed out check if data is to be send */
-      if( kConnectionObjectStateEstablished ==
-          ConnectionObjectGetState(connection_object) ) {
+      if(kConnectionObjectStateEstablished ==
+         ConnectionObjectGetState(connection_object) ) {
         /* client connection */
-        if( ( 0 != ConnectionObjectGetExpectedPacketRate(connection_object) )
+        if( (0 != ConnectionObjectGetExpectedPacketRate(connection_object) )
             && (kEipInvalidSocket !=
                 connection_object->socket[kUdpCommuncationDirectionProducing]) ) /* only produce for the master connection */
         {
-          if( kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
-              ConnectionObjectGetTransportClassTriggerProductionTrigger(
-                connection_object) ) {
+          if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
+             ConnectionObjectGetTransportClassTriggerProductionTrigger(
+               connection_object) ) {
             /* non cyclic connections have to decrement production inhibit timer */
             if(elapsed_time <= connection_object->production_inhibit_timer) {
               //The connection is allowed to send again
@@ -986,15 +985,13 @@ EipStatus ManageConnections(MilliSeconds elapsed_time) {
               connection_object->transmission_trigger_timer -= elapsed_time;
             } else {  /* elapsed time was longer than RPI */
               connection_object->transmission_trigger_timer = 0;
-              OPENER_TRACE_INFO(
-                "elapsed time: %lu ms was longer than RPI: %u ms\n",
-                elapsed_time,
-                ConnectionObjectGetRequestedPacketInterval(
-                  connection_object) );
+              OPENER_TRACE_INFO("elapsed time: %lu ms was longer than RPI: %u ms\n",
+                                elapsed_time,
+                                ConnectionObjectGetRequestedPacketInterval(connection_object));
             }
-            if( kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
-                ConnectionObjectGetTransportClassTriggerProductionTrigger(
-                  connection_object) ) {
+            if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
+               ConnectionObjectGetTransportClassTriggerProductionTrigger(
+                 connection_object) ) {
               /* non cyclic connections have to reload the production inhibit timer */
               ConnectionObjectResetProductionInhibitTimer(connection_object);
             }
@@ -1059,10 +1056,7 @@ EipStatus AssembleForwardOpenResponse(CipConnectionObject *connection_object,
                      &message_router_response->message);
   } else {
     /* we have an connection creation error */
-    OPENER_TRACE_WARN(
-      "AssembleForwardOpenResponse: sending error response, general/extended status=%d/%d\n",
-      general_status,
-      extended_status);
+    OPENER_TRACE_WARN("AssembleForwardOpenResponse: sending error response, general/extended status=%d/%d\n", general_status, extended_status);
     ConnectionObjectSetState(connection_object,
                              kConnectionObjectStateNonExistent);
     /* Expected data length is 10 octets */
@@ -1206,10 +1200,10 @@ CipConnectionObject *GetConnectedObject(const EipUint32 connection_id) {
   DoublyLinkedListNode *iterator = connection_list.first;
 
   while(NULL != iterator) {
-    if( kConnectionObjectStateEstablished ==
-        ConnectionObjectGetState(iterator->data)
-        && connection_id ==
-        ConnectionObjectGetCipConsumedConnectionID(iterator->data) ) {
+    if(kConnectionObjectStateEstablished ==
+       ConnectionObjectGetState(iterator->data)
+       && connection_id ==
+       ConnectionObjectGetCipConsumedConnectionID(iterator->data) ) {
       return iterator->data;
     }
     iterator = iterator->next;
@@ -1224,10 +1218,10 @@ CipConnectionObject *GetConnectedOutputAssembly(
   while(NULL != iterator) {
     if(kConnectionObjectInstanceTypeIOExclusiveOwner ==
        ConnectionObjectGetInstanceType(iterator->data)
-       && ( kConnectionObjectStateEstablished ==
-            ConnectionObjectGetState(iterator->data)
-            || kConnectionObjectStateTimedOut ==
-            ConnectionObjectGetState(iterator->data) )
+       && (kConnectionObjectStateEstablished ==
+           ConnectionObjectGetState(iterator->data)
+           || kConnectionObjectStateTimedOut ==
+           ConnectionObjectGetState(iterator->data) )
        && output_assembly_id ==
        ( (CipConnectionObject *) iterator->data )->produced_path.instance_id) {
       return iterator->data;
@@ -1243,9 +1237,9 @@ CipConnectionObject *CheckForExistingConnection(
   DoublyLinkedListNode *iterator = connection_list.first;
 
   while(NULL != iterator) {
-    if( kConnectionObjectStateEstablished ==
-        ConnectionObjectGetState(iterator->data) ) {
-      if( EqualConnectionTriad(connection_object, iterator->data) ) {
+    if(kConnectionObjectStateEstablished ==
+       ConnectionObjectGetState(iterator->data) ) {
+      if(EqualConnectionTriad(connection_object, iterator->data) ) {
         return iterator->data;
       }
     }
@@ -1295,7 +1289,7 @@ EipStatus CheckElectronicKeyData(EipUint8 key_format,
 
       if(false == compatiblity_mode) {
         /* Major = 0 is valid */
-        if( 0 == ElectronicKeyFormat4GetMajorRevision(key_data) ) {
+        if(0 == ElectronicKeyFormat4GetMajorRevision(key_data) ) {
           return kEipStatusOk;
         }
 
@@ -1348,7 +1342,7 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
   CipClass *class = NULL;
 
   CipDword class_id = 0x0;
-  CipDword instance_id = 0x0;
+  CipInstanceNum instance_id = 0x0;
 
   /* with 256 we mark that we haven't got a PIT segment */
   ConnectionObjectSetProductionInhibitTime(connection_object, 256);
@@ -1358,14 +1352,14 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
     header_length = g_kLargeForwardOpenHeaderLength;
   }
 
-  if( (header_length + remaining_path * 2) <
+  if( ( header_length + remaining_path * sizeof(CipWord) ) <
       message_router_request->request_data_size ) {
     /* the received packet is larger than the data in the path */
     *extended_error = 0;
     return kCipErrorTooMuchData;
   }
 
-  if( (header_length + remaining_path * 2) >
+  if( ( header_length + remaining_path * sizeof(CipWord) ) >
       message_router_request->request_data_size ) {
     /*there is not enough data in received packet */
     *extended_error = 0;
@@ -1375,13 +1369,13 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
 
   if(remaining_path > 0) {
     /* first look if there is an electronic key */
-    if( kSegmentTypeLogicalSegment == GetPathSegmentType(message) ) {
-      if( kLogicalSegmentLogicalTypeSpecial ==
-          GetPathLogicalSegmentLogicalType(message) ) {
-        if( kLogicalSegmentSpecialTypeLogicalFormatElectronicKey ==
-            GetPathLogicalSegmentSpecialTypeLogicalType(message) ) {
-          if( kElectronicKeySegmentFormatKeyFormat4 ==
-              GetPathLogicalSegmentElectronicKeyFormat(message) ) {
+    if(kSegmentTypeLogicalSegment == GetPathSegmentType(message) ) {
+      if(kLogicalSegmentLogicalTypeSpecial ==
+         GetPathLogicalSegmentLogicalType(message) ) {
+        if(kLogicalSegmentSpecialTypeLogicalFormatElectronicKey ==
+           GetPathLogicalSegmentSpecialTypeLogicalType(message) ) {
+          if(kElectronicKeySegmentFormatKeyFormat4 ==
+             GetPathLogicalSegmentElectronicKeyFormat(message) ) {
             /* Check if there is enough data for holding the electronic key segment */
             if(remaining_path < 5) {
               *extended_error = 0;
@@ -1408,12 +1402,12 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
                                                    electronic_key.key_data),
               ElectronicKeyFormat4GetMinorRevision(connection_object->
                                                    electronic_key.key_data) );
-            if( kEipStatusOk
-                != CheckElectronicKeyData(connection_object->electronic_key.
-                                          key_format,
-                                          connection_object->electronic_key.
-                                          key_data,
-                                          extended_error) ) {
+            if(kEipStatusOk
+               != CheckElectronicKeyData(connection_object->electronic_key.
+                                         key_format,
+                                         connection_object->electronic_key.
+                                         key_data,
+                                         extended_error) ) {
               ElectronicKeyFormat4Delete(&electronic_key);
               return kCipErrorConnectionFailure;
             }
@@ -1427,12 +1421,12 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
     }
 
     //TODO: Refactor this afterwards
-    if( kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
-        ConnectionObjectGetTransportClassTriggerProductionTrigger(
-          connection_object) )
+    if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
+       ConnectionObjectGetTransportClassTriggerProductionTrigger(
+         connection_object) )
     {
       /*non cyclic connections may have a production inhibit */
-      if( kSegmentTypeNetworkSegment == GetPathSegmentType(message) ) {
+      if(kSegmentTypeNetworkSegment == GetPathSegmentType(message) ) {
         NetworkSegmentSubtype network_segment_subtype =
           GetPathNetworkSegmentSubtype(message);
         if(kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds ==
@@ -1445,9 +1439,9 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
       }
     }
 
-    if( kSegmentTypeLogicalSegment == GetPathSegmentType(message) &&
-        kLogicalSegmentLogicalTypeClassId ==
-        GetPathLogicalSegmentLogicalType(message) ) {
+    if(kSegmentTypeLogicalSegment == GetPathSegmentType(message) &&
+       kLogicalSegmentLogicalTypeClassId ==
+       GetPathLogicalSegmentLogicalType(message) ) {
 
       class_id = CipEpathGetLogicalValue(&message);
       class = GetCipClass(class_id);
@@ -1476,28 +1470,29 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
     remaining_path -= 1; /* 1 16Bit word for the class part of the path */
 
     /* Get instance ID */
-    if( kSegmentTypeLogicalSegment == GetPathSegmentType(message) &&
-        kLogicalSegmentLogicalTypeInstanceId ==
-        GetPathLogicalSegmentLogicalType(message) ) { /* store the configuration ID for later checking in the application connection types */
-      instance_id = CipEpathGetLogicalValue(&message);
+    if(kSegmentTypeLogicalSegment == GetPathSegmentType(message) &&
+       kLogicalSegmentLogicalTypeInstanceId ==
+       GetPathLogicalSegmentLogicalType(message) ) { /* store the configuration ID for later checking in the application connection types */
+      const CipDword temp_id = CipEpathGetLogicalValue(&message);
 
       OPENER_TRACE_INFO("Configuration instance id %" PRId32 "\n",
-                        instance_id);
-      if( NULL == GetCipInstance(class, instance_id) ) {
+                        temp_id);
+      if( (temp_id > kCipInstanceNumMax) ||
+          ( NULL == GetCipInstance(class, (CipInstanceNum)temp_id) ) ) {
         /*according to the test tool we should respond with this extended error code */
         *extended_error =
           kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
         return kCipErrorConnectionFailure;
       }
+      instance_id = (CipInstanceNum)temp_id;
       /* 1 or 2 16Bit words for the configuration instance part of the path  */
       remaining_path -= (instance_id > 0xFF) ? 2 : 1; //TODO: 32 bit case missing
     } else {
       OPENER_TRACE_INFO("no config data\n");
     }
 
-    if( kConnectionObjectTransportClassTriggerTransportClass3 ==
-        ConnectionObjectGetTransportClassTriggerTransportClass(
-          connection_object) )
+    if(kConnectionObjectTransportClassTriggerTransportClass3 ==
+       ConnectionObjectGetTransportClassTriggerTransportClass(connection_object) )
     {
       /*we have Class 3 connection*/
       if(remaining_path > 0) {
@@ -1519,20 +1514,20 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
       { .class_id = class_id, .instance_id = instance_id,
         .attribute_id_or_connection_point = 0 };
 
-      memcpy( &(connection_object->configuration_path),
-              &connection_epath,
-              sizeof(connection_object->configuration_path) );
-      memcpy( &(connection_object->produced_path), &connection_epath,
-              sizeof(connection_object->produced_path) );
+      memcpy(&(connection_object->configuration_path),
+             &connection_epath,
+             sizeof(connection_object->configuration_path) );
+      memcpy(&(connection_object->produced_path), &connection_epath,
+             sizeof(connection_object->produced_path) );
 
       /* End class 3 connection handling */
     } else { /* we have an IO connection */
       CipConnectionPathEpath connection_epath =
       { .class_id = class_id, .instance_id = instance_id,
         .attribute_id_or_connection_point = 0 };
-      memcpy( &(connection_object->configuration_path),
-              &connection_epath,
-              sizeof(connection_object->configuration_path) );
+      memcpy(&(connection_object->configuration_path),
+             &connection_epath,
+             sizeof(connection_object->configuration_path) );
       ConnectionObjectConnectionType originator_to_target_connection_type =
         ConnectionObjectGetOToTConnectionType(connection_object);
       ConnectionObjectConnectionType target_to_originator_connection_type =
@@ -1571,28 +1566,38 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
 
       for(size_t i = 0; i < number_of_encoded_paths; i++) /* process up to 2 encoded paths */
       {
-        if( kSegmentTypeLogicalSegment == GetPathSegmentType(message)
-            && ( kLogicalSegmentLogicalTypeInstanceId ==
-                 GetPathLogicalSegmentLogicalType(message)
-                 || kLogicalSegmentLogicalTypeConnectionPoint ==
-                 GetPathLogicalSegmentLogicalType(message) ) ) /* Connection Point interpreted as InstanceNr -> only in Assembly Objects */
+        if(kSegmentTypeLogicalSegment == GetPathSegmentType(message)
+           && (kLogicalSegmentLogicalTypeInstanceId ==
+               GetPathLogicalSegmentLogicalType(message)
+               || kLogicalSegmentLogicalTypeConnectionPoint ==
+               GetPathLogicalSegmentLogicalType(message) ) ) /* Connection Point interpreted as InstanceNr -> only in Assembly Objects */
         {   /* Attribute Id or Connection Point */
-          CipDword attribute_id = CipEpathGetLogicalValue(&message);
-          CipConnectionPathEpath path =
-          { .class_id = class_id, .instance_id = attribute_id,
-            .attribute_id_or_connection_point = 0 };
-          memcpy( paths_to_encode[i], &path,
-                  sizeof(connection_object->produced_path) );
+
+          /* Validate encoded instance number. */
+          const CipDword temp_instance_id = CipEpathGetLogicalValue(&message);
+          if (temp_instance_id > kCipInstanceNumMax) {
+            *extended_error =
+              kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
+            return kCipErrorConnectionFailure;
+          }
+          instance_id = (CipInstanceNum)temp_instance_id;
+
+          CipConnectionPathEpath path;
+          path.class_id = class_id;
+          path.instance_id = instance_id;
+          path.attribute_id_or_connection_point = 0;
+          memcpy(paths_to_encode[i], &path,
+                 sizeof(connection_object->produced_path) );
           OPENER_TRACE_INFO(
             "connection point %" PRIu32 "\n",
-            attribute_id);
-          if( NULL == GetCipInstance(class, attribute_id) ) { /* Old code - Probably here the attribute ID marks the instance for the assembly object  */
+            instance_id);
+          if( NULL == GetCipInstance(class, instance_id) ) {
             *extended_error =
               kConnectionManagerExtendedStatusCodeInconsistentApplicationPathCombo;
             return kCipErrorConnectionFailure;
           }
           /* 1 or 2 16Bit word for the connection point part of the path */
-          remaining_path -= (attribute_id > 0xFF) ? 2 : 1;
+          remaining_path -= (instance_id > 0xFF) ? 2 : 1;
         } else {
           *extended_error =
             kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
@@ -1628,10 +1633,9 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
               GetPathNetworkSegmentSubtype(message);
             switch(subtype) {
               case kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds:
-                if(
-                  kConnectionObjectTransportClassTriggerProductionTriggerCyclic
-                  != ConnectionObjectGetTransportClassTriggerProductionTrigger(
-                    connection_object) ) {
+                if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic
+                   != ConnectionObjectGetTransportClassTriggerProductionTrigger(
+                     connection_object) ) {
                   /* only non cyclic connections may have a production inhibit */
                   connection_object->production_inhibit_time = message[1];
                   message += 2;
@@ -1668,12 +1672,11 @@ EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
 
 void CloseConnection(CipConnectionObject *RESTRICT connection_object) {
 
-  OPENER_TRACE_INFO( "cipconnectionmanager: CloseConnection, trigger: %d \n",
-                     ConnectionObjectGetTransportClassTriggerTransportClass(
-                       connection_object) );
+  OPENER_TRACE_INFO("cipconnectionmanager: CloseConnection, trigger: %d \n",
+  	ConnectionObjectGetTransportClassTriggerTransportClass(connection_object));
 
-  if( kConnectionObjectTransportClassTriggerTransportClass3 !=
-      ConnectionObjectGetTransportClassTriggerTransportClass(connection_object) )
+  if(kConnectionObjectTransportClassTriggerTransportClass3 !=
+     ConnectionObjectGetTransportClassTriggerTransportClass(connection_object) )
   {
     /* only close the UDP connection for not class 3 connections */
     CloseUdpSocket(connection_object->socket[kUdpCommuncationDirectionConsuming]);
@@ -1704,7 +1707,7 @@ void RemoveFromActiveConnections(CipConnectionObject *const connection_object) {
   } OPENER_TRACE_ERR("Connection not found in active connection list\n");
 }
 
-EipBool8 IsConnectedOutputAssembly(const EipUint32 instance_number) {
+EipBool8 IsConnectedOutputAssembly(const CipInstanceNum instance_number) {
   EipBool8 is_connected = false;
 
   DoublyLinkedListNode *node = connection_list.first;
@@ -1713,8 +1716,8 @@ EipBool8 IsConnectedOutputAssembly(const EipUint32 instance_number) {
     CipConnectionObject *connection_object = (CipConnectionObject *) node->data;
     CipDword consumed_connection_point =
       connection_object->consumed_path.instance_id;
-    if( instance_number == consumed_connection_point &&
-        true == ConnectionObjectIsTypeIOConnection(connection_object) ) {
+    if(instance_number == consumed_connection_point &&
+       true == ConnectionObjectIsTypeIOConnection(connection_object) ) {
       is_connected = true;
       break;
     }
@@ -1784,17 +1787,18 @@ EipStatus TriggerConnections(unsigned int output_assembly,
 
 void CheckForTimedOutConnectionsAndCloseTCPConnections(
   const CipConnectionObject *const connection_object,
-  CloseSessionFunction CloseSessions) {
+  CloseSessionFunction CloseSessions)
+{
 
   DoublyLinkedListNode *search_node = connection_list.first;
   bool non_timed_out_connection_found = false;
   while(NULL != search_node) {
     CipConnectionObject *search_connection = search_node->data;
-    if( ConnectionObjectEqualOriginator(connection_object,
-                                        search_connection) &&
-        connection_object != search_connection
-        && kConnectionObjectStateTimedOut !=
-        ConnectionObjectGetState(search_connection) ) {
+    if(ConnectionObjectEqualOriginator(connection_object,
+                                       search_connection) &&
+       connection_object != search_connection
+       && kConnectionObjectStateTimedOut !=
+       ConnectionObjectGetState(search_connection) ) {
       non_timed_out_connection_found = true;
       break;
     }
@@ -1806,10 +1810,9 @@ void CheckForTimedOutConnectionsAndCloseTCPConnections(
 }
 
 void InitializeConnectionManagerData() {
-  memset( g_connection_management_list,
-          0,
-          g_kNumberOfConnectableObjects *
-          sizeof(ConnectionManagementHandling) );
+  memset(g_connection_management_list,
+         0,
+         g_kNumberOfConnectableObjects * sizeof(ConnectionManagementHandling) );
   InitializeClass3ConnectionData();
   InitializeIoConnectionData();
 }

+ 1 - 1
source/src/cip/cipconnectionmanager.h

@@ -199,7 +199,7 @@ CipConnectionObject *GetConnectedOutputAssembly(
 void CloseConnection(CipConnectionObject *RESTRICT connection_object);
 
 /* TODO: Missing documentation */
-EipBool8 IsConnectedOutputAssembly(const EipUint32 instance_number);
+EipBool8 IsConnectedOutputAssembly(const CipInstanceNum instance_number);
 
 /** @brief Insert the given connection object to the list of currently active
  *  and managed connections.

+ 1 - 1
source/src/cip/cipepath.h

@@ -180,7 +180,7 @@ typedef enum symbolic_segment_extended_format {
 /* Start - Often used types of EPaths */
 typedef struct connection_path_epath {
   CipDword class_id;   /**< here in accordance with Vol. 1 C-1.4.2 */
-  CipDword instance_id;
+  CipInstanceNum instance_id;
   CipDword attribute_id_or_connection_point;
 } CipConnectionPathEpath;
 /* End - Often used types of EPaths */

+ 3 - 3
source/src/cip/cipethernetlink.c

@@ -275,9 +275,9 @@ EipStatus CipEthernetLinkInit(void) {
 #endif
 
     /* bind attributes to the instance */
-    for (unsigned int idx = 0; idx < OPENER_ETHLINK_INSTANCE_CNT; ++idx) {
+    for (CipInstanceNum idx = 0; idx < OPENER_ETHLINK_INSTANCE_CNT; ++idx) {
       CipInstance *ethernet_link_instance =
-        GetCipInstance(ethernet_link_class, idx + 1);
+        GetCipInstance( ethernet_link_class, (CipInstanceNum)(idx + 1) );
 
       InsertAttribute(ethernet_link_instance,
                       1,
@@ -551,7 +551,7 @@ EipStatus GetAndClearEthernetLink(
 
 #if defined(OPENER_ETHLINK_IFACE_CTRL_ENABLE) && \
   0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE
-static bool IsIfaceControlAllowed(CipUdint instance_id,
+static bool IsIfaceControlAllowed(CipInstanceNum instance_id,
                                   CipEthernetLinkInterfaceControl const *iface_cntrl)
 {
   const CipUsint duplex_mode =

+ 1 - 1
source/src/cip/cipioconnection.c

@@ -1015,7 +1015,7 @@ CipError OpenCommunicationChannels(CipConnectionObject *connection_object) {
 
     if(OpenProducingPointToPointConnection(connection_object,
                                            common_packet_format_data) !=
-       kEipStatusOk) {
+       kCipErrorSuccess) {
       OPENER_TRACE_ERR("error in PointToPoint producing connection\n");
       return kCipErrorConnectionFailure;
     }

+ 1 - 1
source/src/cip/cipmessagerouter.c

@@ -137,7 +137,7 @@ CipClass *GetCipClass(const CipUdint class_code) {
 }
 
 CipInstance *GetCipInstance(const CipClass *RESTRICT const cip_class,
-                            const EipUint32 instance_number) {
+                            const CipInstanceNum instance_number) {
 
   if(instance_number == 0) {
     return (CipInstance *) cip_class; /* if the instance number is zero, return the class object itself*/

+ 4 - 0
source/src/cip/ciptypes.c

@@ -7,6 +7,10 @@
 #include <endianconv.h>
 #include <trace.h>
 
+
+const CipInstanceNum kCipInstanceNumMax = UINT16_MAX;
+
+
 /* functions*/
 size_t GetCipDataTypeLength(EipUint8 type,
                             const EipUint8 *data) {

+ 12 - 2
source/src/cip/ciptypes.h

@@ -211,6 +211,16 @@ typedef struct cip_type_string_i_struct {
   CipOctet *string;   /**< Pointer to the string data */
 } CipStringIStruct;
 
+
+/** @brief Highest CIP instance number.
+ *
+ * Largest value that can be used to represent or count CIP instances;
+ * intentended for use when validating instance numbers encoded as data types
+ * that can contain illegal values.
+ */
+extern const CipInstanceNum kCipInstanceNumMax;
+
+
 /** @brief Struct for padded EPATHs
  *
  * Here the class code is referenced as class ID - see Vol. 1 C-1.4.2
@@ -219,7 +229,7 @@ typedef struct cip_type_string_i_struct {
 typedef struct {
   EipUint8 path_size;   /**< Path size in 16 bit words (path_size * 16 bit) */
   EipUint16 class_id;   /**< Class ID of the linked object */
-  EipUint16 instance_number;   /**< Requested Instance Number of the linked object */
+  CipInstanceNum instance_number;   /**< Requested Instance Number of the linked object */
   EipUint16 attribute_number;   /**< Requested Attribute Number of the linked object */
 } CipEpath;
 
@@ -308,7 +318,7 @@ typedef struct {
  *  pointer of the @ref CipClass structure.
  */
 typedef struct cip_instance {
-  EipUint32 instance_number;   /**< this instance's number (unique within the class) */
+  CipInstanceNum instance_number;   /**< this instance's number (unique within the class) */
   CipAttributeStruct *attributes;   /**< pointer to an array of attributes which
                                        is unique to this instance */
   struct cip_class *cip_class;   /**< class the instance belongs to */

+ 43 - 43
source/src/opener_api.h

@@ -213,7 +213,7 @@ CipClass *GetCipClass(const CipUdint class_code);
  *          0 if instance is not in the object
  */
 CipInstance *GetCipInstance(const CipClass *RESTRICT const cip_object,
-                            const EipUint32 instance_number);
+                            const CipInstanceNum instance_number);
 
 /** @ingroup CIP_API
  * @brief Get a pointer to an instance's attribute
@@ -258,7 +258,7 @@ CipClass *CreateCipClass(const CipUdint class_code,
                          const int number_of_instance_attributes,
                          const EipUint32 highest_instance_attribute_number,
                          const int number_of_instance_services,
-                         const int number_of_instances,
+                         const CipInstanceNum number_of_instances,
                          const char *const name,
                          const EipUint16 revision,
                          InitializeCipClass initializer);
@@ -283,7 +283,7 @@ CipClass *CreateCipClass(const CipUdint class_code,
  */
 CipInstance *AddCipInstances(
   CipClass *RESTRICT const cip_object_to_add_instances,
-  const int number_of_instances);
+  const CipInstanceNum number_of_instances);
 
 /** @ingroup CIP_API
  * @brief Create one instance of a given class with a certain instance number
@@ -296,7 +296,7 @@ CipInstance *AddCipInstances(
  *
  */
 CipInstance *AddCipInstance(CipClass *RESTRICT const cip_class_to_add_instance,
-                            const EipUint32 instance_id);
+                            const CipInstanceNum instance_id);
 
 /** @ingroup CIP_API
  * @brief Insert an attribute in an instance of a CIP class
@@ -385,73 +385,73 @@ void InsertGetSetCallback(CipClass *const cip_class,
  *  @param message_router_response The message router response construct
  */
 
-void EncodeCipBool(const CipBool *const data,
+void EncodeCipBool(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipByte(const CipByte *const data,
+void EncodeCipByte(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipWord(const CipWord *const data,
+void EncodeCipWord(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipDword(const CipDword *const data,
+void EncodeCipDword(const void *const data,
                     ENIPMessage *const outgoing_message);
 
-void EncodeCipLword(const CipLword *const data,
+void EncodeCipLword(const void *const data,
                     ENIPMessage *const outgoing_message);
 
-void EncodeCipUsint(const CipUsint *const data,
+void EncodeCipUsint(const void *const data,
                     ENIPMessage *const outgoing_message);
 
-void EncodeCipUint(const CipUint *const data,
+void EncodeCipUint(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipUdint(const CipUdint *const data,
+void EncodeCipUdint(const void *const data,
                     ENIPMessage *const outgoing_message);
 
-void EncodeCipUlint(const CipUlint *const data,
+void EncodeCipUlint(const void *const data,
                     ENIPMessage *const outgoing_message);
 
-void EncodeCipSint(const CipSint *const data,
+void EncodeCipSint(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipInt(const CipInt *const data,
+void EncodeCipInt(const void *const data,
                   ENIPMessage *const outgoing_message);
 
-void EncodeCipDint(const CipDint *const data,
+void EncodeCipDint(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipLint(const CipLint *const data,
+void EncodeCipLint(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipReal(const CipReal *const data,
+void EncodeCipReal(const void *const data,
                    ENIPMessage *const outgoing_message);
 
-void EncodeCipLreal(const CipLreal *const data,
+void EncodeCipLreal(const void *const data,
                     ENIPMessage *const outgoing_message);
 
-void EncodeCipShortString(const CipShortString *const data,
+void EncodeCipShortString(const void *const data,
                           ENIPMessage *const outgoing_message);
 
-void EncodeCipString(const CipString *const data,
+void EncodeCipString(const void *const data,
                      ENIPMessage *const outgoing_message);
 
-void EncodeCipString2(const CipString2 *const data,
+void EncodeCipString2(const void *const data,
                       ENIPMessage *const outgoing_message);
 
-void EncodeCipStringN(const CipStringN *const data,
+void EncodeCipStringN(const void *const data,
                       ENIPMessage *const outgoing_message);
 
-void EncodeCipStringI(const CipStringI *const data,
+void EncodeCipStringI(const void *const data,
                       ENIPMessage *const outgoing_message);
 
-void EncodeCipByteArray(const CipByteArray *const data,
+void EncodeCipByteArray(const void *const data,
                         ENIPMessage *const outgoing_message);
 
-void EncodeCipEPath(const CipEpath *const data,
+void EncodeCipEPath(const void *const data,
                     ENIPMessage *const outgoing_message); //path_size UINT
 
-void EncodeEPath(const CipEpath *const data,
+void EncodeEPath(const void *const data,
                  ENIPMessage *const outgoing_message); //path_size not encoded
 
 void EncodeCipEthernetLinkPhyisicalAddress(const void *const data,
@@ -471,11 +471,11 @@ void EncodeCipEthernetLinkPhyisicalAddress(const void *const data,
  *          -1 .. error
  */
 int DecodeCipBool(CipBool *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipByte(CipByte *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipByteArray(CipByteArray *const data,
@@ -483,55 +483,55 @@ int DecodeCipByteArray(CipByteArray *const data,
                        CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipWord(CipWord *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipDword(CipDword *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipLword(CipLword *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipUsint(CipUsint *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipUint(CipUint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipUdint(CipUdint *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipUlint(CipUlint *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipSint(CipSint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipInt(CipInt *const data,
-                 const CipMessageRouterRequest *const message_router_request,
+                 CipMessageRouterRequest *const message_router_request,
                  CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipDint(CipDint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipLint(CipLint *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipReal(CipReal *const data,
-                  const CipMessageRouterRequest *const message_router_request,
+                  CipMessageRouterRequest *const message_router_request,
                   CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipLreal(CipLreal *const data,
-                   const CipMessageRouterRequest *const message_router_request,
+                   CipMessageRouterRequest *const message_router_request,
                    CipMessageRouterResponse *const message_router_response);
 
 int DecodeCipString(CipString *const data,
@@ -559,7 +559,7 @@ int DecodeCipShortString(CipShortString *const data,
  * The notification on received configuration data is handled with the
  * AfterAssemblyDataReceived.
  */
-CipInstance *CreateAssemblyObject(const EipUint32 instance_number,
+CipInstance *CreateAssemblyObject(const CipInstanceNum instance_number,
                                   EipByte *const data,
                                   const EipUint16 data_length);
 

+ 67 - 138
source/src/ports/MINGW/sample_application/ethlinkcbs.c

@@ -52,138 +52,66 @@ static CipUdint media_calls[OPENER_ETHLINK_INSTANCE_CNT];
 /* This is meant as debugging aid and to check if the individual counter     */
 /*  value is sent at the right position in the Get* service response.        */
 
-#define MAKE_CNTR(inst, attr, idx, \
-                  cnt) ( (10000000U * inst) + (100000U * attr) + (1000U * idx) + \
-                         cnt )
+#define MAKE_CNTR(inst, attr, idx, cnt) ((10000000U * inst) + (100000U * attr) + (1000U * idx) + cnt)
 
 EipStatus EthLnkPreGetCallback
 (
   CipInstance *const instance,
   CipAttributeStruct *const attribute,
   CipByte service
-) {
+)
+{
   bool hadAction = true;
   EipStatus status = kEipStatusOk;
 
   CipUint attr_no = attribute->attribute_number;
   /* ATTENTION: Array indices run from 0..(N-1), instance numbers from 1..N */
-  CipUdint inst_no  = instance->instance_number;
-  unsigned idx = inst_no - 1;
+  CipInstanceNum inst_no  = instance->instance_number;
+  unsigned idx = inst_no-1;
   switch (attr_no) {
-    case 4: {
-      CipEthernetLinkInterfaceCounters *p_iface_cntrs =
-        &g_ethernet_link[idx].interface_cntrs;
-
-      ++iface_calls[idx]; /* Count successful calls */
-      p_iface_cntrs->ul.in_octets   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                0,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_ucast    = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                1,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_nucast   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                2,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_discards = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                3,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_errors   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                4,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_unknown_protos = MAKE_CNTR(inst_no,
-                                                      attr_no,
-                                                      5,
-                                                      iface_calls[idx]);
-      p_iface_cntrs->ul.out_octets  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                6,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_ucast   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                7,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_nucast  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                8,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_discards = MAKE_CNTR(inst_no,
-                                                 attr_no,
-                                                 9,
-                                                 iface_calls[idx]);
-      p_iface_cntrs->ul.out_errors  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                10,
-                                                iface_calls[idx]);
-      break;
-    }
-    case 5: {
-      CipEthernetLinkMediaCounters *p_media_cntrs =
-        &g_ethernet_link[idx].media_cntrs;
-
-      ++media_calls[idx]; /* Count successful calls */
-      /* The 1 != mediaCalls[idx] is a concession to the conformance test tool that
-       *  expects the media counters to be zero after a GetAndClear service.
-       * This way we always transmit zeros after reset or a GetAndClear service. */
-      if (1 != media_calls[idx]) {
-        p_media_cntrs->ul.align_errs    = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    0,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.fcs_errs      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    1,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.single_coll   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    2,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.multi_coll    = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    3,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.sqe_test_errs = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    4,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.def_trans     = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    5,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.late_coll     = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    6,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.exc_coll      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    7,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.mac_tx_errs   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    8,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.crs_errs      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    9,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.frame_too_long = MAKE_CNTR(inst_no,
-                                                     attr_no,
-                                                     10,
-                                                     media_calls[idx]);
-        p_media_cntrs->ul.mac_rx_errs   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    11,
-                                                    media_calls[idx]);
-      }
-      break;
+  case 4: {
+    CipEthernetLinkInterfaceCounters *p_iface_cntrs = &g_ethernet_link[idx].interface_cntrs;
+
+    ++iface_calls[idx];  /* Count successful calls */
+    p_iface_cntrs->ul.in_octets   = MAKE_CNTR(inst_no, attr_no,  0, iface_calls[idx]);
+    p_iface_cntrs->ul.in_ucast    = MAKE_CNTR(inst_no, attr_no,  1, iface_calls[idx]);
+    p_iface_cntrs->ul.in_nucast   = MAKE_CNTR(inst_no, attr_no,  2, iface_calls[idx]);
+    p_iface_cntrs->ul.in_discards = MAKE_CNTR(inst_no, attr_no,  3, iface_calls[idx]);
+    p_iface_cntrs->ul.in_errors   = MAKE_CNTR(inst_no, attr_no,  4, iface_calls[idx]);
+    p_iface_cntrs->ul.in_unknown_protos = MAKE_CNTR(inst_no, attr_no, 5, iface_calls[idx]);
+    p_iface_cntrs->ul.out_octets  = MAKE_CNTR(inst_no, attr_no,  6, iface_calls[idx]);
+    p_iface_cntrs->ul.out_ucast   = MAKE_CNTR(inst_no, attr_no,  7, iface_calls[idx]);
+    p_iface_cntrs->ul.out_nucast  = MAKE_CNTR(inst_no, attr_no,  8, iface_calls[idx]);
+    p_iface_cntrs->ul.out_discards = MAKE_CNTR(inst_no, attr_no, 9, iface_calls[idx]);
+    p_iface_cntrs->ul.out_errors  = MAKE_CNTR(inst_no, attr_no, 10, iface_calls[idx]);
+    break;
+  }
+  case 5: {
+    CipEthernetLinkMediaCounters *p_media_cntrs = &g_ethernet_link[idx].media_cntrs;
+
+    ++media_calls[idx];  /* Count successful calls */
+    /* The 1 != mediaCalls[idx] is a concession to the conformance test tool that
+     *  expects the media counters to be zero after a GetAndClear service.
+     * This way we always transmit zeros after reset or a GetAndClear service. */
+    if (1 != media_calls[idx]) {
+      p_media_cntrs->ul.align_errs    = MAKE_CNTR(inst_no, attr_no,  0, media_calls[idx]);
+      p_media_cntrs->ul.fcs_errs      = MAKE_CNTR(inst_no, attr_no,  1, media_calls[idx]);
+      p_media_cntrs->ul.single_coll   = MAKE_CNTR(inst_no, attr_no,  2, media_calls[idx]);
+      p_media_cntrs->ul.multi_coll    = MAKE_CNTR(inst_no, attr_no,  3, media_calls[idx]);
+      p_media_cntrs->ul.sqe_test_errs = MAKE_CNTR(inst_no, attr_no,  4, media_calls[idx]);
+      p_media_cntrs->ul.def_trans     = MAKE_CNTR(inst_no, attr_no,  5, media_calls[idx]);
+      p_media_cntrs->ul.late_coll     = MAKE_CNTR(inst_no, attr_no,  6, media_calls[idx]);
+      p_media_cntrs->ul.exc_coll      = MAKE_CNTR(inst_no, attr_no,  7, media_calls[idx]);
+      p_media_cntrs->ul.mac_tx_errs   = MAKE_CNTR(inst_no, attr_no,  8, media_calls[idx]);
+      p_media_cntrs->ul.crs_errs      = MAKE_CNTR(inst_no, attr_no,  9, media_calls[idx]);
+      p_media_cntrs->ul.frame_too_long= MAKE_CNTR(inst_no, attr_no, 10, media_calls[idx]);
+      p_media_cntrs->ul.mac_rx_errs   = MAKE_CNTR(inst_no, attr_no, 11, media_calls[idx]);
     }
-    default:
-      hadAction = false;
-      break;
+    break;
+  }
+  default:
+    hadAction = false;
+    break;
   }
 
   if (hadAction) {
@@ -203,11 +131,12 @@ EipStatus EthLnkPostGetCallback
   CipInstance *const instance,
   CipAttributeStruct *const attribute,
   CipByte service
-) {
-  CipUdint inst_no = instance->instance_number;
+)
+{
+  CipInstanceNum inst_no = instance->instance_number;
   EipStatus status = kEipStatusOk;
 
-  if ( kEthLinkGetAndClear == (service & 0x7f) ) {
+  if (kEthLinkGetAndClear == (service & 0x7f)) {
     OPENER_TRACE_INFO(
       "Eth Link PostCallback: %s, i %" PRIu32 ", a %" PRIu16 ", s %" PRIu8 "\n",
       instance->cip_class->class_name,
@@ -217,22 +146,22 @@ EipStatus EthLnkPostGetCallback
     /* Clear the instance specific object counters. In this dummy function we only
      *  clear our GetAttributeSingle PreCallback execution counters. */
     switch (attribute->attribute_number) {
-      case 4:
-        iface_calls[inst_no - 1] = 0U;
-        break;
-      case 5:
-        media_calls[inst_no - 1] = 0U;
-        /* This is a concession to the conformance test tool that expects
-         *  the media counters to be zero after a GetAndClear service. */
-        for (int idx = 0; idx < 12; ++idx) {
-          g_ethernet_link[inst_no - 1].media_cntrs.cntr32[idx] = 0U;
-        }
-        break;
-      default:
-        OPENER_TRACE_INFO(
-          "Wrong attribute number %" PRIu16 " in GetAndClear callback\n",
-          attribute->attribute_number);
-        break;
+    case 4:
+      iface_calls[inst_no-1] = 0U;
+      break;
+    case 5:
+      media_calls[inst_no-1] = 0U;
+      /* This is a concession to the conformance test tool that expects
+       *  the media counters to be zero after a GetAndClear service. */
+      for (int idx = 0; idx < 12; ++idx) {
+        g_ethernet_link[inst_no-1].media_cntrs.cntr32[idx] = 0U;
+      }
+      break;
+    default:
+      OPENER_TRACE_INFO(
+        "Wrong attribute number %" PRIu16 " in GetAndClear callback\n",
+        attribute->attribute_number);
+      break;
     }
   }
   return status;

+ 67 - 138
source/src/ports/POSIX/sample_application/ethlinkcbs.c

@@ -52,138 +52,66 @@ static CipUdint media_calls[OPENER_ETHLINK_INSTANCE_CNT];
 /* This is meant as debugging aid and to check if the individual counter     */
 /*  value is sent at the right position in the Get* service response.        */
 
-#define MAKE_CNTR(inst, attr, idx, \
-                  cnt) ( (10000000U * inst) + (100000U * attr) + (1000U * idx) + \
-                         cnt )
+#define MAKE_CNTR(inst, attr, idx, cnt) ((10000000U * inst) + (100000U * attr) + (1000U * idx) + cnt)
 
 EipStatus EthLnkPreGetCallback
 (
   CipInstance *const instance,
   CipAttributeStruct *const attribute,
   CipByte service
-) {
+)
+{
   bool hadAction = true;
   EipStatus status = kEipStatusOk;
 
   CipUint attr_no = attribute->attribute_number;
   /* ATTENTION: Array indices run from 0..(N-1), instance numbers from 1..N */
-  CipUdint inst_no  = instance->instance_number;
-  unsigned idx = inst_no - 1;
+  CipInstanceNum inst_no  = instance->instance_number;
+  unsigned idx = inst_no-1;
   switch (attr_no) {
-    case 4: {
-      CipEthernetLinkInterfaceCounters *p_iface_cntrs =
-        &g_ethernet_link[idx].interface_cntrs;
-
-      ++iface_calls[idx]; /* Count successful calls */
-      p_iface_cntrs->ul.in_octets   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                0,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_ucast    = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                1,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_nucast   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                2,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_discards = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                3,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_errors   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                4,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_unknown_protos = MAKE_CNTR(inst_no,
-                                                      attr_no,
-                                                      5,
-                                                      iface_calls[idx]);
-      p_iface_cntrs->ul.out_octets  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                6,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_ucast   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                7,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_nucast  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                8,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_discards = MAKE_CNTR(inst_no,
-                                                 attr_no,
-                                                 9,
-                                                 iface_calls[idx]);
-      p_iface_cntrs->ul.out_errors  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                10,
-                                                iface_calls[idx]);
-      break;
-    }
-    case 5: {
-      CipEthernetLinkMediaCounters *p_media_cntrs =
-        &g_ethernet_link[idx].media_cntrs;
-
-      ++media_calls[idx]; /* Count successful calls */
-      /* The 1 != mediaCalls[idx] is a concession to the conformance test tool that
-       *  expects the media counters to be zero after a GetAndClear service.
-       * This way we always transmit zeros after reset or a GetAndClear service. */
-      if (1 != media_calls[idx]) {
-        p_media_cntrs->ul.align_errs    = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    0,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.fcs_errs      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    1,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.single_coll   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    2,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.multi_coll    = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    3,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.sqe_test_errs = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    4,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.def_trans     = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    5,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.late_coll     = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    6,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.exc_coll      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    7,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.mac_tx_errs   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    8,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.crs_errs      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    9,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.frame_too_long = MAKE_CNTR(inst_no,
-                                                     attr_no,
-                                                     10,
-                                                     media_calls[idx]);
-        p_media_cntrs->ul.mac_rx_errs   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    11,
-                                                    media_calls[idx]);
-      }
-      break;
+  case 4: {
+    CipEthernetLinkInterfaceCounters *p_iface_cntrs = &g_ethernet_link[idx].interface_cntrs;
+
+    ++iface_calls[idx];  /* Count successful calls */
+    p_iface_cntrs->ul.in_octets   = MAKE_CNTR(inst_no, attr_no,  0, iface_calls[idx]);
+    p_iface_cntrs->ul.in_ucast    = MAKE_CNTR(inst_no, attr_no,  1, iface_calls[idx]);
+    p_iface_cntrs->ul.in_nucast   = MAKE_CNTR(inst_no, attr_no,  2, iface_calls[idx]);
+    p_iface_cntrs->ul.in_discards = MAKE_CNTR(inst_no, attr_no,  3, iface_calls[idx]);
+    p_iface_cntrs->ul.in_errors   = MAKE_CNTR(inst_no, attr_no,  4, iface_calls[idx]);
+    p_iface_cntrs->ul.in_unknown_protos = MAKE_CNTR(inst_no, attr_no, 5, iface_calls[idx]);
+    p_iface_cntrs->ul.out_octets  = MAKE_CNTR(inst_no, attr_no,  6, iface_calls[idx]);
+    p_iface_cntrs->ul.out_ucast   = MAKE_CNTR(inst_no, attr_no,  7, iface_calls[idx]);
+    p_iface_cntrs->ul.out_nucast  = MAKE_CNTR(inst_no, attr_no,  8, iface_calls[idx]);
+    p_iface_cntrs->ul.out_discards = MAKE_CNTR(inst_no, attr_no, 9, iface_calls[idx]);
+    p_iface_cntrs->ul.out_errors  = MAKE_CNTR(inst_no, attr_no, 10, iface_calls[idx]);
+    break;
+  }
+  case 5: {
+    CipEthernetLinkMediaCounters *p_media_cntrs = &g_ethernet_link[idx].media_cntrs;
+
+    ++media_calls[idx];  /* Count successful calls */
+    /* The 1 != mediaCalls[idx] is a concession to the conformance test tool that
+     *  expects the media counters to be zero after a GetAndClear service.
+     * This way we always transmit zeros after reset or a GetAndClear service. */
+    if (1 != media_calls[idx]) {
+      p_media_cntrs->ul.align_errs    = MAKE_CNTR(inst_no, attr_no,  0, media_calls[idx]);
+      p_media_cntrs->ul.fcs_errs      = MAKE_CNTR(inst_no, attr_no,  1, media_calls[idx]);
+      p_media_cntrs->ul.single_coll   = MAKE_CNTR(inst_no, attr_no,  2, media_calls[idx]);
+      p_media_cntrs->ul.multi_coll    = MAKE_CNTR(inst_no, attr_no,  3, media_calls[idx]);
+      p_media_cntrs->ul.sqe_test_errs = MAKE_CNTR(inst_no, attr_no,  4, media_calls[idx]);
+      p_media_cntrs->ul.def_trans     = MAKE_CNTR(inst_no, attr_no,  5, media_calls[idx]);
+      p_media_cntrs->ul.late_coll     = MAKE_CNTR(inst_no, attr_no,  6, media_calls[idx]);
+      p_media_cntrs->ul.exc_coll      = MAKE_CNTR(inst_no, attr_no,  7, media_calls[idx]);
+      p_media_cntrs->ul.mac_tx_errs   = MAKE_CNTR(inst_no, attr_no,  8, media_calls[idx]);
+      p_media_cntrs->ul.crs_errs      = MAKE_CNTR(inst_no, attr_no,  9, media_calls[idx]);
+      p_media_cntrs->ul.frame_too_long= MAKE_CNTR(inst_no, attr_no, 10, media_calls[idx]);
+      p_media_cntrs->ul.mac_rx_errs   = MAKE_CNTR(inst_no, attr_no, 11, media_calls[idx]);
     }
-    default:
-      hadAction = false;
-      break;
+    break;
+  }
+  default:
+    hadAction = false;
+    break;
   }
 
   if (hadAction) {
@@ -203,11 +131,12 @@ EipStatus EthLnkPostGetCallback
   CipInstance *const instance,
   CipAttributeStruct *const attribute,
   CipByte service
-) {
-  CipUdint inst_no = instance->instance_number;
+)
+{
+  CipInstanceNum inst_no = instance->instance_number;
   EipStatus status = kEipStatusOk;
 
-  if ( kEthLinkGetAndClear == (service & 0x7f) ) {
+  if (kEthLinkGetAndClear == (service & 0x7f)) {
     OPENER_TRACE_INFO(
       "Eth Link PostCallback: %s, i %" PRIu32 ", a %" PRIu16 ", s %" PRIu8 "\n",
       instance->cip_class->class_name,
@@ -217,22 +146,22 @@ EipStatus EthLnkPostGetCallback
     /* Clear the instance specific object counters. In this dummy function we only
      *  clear our GetAttributeSingle PreCallback execution counters. */
     switch (attribute->attribute_number) {
-      case 4:
-        iface_calls[inst_no - 1] = 0U;
-        break;
-      case 5:
-        media_calls[inst_no - 1] = 0U;
-        /* This is a concession to the conformance test tool that expects
-         *  the media counters to be zero after a GetAndClear service. */
-        for (int idx = 0; idx < 12; ++idx) {
-          g_ethernet_link[inst_no - 1].media_cntrs.cntr32[idx] = 0U;
-        }
-        break;
-      default:
-        OPENER_TRACE_INFO(
-          "Wrong attribute number %" PRIu16 " in GetAndClear callback\n",
-          attribute->attribute_number);
-        break;
+    case 4:
+      iface_calls[inst_no-1] = 0U;
+      break;
+    case 5:
+      media_calls[inst_no-1] = 0U;
+      /* This is a concession to the conformance test tool that expects
+       *  the media counters to be zero after a GetAndClear service. */
+      for (int idx = 0; idx < 12; ++idx) {
+        g_ethernet_link[inst_no-1].media_cntrs.cntr32[idx] = 0U;
+      }
+      break;
+    default:
+      OPENER_TRACE_INFO(
+        "Wrong attribute number %" PRIu16 " in GetAndClear callback\n",
+        attribute->attribute_number);
+      break;
     }
   }
   return status;

+ 67 - 138
source/src/ports/WIN32/sample_application/ethlinkcbs.c

@@ -52,138 +52,66 @@ static CipUdint media_calls[OPENER_ETHLINK_INSTANCE_CNT];
 /* This is meant as debugging aid and to check if the individual counter     */
 /*  value is sent at the right position in the Get* service response.        */
 
-#define MAKE_CNTR(inst, attr, idx, \
-                  cnt) ( (10000000U * inst) + (100000U * attr) + (1000U * idx) + \
-                         cnt )
+#define MAKE_CNTR(inst, attr, idx, cnt) ((10000000U * inst) + (100000U * attr) + (1000U * idx) + cnt)
 
 EipStatus EthLnkPreGetCallback
 (
   CipInstance *const instance,
   CipAttributeStruct *const attribute,
   CipByte service
-) {
+)
+{
   bool hadAction = true;
   EipStatus status = kEipStatusOk;
 
   CipUint attr_no = attribute->attribute_number;
   /* ATTENTION: Array indices run from 0..(N-1), instance numbers from 1..N */
-  CipUdint inst_no  = instance->instance_number;
-  unsigned idx = inst_no - 1;
+  CipInstanceNum inst_no  = instance->instance_number;
+  unsigned idx = inst_no-1;
   switch (attr_no) {
-    case 4: {
-      CipEthernetLinkInterfaceCounters *p_iface_cntrs =
-        &g_ethernet_link[idx].interface_cntrs;
-
-      ++iface_calls[idx]; /* Count successful calls */
-      p_iface_cntrs->ul.in_octets   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                0,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_ucast    = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                1,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_nucast   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                2,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_discards = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                3,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_errors   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                4,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.in_unknown_protos = MAKE_CNTR(inst_no,
-                                                      attr_no,
-                                                      5,
-                                                      iface_calls[idx]);
-      p_iface_cntrs->ul.out_octets  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                6,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_ucast   = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                7,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_nucast  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                8,
-                                                iface_calls[idx]);
-      p_iface_cntrs->ul.out_discards = MAKE_CNTR(inst_no,
-                                                 attr_no,
-                                                 9,
-                                                 iface_calls[idx]);
-      p_iface_cntrs->ul.out_errors  = MAKE_CNTR(inst_no,
-                                                attr_no,
-                                                10,
-                                                iface_calls[idx]);
-      break;
-    }
-    case 5: {
-      CipEthernetLinkMediaCounters *p_media_cntrs =
-        &g_ethernet_link[idx].media_cntrs;
-
-      ++media_calls[idx]; /* Count successful calls */
-      /* The 1 != mediaCalls[idx] is a concession to the conformance test tool that
-       *  expects the media counters to be zero after a GetAndClear service.
-       * This way we always transmit zeros after reset or a GetAndClear service. */
-      if (1 != media_calls[idx]) {
-        p_media_cntrs->ul.align_errs    = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    0,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.fcs_errs      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    1,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.single_coll   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    2,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.multi_coll    = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    3,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.sqe_test_errs = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    4,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.def_trans     = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    5,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.late_coll     = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    6,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.exc_coll      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    7,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.mac_tx_errs   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    8,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.crs_errs      = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    9,
-                                                    media_calls[idx]);
-        p_media_cntrs->ul.frame_too_long = MAKE_CNTR(inst_no,
-                                                     attr_no,
-                                                     10,
-                                                     media_calls[idx]);
-        p_media_cntrs->ul.mac_rx_errs   = MAKE_CNTR(inst_no,
-                                                    attr_no,
-                                                    11,
-                                                    media_calls[idx]);
-      }
-      break;
+  case 4: {
+    CipEthernetLinkInterfaceCounters *p_iface_cntrs = &g_ethernet_link[idx].interface_cntrs;
+
+    ++iface_calls[idx];  /* Count successful calls */
+    p_iface_cntrs->ul.in_octets   = MAKE_CNTR(inst_no, attr_no,  0, iface_calls[idx]);
+    p_iface_cntrs->ul.in_ucast    = MAKE_CNTR(inst_no, attr_no,  1, iface_calls[idx]);
+    p_iface_cntrs->ul.in_nucast   = MAKE_CNTR(inst_no, attr_no,  2, iface_calls[idx]);
+    p_iface_cntrs->ul.in_discards = MAKE_CNTR(inst_no, attr_no,  3, iface_calls[idx]);
+    p_iface_cntrs->ul.in_errors   = MAKE_CNTR(inst_no, attr_no,  4, iface_calls[idx]);
+    p_iface_cntrs->ul.in_unknown_protos = MAKE_CNTR(inst_no, attr_no, 5, iface_calls[idx]);
+    p_iface_cntrs->ul.out_octets  = MAKE_CNTR(inst_no, attr_no,  6, iface_calls[idx]);
+    p_iface_cntrs->ul.out_ucast   = MAKE_CNTR(inst_no, attr_no,  7, iface_calls[idx]);
+    p_iface_cntrs->ul.out_nucast  = MAKE_CNTR(inst_no, attr_no,  8, iface_calls[idx]);
+    p_iface_cntrs->ul.out_discards = MAKE_CNTR(inst_no, attr_no, 9, iface_calls[idx]);
+    p_iface_cntrs->ul.out_errors  = MAKE_CNTR(inst_no, attr_no, 10, iface_calls[idx]);
+    break;
+  }
+  case 5: {
+    CipEthernetLinkMediaCounters *p_media_cntrs = &g_ethernet_link[idx].media_cntrs;
+
+    ++media_calls[idx];  /* Count successful calls */
+    /* The 1 != mediaCalls[idx] is a concession to the conformance test tool that
+     *  expects the media counters to be zero after a GetAndClear service.
+     * This way we always transmit zeros after reset or a GetAndClear service. */
+    if (1 != media_calls[idx]) {
+      p_media_cntrs->ul.align_errs    = MAKE_CNTR(inst_no, attr_no,  0, media_calls[idx]);
+      p_media_cntrs->ul.fcs_errs      = MAKE_CNTR(inst_no, attr_no,  1, media_calls[idx]);
+      p_media_cntrs->ul.single_coll   = MAKE_CNTR(inst_no, attr_no,  2, media_calls[idx]);
+      p_media_cntrs->ul.multi_coll    = MAKE_CNTR(inst_no, attr_no,  3, media_calls[idx]);
+      p_media_cntrs->ul.sqe_test_errs = MAKE_CNTR(inst_no, attr_no,  4, media_calls[idx]);
+      p_media_cntrs->ul.def_trans     = MAKE_CNTR(inst_no, attr_no,  5, media_calls[idx]);
+      p_media_cntrs->ul.late_coll     = MAKE_CNTR(inst_no, attr_no,  6, media_calls[idx]);
+      p_media_cntrs->ul.exc_coll      = MAKE_CNTR(inst_no, attr_no,  7, media_calls[idx]);
+      p_media_cntrs->ul.mac_tx_errs   = MAKE_CNTR(inst_no, attr_no,  8, media_calls[idx]);
+      p_media_cntrs->ul.crs_errs      = MAKE_CNTR(inst_no, attr_no,  9, media_calls[idx]);
+      p_media_cntrs->ul.frame_too_long= MAKE_CNTR(inst_no, attr_no, 10, media_calls[idx]);
+      p_media_cntrs->ul.mac_rx_errs   = MAKE_CNTR(inst_no, attr_no, 11, media_calls[idx]);
     }
-    default:
-      hadAction = false;
-      break;
+    break;
+  }
+  default:
+    hadAction = false;
+    break;
   }
 
   if (hadAction) {
@@ -203,11 +131,12 @@ EipStatus EthLnkPostGetCallback
   CipInstance *const instance,
   CipAttributeStruct *const attribute,
   CipByte service
-) {
-  CipUdint inst_no = instance->instance_number;
+)
+{
+  CipInstanceNum inst_no = instance->instance_number;
   EipStatus status = kEipStatusOk;
 
-  if ( kEthLinkGetAndClear == (service & 0x7f) ) {
+  if (kEthLinkGetAndClear == (service & 0x7f)) {
     OPENER_TRACE_INFO(
       "Eth Link PostCallback: %s, i %" PRIu32 ", a %" PRIu16 ", s %" PRIu8 "\n",
       instance->cip_class->class_name,
@@ -217,22 +146,22 @@ EipStatus EthLnkPostGetCallback
     /* Clear the instance specific object counters. In this dummy function we only
      *  clear our GetAttributeSingle PreCallback execution counters. */
     switch (attribute->attribute_number) {
-      case 4:
-        iface_calls[inst_no - 1] = 0U;
-        break;
-      case 5:
-        media_calls[inst_no - 1] = 0U;
-        /* This is a concession to the conformance test tool that expects
-         *  the media counters to be zero after a GetAndClear service. */
-        for (int idx = 0; idx < 12; ++idx) {
-          g_ethernet_link[inst_no - 1].media_cntrs.cntr32[idx] = 0U;
-        }
-        break;
-      default:
-        OPENER_TRACE_INFO(
-          "Wrong attribute number %" PRIu16 " in GetAndClear callback\n",
-          attribute->attribute_number);
-        break;
+    case 4:
+      iface_calls[inst_no-1] = 0U;
+      break;
+    case 5:
+      media_calls[inst_no-1] = 0U;
+      /* This is a concession to the conformance test tool that expects
+       *  the media counters to be zero after a GetAndClear service. */
+      for (int idx = 0; idx < 12; ++idx) {
+        g_ethernet_link[inst_no-1].media_cntrs.cntr32[idx] = 0U;
+      }
+      break;
+    default:
+      OPENER_TRACE_INFO(
+        "Wrong attribute number %" PRIu16 " in GetAndClear callback\n",
+        attribute->attribute_number);
+      break;
     }
   }
   return status;

+ 1 - 0
source/src/ports/WIN32/sample_application/sampleapplication.c

@@ -9,6 +9,7 @@
 
 #include "trace.h"
 #include "opener_api.h"
+#include "appcontype.h"
 #include "ciptcpipinterface.h"
 #include "cipqos.h"
 #include "nvdata.h"

+ 32 - 11
source/src/ports/nvdata/nvqos.c

@@ -14,6 +14,7 @@
 #include "nvqos.h"
 
 #include <inttypes.h>
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -32,11 +33,18 @@ int NvQosLoad(CipQosObject *p_qos) {
   int rd_cnt = 0;
   EipStatus eip_status = kEipStatusError;
 
-  CipUsint dscp_urgent = 0;
-  CipUsint dscp_scheduled = 0;
-  CipUsint dscp_high = 0;
-  CipUsint dscp_low = 0;
-  CipUsint dscp_explicit = 0;
+  /*
+   * Data type for these parameters explicitly differs from the specification(CipUsint),
+   * because the required scanf specifier to read that type, "hhu", is not supported
+   * in MinGW. The generic unsigned type is used instead, which is guaranteed to fit
+   * a CipUsint, followed by a check after scanf to ensure valid values before
+   * casting them to CipUsint upon assignment to the output structure.
+   */
+  unsigned int dscp_urgent = 0;
+  unsigned int dscp_scheduled = 0;
+  unsigned int dscp_high = 0;
+  unsigned int dscp_low = 0;
+  unsigned int dscp_explicit = 0;
 
   FILE  *p_file = ConfFileOpen(false, QOS_CFG_NAME);
   if (NULL != p_file) {
@@ -48,7 +56,7 @@ int NvQosLoad(CipQosObject *p_qos) {
 
     /* Read input data */
     rd_cnt = fscanf(p_file,
-                    " %" SCNu8 ", %" SCNu8 ", %" SCNu8 ", %" SCNu8 ", %" SCNu8 "\n",
+                    " %u, %u, %u, %u, %u\n",
                     &dscp_urgent,
                     &dscp_scheduled,
                     &dscp_high,
@@ -64,13 +72,26 @@ int NvQosLoad(CipQosObject *p_qos) {
     eip_status = ConfFileClose(&p_file);
   }
   if (kEipStatusOk == eip_status) {
+
+    /*
+     * Ensure all values read from the configuration file are within the CipUsint range;
+     * see above comments for these dscp_* local variables for details.
+     */
+    if ( (dscp_urgent > UCHAR_MAX)
+         || (dscp_scheduled > UCHAR_MAX)
+         || (dscp_high > UCHAR_MAX)
+         || (dscp_low > UCHAR_MAX)
+         || (dscp_explicit > UCHAR_MAX) ) {
+      rd_cnt = 0;
+    }
+
     /* If all data were read copy them to the global QoS object. */
     if (5 == rd_cnt) {
-      p_qos->dscp.urgent = dscp_urgent;
-      p_qos->dscp.scheduled = dscp_scheduled;
-      p_qos->dscp.high = dscp_high;
-      p_qos->dscp.low = dscp_low;
-      p_qos->dscp.explicit_msg = dscp_explicit;
+      p_qos->dscp.urgent = (CipUsint)dscp_urgent;
+      p_qos->dscp.scheduled = (CipUsint)dscp_scheduled;
+      p_qos->dscp.high = (CipUsint)dscp_high;
+      p_qos->dscp.low = (CipUsint)dscp_low;
+      p_qos->dscp.explicit_msg = (CipUsint)dscp_explicit;
     } else {
       eip_status = kEipStatusError;
     }

+ 11 - 0
source/src/typedefs.h

@@ -68,6 +68,17 @@ static const int kEipInvalidSocket = -1;
 typedef unsigned long MilliSeconds;
 typedef unsigned long long MicroSeconds;
 
+
+/** @brief CIP object instance number type.
+ *
+ * This type is intended for storing values related to identifying or
+ * quantifying object instances, e.g., the maximum number of instances or
+ * a specific instance number. The data type is based on @cite CipVol1,
+ * Table 4-4.2, Attribute IDs 2 and 3.
+ */
+typedef CipUint CipInstanceNum;
+
+
 /**
 
    The following are generally true regarding return status: