Exemplo n.º 1
0
EipStatus
SendUdpData(struct sockaddr_in *pa_pstAddr, int pa_nSockFd,
    EipUint8*pa_acData, EipUint16 pa_nDataLength)
{
  int sentlength;

  sentlength = sendto(pa_nSockFd, (char *) pa_acData, pa_nDataLength, 0,
      (struct sockaddr *) pa_pstAddr, sizeof(*pa_pstAddr));

  if (sentlength < 0)
    {
      OPENER_TRACE_ERR("networkhandler: error with sendto in sendUDPData: %s\n", strerror(errno));
      return kEipStatusError;
    }
  else if (sentlength != pa_nDataLength)
    {
      OPENER_TRACE_WARN("not all data was sent in sendUDPData, sent %d of %d\n",
          sentlength, pa_nDataLength);
      return kEipStatusError;
    }
  else
    return kEipStatusError;
}
Exemplo n.º 2
0
EipUint16 HandleConfigData(CipClass *assembly_class,
                           ConnectionObject *connection_object) {
  EipUint16 connection_manager_status = 0;
  CipInstance *config_instance = GetCipInstance(
      assembly_class, connection_object->connection_path.connection_point[2]);

  if (0 != g_config_data_length) {
    if (ConnectionWithSameConfigPointExists(
        connection_object->connection_path.connection_point[2])) { /* there is a connected connection with the same config point
         * we have to have the same data as already present in the config point*/
      CipByteArray *p = (CipByteArray *) GetCipAttribute(config_instance, 3)
          ->data;
      if (p->length != g_config_data_length) {
        connection_manager_status =
            kConnectionManagerStatusCodeErrorOwnershipConflict;
      } else {
        /*FIXME check if this is correct */
        if (memcmp(p->data, g_config_data_buffer, g_config_data_length)) {
          connection_manager_status =
              kConnectionManagerStatusCodeErrorOwnershipConflict;
        }
      }
    } else {
      /* put the data on the configuration assembly object with the current
       design this can be done rather efficiently */
      if (kEipStatusOk
          != NotifyAssemblyConnectedDataReceived(config_instance,
                                                 g_config_data_buffer,
                                                 g_config_data_length)) {
        OPENER_TRACE_WARN("Configuration data was invalid\n");
        connection_manager_status =
            kConnectionManagerStatusCodeInvalidConfigurationApplicationPath;
      }
    }
  }
  return connection_manager_status;
}
Exemplo n.º 3
0
/*   @brief Creates Common Packet Format structure out of data.
 *   @param data		pointer to data which need to be structured.
 *   @param data_length	length of data in pa_Data.
 *   @param common_packet_format_data	pointer to structure of CPF data item.
 *
 *   @return kEipStatusOk .. success
 * 	       kEipStatusError .. error
 */
