Selaa lähdekoodia

fixed Bug 2997845: if CIP Item Id is bad, need to return encapsulation error

Alois Zoitl 16 vuotta sitten
vanhempi
sitoutus
b64175682b
4 muutettua tiedostoa jossa 138 lisäystä ja 116 poistoa
  1. 83 63
      src/enet_encap/cpf.c
  2. 42 38
      src/enet_encap/cpf.h
  3. 4 15
      src/enet_encap/encap.c
  4. 9 0
      src/enet_encap/encap.h

+ 83 - 63
src/enet_encap/cpf.c

@@ -16,90 +16,110 @@
 S_CIP_CPF_Data g_stCPFDataItem;
 
 int
-notifyCPF(EIP_UINT8 * pa_nData, /* message data*/
-EIP_INT16 pa_nData_length, /* data length*/
-EIP_UINT8 * pa_replybuf) /* reply buffer*/
+notifyCPF(struct S_Encapsulation_Data * pa_stReceiveData, /* recieved encap data*/
+EIP_UINT8 * pa_acReplyBuf) /* reply buffer*/
 {
-  EIP_STATUS res;
+  EIP_STATUS nRetVal;
 
-  if ((createCPFstructure(pa_nData, pa_nData_length, &g_stCPFDataItem))
-      == EIP_ERROR)
+  if ((nRetVal = createCPFstructure(pa_stReceiveData->m_acCurrentCommBufferPos,
+      pa_stReceiveData->nData_length, &g_stCPFDataItem)) == EIP_ERROR)
     {
       OPENER_TRACE_ERR("notifyMR: error from createCPFstructure\n");
-      return EIP_ERROR; /* error from createCPFstructure */
     }
-
-  if (g_stCPFDataItem.stAddr_Item.TypeID == CIP_ITEM_ID_NULL) /* check if NullAddressItem received, otherwise it is no unconnected message and should not be here*/
-    { /* found null address item*/
-      if (g_stCPFDataItem.stDataI_Item.TypeID == CIP_ITEM_ID_UNCONNECTEDMESSAGE)
-        { /* unconnected data item received*/
-          res = notifyMR(g_stCPFDataItem.stDataI_Item.Data,
-              g_stCPFDataItem.stDataI_Item.Length);
-          if (res == EIP_ERROR)
-            return EIP_ERROR;
-
-          return assembleLinearMsg(&gMRResponse, &g_stCPFDataItem, pa_replybuf);
+  else
+    {
+      nRetVal = EIP_OK; /* In cases of errors we normaly need to send an error response */
+      if (g_stCPFDataItem.stAddr_Item.TypeID == CIP_ITEM_ID_NULL) /* check if NullAddressItem received, otherwise it is no unconnected message and should not be here*/
+        { /* found null address item*/
+          if (g_stCPFDataItem.stDataI_Item.TypeID
+              == CIP_ITEM_ID_UNCONNECTEDMESSAGE)
+            { /* unconnected data item received*/
+              nRetVal = notifyMR(g_stCPFDataItem.stDataI_Item.Data,
+                  g_stCPFDataItem.stDataI_Item.Length);
+              if (nRetVal != EIP_ERROR)
+                {
+                  nRetVal = assembleLinearMsg(&gMRResponse, &g_stCPFDataItem,
+                      pa_acReplyBuf);
+                }
+            }
+          else
+            {
+              /* wrong data item detected*/
+              OPENER_TRACE_ERR(
+                  "notifyMR: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
+              pa_stReceiveData->nStatus = OPENER_ENCAP_STATUS_INCORRECT_DATA;
+            }
+        }
+      else
+        {
+          OPENER_TRACE_ERR("notifyMR: got something besides the expected CIP_ITEM_ID_NULL\n");
+          pa_stReceiveData->nStatus = OPENER_ENCAP_STATUS_INCORRECT_DATA;
         }
-      /* wrong data item detected*/
-      OPENER_TRACE_ERR(
-          "notifyMR: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
-      return EIP_ERROR;
     }
-
-  OPENER_TRACE_ERR("notifyMR: got something besides the expected CIP_ITEM_ID_NULL\n");
-  return EIP_ERROR;
+  return nRetVal;
 }
 
 int
-notifyConnectedCPF(EIP_UINT8 * pa_nData, /* message data*/
-EIP_INT16 pa_nData_length, /* data length*/
-EIP_UINT8 * pa_replybuf) /* reply buffer*/
+notifyConnectedCPF(struct S_Encapsulation_Data * pa_stReceiveData, /* recieved encap data*/
+EIP_UINT8 * pa_acReplyBuf) /* reply buffer*/
 {
-  EIP_STATUS res;
+  EIP_STATUS nRetVal;
   S_CIP_ConnectionObject *pstConnectionObject;
 
-  if ((createCPFstructure(pa_nData, pa_nData_length, &g_stCPFDataItem))
-      == EIP_ERROR)
+  if ((nRetVal == createCPFstructure(
+      pa_stReceiveData->m_acCurrentCommBufferPos,
+      pa_stReceiveData->nData_length, &g_stCPFDataItem)) == EIP_ERROR)
     {
-      OPENER_TRACE_ERR("notifyMR: error from createCPFstructure\n");
-      return EIP_ERROR; /* error from createCPFstructure*/
+      OPENER_TRACE_ERR("notifyConnectedCPF: error from createCPFstructure\n");
     }
+  else
+    {
+      nRetVal = EIP_ERROR; /* For connected explicit messages status always has to be 0*/
+      if (g_stCPFDataItem.stAddr_Item.TypeID == CIP_ITEM_ID_CONNECTIONBASED) /* check if ConnectedAddressItem received, otherwise it is no connected message and should not be here*/
+        { /* ConnectedAddressItem item */
+          pstConnectionObject = getConnectedObject(
+              g_stCPFDataItem.stAddr_Item.Data.ConnectionIdentifier);
+          if (NULL != pstConnectionObject)
+            {
+              /* reset the watchdog timer */
+              pstConnectionObject->InnacitvityWatchdogTimer
+                  = (pstConnectionObject->O_to_T_RPI / 1000) << (2
+                      + pstConnectionObject->ConnectionTimeoutMultiplier);
 
-  if (g_stCPFDataItem.stAddr_Item.TypeID == CIP_ITEM_ID_CONNECTIONBASED) /* check if ConnectedAddressItem received, otherwise it is no connected message and should not be here*/
-    { /* ConnectedAddressItem item */
-      pstConnectionObject = getConnectedObject(
-          g_stCPFDataItem.stAddr_Item.Data.ConnectionIdentifier);
-      if (pstConnectionObject == 0)
-        return EIP_ERROR;
-
-      /* reset the watchdog timer */
-      pstConnectionObject->InnacitvityWatchdogTimer
-          = (pstConnectionObject->O_to_T_RPI / 1000) << (2
-              + pstConnectionObject->ConnectionTimeoutMultiplier);
-
-      /*TODO check connection id  and sequence count    */
-      if (g_stCPFDataItem.stDataI_Item.TypeID
-          == CIP_ITEM_ID_CONNECTIONTRANSPORTPACKET)
-        { /* connected data item received*/
-          EIP_UINT8 *pnBuf = g_stCPFDataItem.stDataI_Item.Data;
-          g_stCPFDataItem.stAddr_Item.Data.SequenceNumber = (EIP_UINT32) ltohs(
-              &pnBuf);
-          res = notifyMR(pnBuf, g_stCPFDataItem.stDataI_Item.Length - 2);
+              /*TODO check connection id  and sequence count    */
+              if (g_stCPFDataItem.stDataI_Item.TypeID
+                  == CIP_ITEM_ID_CONNECTIONTRANSPORTPACKET)
+                { /* connected data item received*/
+                  EIP_UINT8 *pnBuf = g_stCPFDataItem.stDataI_Item.Data;
+                  g_stCPFDataItem.stAddr_Item.Data.SequenceNumber
+                      = (EIP_UINT32) ltohs(&pnBuf);
+                  nRetVal = notifyMR(pnBuf, g_stCPFDataItem.stDataI_Item.Length
+                      - 2);
 
-          if(EIP_OK_SEND == res)
+                  if (nRetVal != EIP_ERROR)
+                    {
+                      nRetVal = assembleLinearMsg(&gMRResponse,
+                          &g_stCPFDataItem, pa_acReplyBuf);
+                    }
+                }
+              else
+                {
+                  /* wrong data item detected*/
+                  OPENER_TRACE_ERR(
+                      "notifyConnectedCPF: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
+                }
+            }
+          else
             {
-              return assembleLinearMsg(&gMRResponse, &g_stCPFDataItem, pa_replybuf);
+              OPENER_TRACE_ERR("notifyConnectedCPF: connection with given ID could not be found\n");
             }
-          return res;
         }
-      /* wrong data item detected*/
-      OPENER_TRACE_ERR(
-          "notifyMR: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
-      return EIP_ERROR;
+      else
+        {
+          OPENER_TRACE_ERR("notifyConnectedCPF: got something besides the expected CIP_ITEM_ID_NULL\n");
+        }
     }
-
-  OPENER_TRACE_ERR("notifyMR: got something besides the expected CIP_ITEM_ID_NULL\n");
-  return EIP_ERROR;
+  return nRetVal;
 }
 
 /*   INT16 createCPFstructure(INT8 *pa_Data, INT16 pa_DataLength, S_CIP_CPF_Data *pa_CPF_data)

+ 42 - 38
src/enet_encap/cpf.h

@@ -8,6 +8,7 @@
 
 #include "typedefs.h"
 #include "ciptypes.h"
+#include "encap.h"
 
 /*/ CPF is Common Packet Format
  CPF packet := <number of items> {<items>}
@@ -16,7 +17,7 @@
  <TypeID> := two bytes
  <Length> := two bytes
  <data> := <the number of bytes specified by Length>
-*/
+ */
 
 /* define Item ID numbers used for address and data items in CPF structures */
 #define CIP_ITEM_ID_NULL                                0x0000  /* Null Address Item */
@@ -30,65 +31,67 @@
 #define CIP_ITEM_ID_SEQUENCEDADDRESS                    0x8002  /* Sequenced Address item */
 
 typedef struct
-  {
-    EIP_UINT32 ConnectionIdentifier;
-    EIP_UINT32 SequenceNumber;
-  } S_Address_Data;
+{
+  EIP_UINT32 ConnectionIdentifier;
+  EIP_UINT32 SequenceNumber;
+} S_Address_Data;
 
 typedef struct
-  {
-    EIP_UINT16 TypeID;
-    EIP_UINT16 Length;
-    S_Address_Data Data;
-  } S_Address_Item;
+{
+  EIP_UINT16 TypeID;
+  EIP_UINT16 Length;
+  S_Address_Data Data;
+} S_Address_Item;
 
 typedef struct
-  {
-    EIP_UINT16 TypeID;
-    EIP_UINT16 Length;
-    EIP_UINT8 *Data;
-  } S_Data_Item;
+{
+  EIP_UINT16 TypeID;
+  EIP_UINT16 Length;
+  EIP_UINT8 *Data;
+} S_Data_Item;
 
 typedef struct
-  {
-    EIP_UINT16 TypeID;
-    EIP_UINT16 Length;
-    EIP_INT16 nsin_family;
-    EIP_UINT16 nsin_port;
-    EIP_UINT32 nsin_addr;
-    EIP_UINT8 nasin_zero[8];
-  } S_SockAddrInfo_Item;
+{
+  EIP_UINT16 TypeID;
+  EIP_UINT16 Length;
+  EIP_INT16 nsin_family;
+  EIP_UINT16 nsin_port;
+  EIP_UINT32 nsin_addr;
+  EIP_UINT8 nasin_zero[8];
+} S_SockAddrInfo_Item;
 
 /* this one case of a CPF packet is supported:*/
 
 typedef struct
-  {
-    EIP_UINT16 ItemCount;
-    S_Address_Item stAddr_Item;
-    S_Data_Item stDataI_Item;
-    S_SockAddrInfo_Item AddrInfo[2];
-  } S_CIP_CPF_Data;
+{
+  EIP_UINT16 ItemCount;
+  S_Address_Item stAddr_Item;
+  S_Data_Item stDataI_Item;
+  S_SockAddrInfo_Item AddrInfo[2];
+} S_CIP_CPF_Data;
 
 /*! \ingroup ENCAP
  * Parse the CPF data from a received unconnected explicit message and
  * hand the data on to the message router 
  *
- * @param  pa_nData message data
- * @param  pa_nData_length data length
- * @param  pa_replybuf reply buffer
+ * @param  pa_stReceiveData pointer to the encapsulation structure with the received message
+ * @param  pa_acReplyBuf reply buffer
+ * @return number of bytes to be sent back. < 0 if nothing should be sent
  */
-int notifyCPF(EIP_UINT8 * pa_nData, EIP_INT16 pa_nData_length, EIP_UINT8 * pa_replybuf); 
+int notifyCPF(struct S_Encapsulation_Data * pa_stReceiveData,
+    EIP_UINT8 * pa_acReplyBuf);
 
 /*! \ingroup ENCAP
  * Parse the CPF data from a received connected explicit message, check
  * the connection status, update any timers, and hand the data on to 
  * the message router 
  *
- * @param  pa_nData message data
- * @param  pa_nData_length data length
- * @param  pa_replybuf reply buffer
+ * @param  pa_stReceiveData pointer to the encapsulation structure with the received message
+ * @param  pa_acReplyBuf reply buffer
+ * @return number of bytes to be sent back. < 0 if nothing should be sent
  */
-int notifyConnectedCPF(EIP_UINT8 * pa_nData, EIP_INT16 pa_nData_length, EIP_UINT8 * pa_replybuf);
+int notifyConnectedCPF(struct S_Encapsulation_Data * pa_stReceiveData,
+    EIP_UINT8 * pa_acReplyBuf);
 
 /*! \ingroup ENCAP
  *  Create CPF structure out of the received data.
@@ -99,7 +102,8 @@ int notifyConnectedCPF(EIP_UINT8 * pa_nData, EIP_INT16 pa_nData_length, EIP_UINT
  * 	       EIP_OK .. success
  * 	       EIP_ERROR .. error
  */
-EIP_STATUS createCPFstructure(EIP_UINT8 * pa_Data, int pa_DataLength, S_CIP_CPF_Data * pa_CPF_data);
+EIP_STATUS createCPFstructure(EIP_UINT8 * pa_Data, int pa_DataLength,
+    S_CIP_CPF_Data * pa_CPF_data);
 
 /*! \ingroup ENCAP
  * Copy data from MRResponse struct and CPFDataItem into linear memory in pa_msg for transmission over in encapsulation.

+ 4 - 15
src/enet_encap/encap.c

@@ -27,15 +27,6 @@
 #define COMMAND_SENDRRDATA              0x006F
 #define COMMAND_SENDUNITDATA            0x0070
 
-/* definition of status codes in encapsulation protocol */
-#define OPENER_ENCAP_STATUS_SUCCESS                     0x0000
-#define OPENER_ENCAP_STATUS_INVALID_COMMAND             0x0001
-#define OPENER_ENCAP_STATUS_INSUFFICIENT_MEM            0x0002
-#define OPENER_ENCAP_STATUS_INCORRECT_DATA              0x0003
-#define OPENER_ENCAP_STATUS_INVALID_SESSION_HANDLE      0x0064
-#define OPENER_ENCAP_STATUS_INVALID_LENGTH              0x0065
-#define OPENER_ENCAP_STATUS_UNSUPPORTED_PROTOCOL        0x0069  
-
 /* definition of capability flags */
 #define SUPPORT_CIP_TCP                 0x0020
 #define SUPPORT_CIP_UDP_CLASS_0_OR_1    0x0100
@@ -191,7 +182,7 @@ int *pa_nRemainingBytes) /* return how many bytes of the input are left over aft
             break;
             }
           /* if nRetVal is greater then 0 data has to be sent */
-          if(0 < nRetVal)
+          if(0 <= nRetVal)
             {
               nRetVal = encapsulate_data(&sEncapData);
             }  
@@ -406,8 +397,7 @@ SendUnitData(struct S_Encapsulation_Data * pa_stReceiveData)
   if (EIP_ERROR != checkRegisteredSessions(pa_stReceiveData)) /* see if the EIP session is registered*/
     {
       nSendSize
-      = notifyConnectedCPF(pa_stReceiveData->m_acCurrentCommBufferPos,
-          pa_stReceiveData->nData_length,
+      = notifyConnectedCPF(pa_stReceiveData,
           &pa_stReceiveData->m_acCommBufferStart[ENCAPSULATION_HEADER_LENGTH]);
 
       if (0 < nSendSize)
@@ -443,11 +433,10 @@ SendRRData(struct S_Encapsulation_Data * pa_stReceiveData)
   if (EIP_ERROR != checkRegisteredSessions(pa_stReceiveData)) /* see if the EIP session is registered*/
     {
       nSendSize
-      = notifyCPF(pa_stReceiveData->m_acCurrentCommBufferPos,
-          pa_stReceiveData->nData_length,
+      = notifyCPF(pa_stReceiveData,
           &pa_stReceiveData->m_acCommBufferStart[ENCAPSULATION_HEADER_LENGTH]);
 
-      if (nSendSize > 0)
+      if (nSendSize >= 0)
         { /* need to send reply */
           pa_stReceiveData->nData_length = nSendSize;
         }

+ 9 - 0
src/enet_encap/encap.h

@@ -18,6 +18,15 @@
 #define ENCAPSULATION_HEADER_LENGTH 24
 #define OPENER_ETHERNET_PORT 0xAF12
 
+/* definition of status codes in encapsulation protocol */
+#define OPENER_ENCAP_STATUS_SUCCESS                     0x0000
+#define OPENER_ENCAP_STATUS_INVALID_COMMAND             0x0001
+#define OPENER_ENCAP_STATUS_INSUFFICIENT_MEM            0x0002
+#define OPENER_ENCAP_STATUS_INCORRECT_DATA              0x0003
+#define OPENER_ENCAP_STATUS_INVALID_SESSION_HANDLE      0x0064
+#define OPENER_ENCAP_STATUS_INVALID_LENGTH              0x0065
+#define OPENER_ENCAP_STATUS_UNSUPPORTED_PROTOCOL        0x0069
+
 
 /*** structs ***/
 struct S_Encapsulation_Data