EipStatus CreateCommonPacketFormatStructure(
    EipUint8 *data, int data_length,
    CipCommonPacketFormatData *common_packet_format_data) {

  common_packet_format_data->address_info_item[0].type_id = 0;
  common_packet_format_data->address_info_item[1].type_id = 0;

  int length_count = 0;
  common_packet_format_data->item_count = GetIntFromMessage(&data);
  length_count += 2;
  if (common_packet_format_data->item_count >= 1) {
    common_packet_format_data->address_item.type_id = GetIntFromMessage(&data);
    common_packet_format_data->address_item.length = GetIntFromMessage(&data);
    length_count += 4;
    if (common_packet_format_data->address_item.length >= 4) {
      common_packet_format_data->address_item.data.connection_identifier =
          GetDintFromMessage(&data);
      length_count += 4;
    }
    if (common_packet_format_data->address_item.length == 8) {
      common_packet_format_data->address_item.data.sequence_number =
          GetDintFromMessage(&data);
      length_count += 4;
    }
  }
  if (common_packet_format_data->item_count >= 2) {
    common_packet_format_data->data_item.type_id = GetIntFromMessage(&data);
    common_packet_format_data->data_item.length = GetIntFromMessage(&data);
    common_packet_format_data->data_item.data = data;
    data += common_packet_format_data->data_item.length;
    length_count += (4 + common_packet_format_data->data_item.length);
  }
  for (int j = 0; j < (common_packet_format_data->item_count - 2); j++) /* TODO there needs to be a limit check here???*/
  {
    common_packet_format_data->address_info_item[j].type_id = GetIntFromMessage(
        &data);
    length_count += 2;
    if ((common_packet_format_data->address_info_item[j].type_id
        == kCipItemIdSocketAddressInfoOriginatorToTarget)
        || (common_packet_format_data->address_info_item[j].type_id
            == kCipItemIdSocketAddressInfoTargetToOriginator)) {
      common_packet_format_data->address_info_item[j].length =
          GetIntFromMessage(&data);
      common_packet_format_data->address_info_item[j].sin_family =
          GetIntFromMessage(&data);
      common_packet_format_data->address_info_item[j].sin_port =
          GetIntFromMessage(&data);
      common_packet_format_data->address_info_item[j].sin_addr =
          GetDintFromMessage(&data);
      for (int i = 0; i < 8; i++) {
        common_packet_format_data->address_info_item[j].nasin_zero[i] = *data;
        data++;
      }
      length_count += 18;
    } else { /* no sockaddr item found */
      common_packet_format_data->address_info_item[j].type_id = 0; /* mark as not set */
      data -= 2;
    }
  }
  /* set the addressInfoItems to not set if they were not received */
  if (common_packet_format_data->item_count < 4) {
    common_packet_format_data->address_info_item[1].type_id = 0;
    if (common_packet_format_data->item_count < 3) {
      common_packet_format_data->address_info_item[0].type_id = 0;
    }
  }
  if (length_count == data_length) { /* length of data is equal to length of Addr and length of Data */
    return kEipStatusOk;
  } else {
    OPENER_TRACE_WARN(
        "something is wrong with the length in Message Router @ CreateCommonPacketFormatStructure\n");
    if (common_packet_format_data->item_count > 2) {
      /* there is an optional packet in data stream which is not sockaddr item */
      return kEipStatusOk;
    } else { /* something with the length was wrong */
      return kEipStatusError;
    }
  }
}
Exemplo n.º 4
0
EIP_STATUS
setAssemblyAttributeSingle(S_CIP_Instance * pa_pstInstance,
                           S_CIP_MR_Request * pa_pstMRRequest,
                           S_CIP_MR_Response * pa_pstMRResponse)
{


  EIP_UINT8 * acReqData;
  S_CIP_attribute_struct * p;
  OPENER_TRACE_INFO(" setAttribute %d\n", pa_pstMRRequest->RequestPath.AttributNr);

  acReqData = pa_pstMRRequest->Data;

  pa_pstMRResponse->DataLength = 0;
  pa_pstMRResponse->ReplyService = (0x80 | pa_pstMRRequest->Service);
  pa_pstMRResponse->GeneralStatus = CIP_ERROR_ATTRIBUTE_NOT_SUPPORTED;
  pa_pstMRResponse->SizeofAdditionalStatus = 0;


  p = getAttribute(pa_pstInstance,
                   pa_pstMRRequest->RequestPath.AttributNr);

  if((p != 0) && (3 == pa_pstMRRequest->RequestPath.AttributNr))
    {
      if(p->pt2data != 0)
        {
          S_CIP_Byte_Array * pacData = (S_CIP_Byte_Array *) p->pt2data;

          //TODO: check for ATTRIBUTE_SET/GETABLE MASK
          if(true == isConnectedOutputAssembly(pa_pstInstance->nInstanceNr))
            {
              OPENER_TRACE_WARN("Assembly AssemblyAttributeSingle: received data for connected output assembly\n\r");
              pa_pstMRResponse->GeneralStatus = CIP_ERROR_ATTRIBUTE_NOT_SETTABLE;
            }
          else
            {
              if(pa_pstMRRequest->DataLength < pacData->len)
                {
                  OPENER_TRACE_INFO("Assembly setAssemblyAttributeSingle: not enough data received.\r\n");
                  pa_pstMRResponse->GeneralStatus = CIP_ERROR_NOT_ENOUGH_DATA;
                }
              else
                {
                  if(pa_pstMRRequest->DataLength > pacData->len)
                    {
                      OPENER_TRACE_INFO("Assembly setAssemblyAttributeSingle: too much data received.\r\n");
                      pa_pstMRResponse->GeneralStatus = CIP_ERROR_TOO_MUCH_DATA;
                    }
                  else
                    {
                      memcpy(pacData->Data, acReqData, pacData->len);

                      if(IApp_AfterAssemblyDataReceived(pa_pstInstance)
                         != EIP_OK)
                        {
                          /* punt early without updating the status... though I don't know
                           * how much this helps us here, as the attribute's data has already
                           * been overwritten.
                           *
                           * however this is the task of the application side which will
                           * take the data. In addition we have to inform the sender that the
                           * data was not ok.
                           */
                          pa_pstMRResponse->GeneralStatus
                            = CIP_ERROR_INVALID_ATTRIBUTE_VALUE;
                        }
                      else
                        {
                          pa_pstMRResponse->GeneralStatus = CIP_ERROR_SUCCESS;
                        }
                    }
                }
            }
        }
      else
        {
          /* the attribute was zero we are a heartbeat assembly */
          pa_pstMRResponse->GeneralStatus = CIP_ERROR_TOO_MUCH_DATA;
        }
    }

  return EIP_OK_SEND;
}
Exemplo n.º 5
0
EipStatus
handleDataOnTCPSocket(int pa_nSocket)
{
  EipUint8 *rxp;
  long nCheckVal;
  size_t unDataSize;
  long nDataSent;
  int nRemainingBytes = 0;

  /* We will handle just one EIP packet here the rest is done by the select
   * method which will inform us if more data is available in the socket
   because of the current implementation of the main loop this may not be
   the fastest way and a loop here with a non blocking socket would better
   fit*/

  /*Check how many data is here -- read the first four bytes from the connection */
  nCheckVal = recv(pa_nSocket, g_ethernet_communciation_buffer, 4, 0); /*TODO we may have to set the socket to a non blocking socket */

  if (nCheckVal == 0)
    {
      OPENER_TRACE_ERR("networkhandler: connection closed by client: %s\n", strerror(errno));
      return kEipStatusError;
    }
  if (nCheckVal < 0)
    {
      OPENER_TRACE_ERR("networkhandler: error on recv: %s\n", strerror(errno));
      return kEipStatusError;
    }

  rxp = &g_ethernet_communciation_buffer[2]; /* at this place EIP stores the data length */
  unDataSize = GetIntFromMessage(&rxp) + ENCAPSULATION_HEADER_LENGTH - 4; /* -4 is for the 4 bytes we have already read*/
  /* (NOTE this advances the buffer pointer) */
  if (PC_OPENER_ETHERNET_BUFFER_SIZE - 4 < unDataSize)
    { /*TODO can this be handled in a better way?*/
      OPENER_TRACE_ERR("too large packet received will be ignored, will drop the data\n");
      /* Currently we will drop the whole packet */
      nDataSent = PC_OPENER_ETHERNET_BUFFER_SIZE;

      do
        {
          nCheckVal = recv(pa_nSocket, g_ethernet_communciation_buffer, nDataSent, 0);

          if (nCheckVal == 0) /* got error or connection closed by client */
            {
              OPENER_TRACE_ERR("networkhandler: connection closed by client: %s\n", strerror(errno));
              return kEipStatusError;
            }
          if (nCheckVal < 0)
            {
              OPENER_TRACE_ERR("networkhandler: error on recv: %s\n", strerror(errno));
              return kEipStatusError;
            }
          unDataSize -= nCheckVal;
          if ((unDataSize < PC_OPENER_ETHERNET_BUFFER_SIZE)
              && (unDataSize != 0))
            {
              nDataSent = unDataSize;
            }
        }
      while (0 != unDataSize); /*TODO fragile end statement */
      return kEipStatusOk;
    }

  nCheckVal = recv(pa_nSocket, &g_ethernet_communciation_buffer[4], unDataSize, 0);

  if (nCheckVal == 0) /* got error or connection closed by client */
    {
      OPENER_TRACE_ERR("networkhandler: connection closed by client: %s\n", strerror(errno));
      return kEipStatusError;
    }
  if (nCheckVal < 0)
    {
      OPENER_TRACE_ERR("networkhandler: error on recv: %s\n", strerror(errno));
      return kEipStatusError;
    }

  if ((unsigned) nCheckVal == unDataSize)
    {
      /*we got the right amount of data */
      unDataSize += 4;
      /*TODO handle partial packets*/
      OPENER_TRACE_INFO("Data received on tcp:\n");

      g_current_active_tcp_socket = pa_nSocket;

      nCheckVal = HandleReceivedExplictTcpData(pa_nSocket,
          g_ethernet_communciation_buffer, unDataSize, &nRemainingBytes);

      g_current_active_tcp_socket = -1;

      if (nRemainingBytes != 0)
        {
          OPENER_TRACE_WARN("Warning: received packet was to long: %d Bytes left!\n",
              nRemainingBytes);
        }

      if (nCheckVal > 0)
        {
          OPENER_TRACE_INFO("reply sent:\n");

          nDataSent = send(pa_nSocket, (char *) g_ethernet_communciation_buffer,
              nCheckVal, 0);
          if (nDataSent != nCheckVal)
            {
              OPENER_TRACE_WARN("TCP response was not fully sent\n");
            }
        }

      return kEipStatusOk;
    }
  else
    {
      /* we got a fragmented packet currently we cannot handle this will
       * for this we would need a network buffer per TCP socket
       *
       * However with typical packet sizes of EIP this should't be a big issue.
       */
      /*TODO handle fragmented packets */
    }
  return kEipStatusError;
}