|
@@ -77,39 +77,26 @@ EncapsulationServiceInformation g_service_information;
|
|
|
|
|
|
|
|
int g_registered_sessions[OPENER_NUMBER_OF_SUPPORTED_SESSIONS];
|
|
int g_registered_sessions[OPENER_NUMBER_OF_SUPPORTED_SESSIONS];
|
|
|
|
|
|
|
|
-DelayedEncapsulationMessage g_delayed_encapsulation_messages[
|
|
|
|
|
- ENCAP_NUMBER_OF_SUPPORTED_DELAYED_ENCAP_MESSAGES];
|
|
|
|
|
|
|
+DelayedEncapsulationMessage g_delayed_encapsulation_messages[ENCAP_NUMBER_OF_SUPPORTED_DELAYED_ENCAP_MESSAGES];
|
|
|
|
|
|
|
|
/*** private functions ***/
|
|
/*** private functions ***/
|
|
|
-void HandleReceivedListIdentityCommandTcp(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
+void HandleReceivedListIdentityCommandTcp(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
|
-void HandleReceivedListIdentityCommandUdp(const int socket,
|
|
|
|
|
- const struct sockaddr_in *const from_address,
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
+void HandleReceivedListIdentityCommandUdp(const int socket, const struct sockaddr_in *const from_address, const EncapsulationData *const receive_data,
|
|
|
|
|
+ ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
|
-EipStatus HandleReceivedUnregisterSessionCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
+EipStatus HandleReceivedUnregisterSessionCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
|
-EipStatus HandleReceivedSendUnitDataCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- const struct sockaddr *const originator_address,
|
|
|
|
|
- ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
+EipStatus HandleReceivedSendUnitDataCommand(const EncapsulationData *const receive_data, const struct sockaddr *const originator_address,
|
|
|
|
|
+ ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
|
-EipStatus HandleReceivedInvalidCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
+EipStatus HandleReceivedInvalidCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message);
|
|
|
|
|
|
|
|
int GetFreeSessionIndex(void);
|
|
int GetFreeSessionIndex(void);
|
|
|
|
|
|
|
|
-SessionStatus CheckRegisteredSessions(
|
|
|
|
|
- const EncapsulationData *const receive_data);
|
|
|
|
|
|
|
+SessionStatus CheckRegisteredSessions(const EncapsulationData *const receive_data);
|
|
|
|
|
|
|
|
-void DetermineDelayTime(const EipByte *buffer_start,
|
|
|
|
|
- DelayedEncapsulationMessage *const delayed_message_buffer);
|
|
|
|
|
|
|
+void DetermineDelayTime(const EipByte *buffer_start, DelayedEncapsulationMessage *const delayed_message_buffer);
|
|
|
|
|
|
|
|
/* @brief Initializes session list and interface information. */
|
|
/* @brief Initializes session list and interface information. */
|
|
|
void EncapsulationInit(void) {
|
|
void EncapsulationInit(void) {
|
|
@@ -134,27 +121,19 @@ void EncapsulationInit(void) {
|
|
|
g_service_information.type_code = kCipItemIdListServiceResponse;
|
|
g_service_information.type_code = kCipItemIdListServiceResponse;
|
|
|
g_service_information.length = sizeof(g_service_information);
|
|
g_service_information.length = sizeof(g_service_information);
|
|
|
g_service_information.encapsulation_protocol_version = 1;
|
|
g_service_information.encapsulation_protocol_version = 1;
|
|
|
- g_service_information.capability_flags = kCapabilityFlagsCipTcp |
|
|
|
|
|
- kCapabilityFlagsCipUdpClass0or1;
|
|
|
|
|
- snprintf( (char *) g_service_information.name_of_service,
|
|
|
|
|
- sizeof(g_service_information.name_of_service), "Communications" );
|
|
|
|
|
|
|
+ g_service_information.capability_flags = kCapabilityFlagsCipTcp | kCapabilityFlagsCipUdpClass0or1;
|
|
|
|
|
+ snprintf((char*) g_service_information.name_of_service, sizeof(g_service_information.name_of_service), "Communications");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-EipStatus HandleReceivedExplictTcpData(int socket,
|
|
|
|
|
- EipUint8 *buffer,
|
|
|
|
|
- size_t length,
|
|
|
|
|
- int *remaining_bytes,
|
|
|
|
|
- struct sockaddr *originator_address,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+EipStatus HandleReceivedExplictTcpData(int socket, EipUint8 *buffer, size_t length, int *remaining_bytes, struct sockaddr *originator_address,
|
|
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
OPENER_TRACE_INFO("Handles data for TCP socket: %d\n", socket);
|
|
OPENER_TRACE_INFO("Handles data for TCP socket: %d\n", socket);
|
|
|
EipStatus return_value = kEipStatusOk;
|
|
EipStatus return_value = kEipStatusOk;
|
|
|
EncapsulationData encapsulation_data = { 0 };
|
|
EncapsulationData encapsulation_data = { 0 };
|
|
|
/* eat the encapsulation header*/
|
|
/* eat the encapsulation header*/
|
|
|
/* the structure contains a pointer to the encapsulated data*/
|
|
/* the structure contains a pointer to the encapsulated data*/
|
|
|
/* returns how many bytes are left after the encapsulated data*/
|
|
/* returns how many bytes are left after the encapsulated data*/
|
|
|
- *remaining_bytes = CreateEncapsulationStructure(buffer,
|
|
|
|
|
- length,
|
|
|
|
|
- &encapsulation_data);
|
|
|
|
|
|
|
+ *remaining_bytes = CreateEncapsulationStructure(buffer, length, &encapsulation_data);
|
|
|
|
|
|
|
|
if(kEncapsulationHeaderOptionsFlag == encapsulation_data.options) /*TODO generate appropriate error response*/
|
|
if(kEncapsulationHeaderOptionsFlag == encapsulation_data.options) /*TODO generate appropriate error response*/
|
|
|
{
|
|
{
|
|
@@ -164,7 +143,7 @@ EipStatus HandleReceivedExplictTcpData(int socket,
|
|
|
encapsulation_data.status = kEncapsulationProtocolSuccess;
|
|
encapsulation_data.status = kEncapsulationProtocolSuccess;
|
|
|
return_value = kEipStatusOkSend;
|
|
return_value = kEipStatusOkSend;
|
|
|
/* most of these functions need a reply to be send */
|
|
/* most of these functions need a reply to be send */
|
|
|
- switch(encapsulation_data.command_code) {
|
|
|
|
|
|
|
+ switch(encapsulation_data.command_code){
|
|
|
case (kEncapsulationCommandNoOperation):
|
|
case (kEncapsulationCommandNoOperation):
|
|
|
OPENER_TRACE_INFO("NOP\n");
|
|
OPENER_TRACE_INFO("NOP\n");
|
|
|
/* NOP needs no reply and does nothing */
|
|
/* NOP needs no reply and does nothing */
|
|
@@ -173,54 +152,41 @@ EipStatus HandleReceivedExplictTcpData(int socket,
|
|
|
|
|
|
|
|
case (kEncapsulationCommandListServices):
|
|
case (kEncapsulationCommandListServices):
|
|
|
OPENER_TRACE_INFO("List services\n");
|
|
OPENER_TRACE_INFO("List services\n");
|
|
|
- HandleReceivedListServicesCommand(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListServicesCommand(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandListIdentity):
|
|
case (kEncapsulationCommandListIdentity):
|
|
|
OPENER_TRACE_INFO("List identity\n");
|
|
OPENER_TRACE_INFO("List identity\n");
|
|
|
- HandleReceivedListIdentityCommandTcp(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListIdentityCommandTcp(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandListInterfaces):
|
|
case (kEncapsulationCommandListInterfaces):
|
|
|
OPENER_TRACE_INFO("List interfaces\n");
|
|
OPENER_TRACE_INFO("List interfaces\n");
|
|
|
- HandleReceivedListInterfacesCommand(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListInterfacesCommand(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandRegisterSession):
|
|
case (kEncapsulationCommandRegisterSession):
|
|
|
OPENER_TRACE_INFO("Register session\n");
|
|
OPENER_TRACE_INFO("Register session\n");
|
|
|
- HandleReceivedRegisterSessionCommand(socket,
|
|
|
|
|
- &encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedRegisterSessionCommand(socket, &encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandUnregisterSession):
|
|
case (kEncapsulationCommandUnregisterSession):
|
|
|
OPENER_TRACE_INFO("unregister session\n");
|
|
OPENER_TRACE_INFO("unregister session\n");
|
|
|
- return_value = HandleReceivedUnregisterSessionCommand(
|
|
|
|
|
- &encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ return_value = HandleReceivedUnregisterSessionCommand(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandSendRequestReplyData):
|
|
case (kEncapsulationCommandSendRequestReplyData):
|
|
|
OPENER_TRACE_INFO("Send Request/Reply Data\n");
|
|
OPENER_TRACE_INFO("Send Request/Reply Data\n");
|
|
|
- return_value = HandleReceivedSendRequestResponseDataCommand(
|
|
|
|
|
- &encapsulation_data,
|
|
|
|
|
- originator_address,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ return_value = HandleReceivedSendRequestResponseDataCommand(&encapsulation_data, originator_address, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandSendUnitData):
|
|
case (kEncapsulationCommandSendUnitData):
|
|
|
OPENER_TRACE_INFO("Send Unit Data\n");
|
|
OPENER_TRACE_INFO("Send Unit Data\n");
|
|
|
- return_value = HandleReceivedSendUnitDataCommand(&encapsulation_data,
|
|
|
|
|
- originator_address,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ return_value = HandleReceivedSendUnitDataCommand(&encapsulation_data, originator_address, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
default:
|
|
|
- return_value = HandleReceivedInvalidCommand(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ return_value = HandleReceivedInvalidCommand(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -229,21 +195,23 @@ EipStatus HandleReceivedExplictTcpData(int socket,
|
|
|
return return_value;
|
|
return return_value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-EipStatus HandleReceivedExplictUdpData(const int socket,
|
|
|
|
|
- const struct sockaddr_in *from_address,
|
|
|
|
|
- const EipUint8 *buffer,
|
|
|
|
|
- const size_t buffer_length,
|
|
|
|
|
- int *number_of_remaining_bytes,
|
|
|
|
|
- bool unicast,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+EipStatus HandleReceivedExplictUdpData(const int socket, const struct sockaddr_in *from_address, const EipUint8 *buffer, const size_t buffer_length,
|
|
|
|
|
+ int *number_of_remaining_bytes,
|
|
|
|
|
+ bool unicast, ENIPMessage *const outgoing_message) {
|
|
|
EipStatus return_value = kEipStatusOk;
|
|
EipStatus return_value = kEipStatusOk;
|
|
|
EncapsulationData encapsulation_data = { 0 };
|
|
EncapsulationData encapsulation_data = { 0 };
|
|
|
/* eat the encapsulation header*/
|
|
/* eat the encapsulation header*/
|
|
|
/* the structure contains a pointer to the encapsulated data*/
|
|
/* the structure contains a pointer to the encapsulated data*/
|
|
|
/* returns how many bytes are left after the encapsulated data*/
|
|
/* returns how many bytes are left after the encapsulated data*/
|
|
|
- *number_of_remaining_bytes = CreateEncapsulationStructure(buffer,
|
|
|
|
|
- buffer_length,
|
|
|
|
|
- &encapsulation_data);
|
|
|
|
|
|
|
+ int remaining_bytes = CreateEncapsulationStructure(buffer, buffer_length, &encapsulation_data);
|
|
|
|
|
+
|
|
|
|
|
+ if(remaining_bytes >= 0) {
|
|
|
|
|
+ *number_of_remaining_bytes = remaining_bytes;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ OPENER_TRACE_ERR("Fragmented packet detected! Fragmented packets are not supported!\n");
|
|
|
|
|
+ *number_of_remaining_bytes = 0;
|
|
|
|
|
+ return kEipStatusError;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if(kEncapsulationHeaderOptionsFlag == encapsulation_data.options) /*TODO generate appropriate error response*/
|
|
if(kEncapsulationHeaderOptionsFlag == encapsulation_data.options) /*TODO generate appropriate error response*/
|
|
|
{
|
|
{
|
|
@@ -253,23 +221,18 @@ EipStatus HandleReceivedExplictUdpData(const int socket,
|
|
|
encapsulation_data.status = kEncapsulationProtocolSuccess;
|
|
encapsulation_data.status = kEncapsulationProtocolSuccess;
|
|
|
return_value = kEipStatusOkSend;
|
|
return_value = kEipStatusOkSend;
|
|
|
/* most of these functions need a reply to be send */
|
|
/* most of these functions need a reply to be send */
|
|
|
- switch(encapsulation_data.command_code) {
|
|
|
|
|
|
|
+ switch(encapsulation_data.command_code){
|
|
|
case (kEncapsulationCommandListServices):
|
|
case (kEncapsulationCommandListServices):
|
|
|
OPENER_TRACE_INFO("List Service\n");
|
|
OPENER_TRACE_INFO("List Service\n");
|
|
|
- HandleReceivedListServicesCommand(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListServicesCommand(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case (kEncapsulationCommandListIdentity):
|
|
case (kEncapsulationCommandListIdentity):
|
|
|
OPENER_TRACE_INFO("List Identity\n");
|
|
OPENER_TRACE_INFO("List Identity\n");
|
|
|
if(unicast == true) {
|
|
if(unicast == true) {
|
|
|
- HandleReceivedListIdentityCommandTcp(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListIdentityCommandTcp(&encapsulation_data, outgoing_message);
|
|
|
} else {
|
|
} else {
|
|
|
- HandleReceivedListIdentityCommandUdp(socket,
|
|
|
|
|
- from_address,
|
|
|
|
|
- &encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListIdentityCommandUdp(socket, from_address, &encapsulation_data, outgoing_message);
|
|
|
/* as the response has to be delayed do not send it now */
|
|
/* as the response has to be delayed do not send it now */
|
|
|
return_value = kEipStatusOk;
|
|
return_value = kEipStatusOk;
|
|
|
}
|
|
}
|
|
@@ -277,11 +240,10 @@ EipStatus HandleReceivedExplictUdpData(const int socket,
|
|
|
|
|
|
|
|
case (kEncapsulationCommandListInterfaces):
|
|
case (kEncapsulationCommandListInterfaces):
|
|
|
OPENER_TRACE_INFO("List Interfaces\n");
|
|
OPENER_TRACE_INFO("List Interfaces\n");
|
|
|
- HandleReceivedListInterfacesCommand(&encapsulation_data,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ HandleReceivedListInterfacesCommand(&encapsulation_data, outgoing_message);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
- /* The following commands are not to be sent via UDP */
|
|
|
|
|
|
|
+ /* The following commands are not to be sent via UDP */
|
|
|
case (kEncapsulationCommandNoOperation):
|
|
case (kEncapsulationCommandNoOperation):
|
|
|
case (kEncapsulationCommandRegisterSession):
|
|
case (kEncapsulationCommandRegisterSession):
|
|
|
case (kEncapsulationCommandUnregisterSession):
|
|
case (kEncapsulationCommandUnregisterSession):
|
|
@@ -304,18 +266,13 @@ void SkipEncapsulationHeader(ENIPMessage *const outgoing_message) {
|
|
|
outgoing_message->current_message_position += ENCAPSULATION_HEADER_LENGTH;
|
|
outgoing_message->current_message_position += ENCAPSULATION_HEADER_LENGTH;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void GenerateEncapsulationHeader(const EncapsulationData *const receive_data,
|
|
|
|
|
- const size_t command_specific_data_length,
|
|
|
|
|
- const size_t session_handle,
|
|
|
|
|
- const EncapsulationProtocolErrorCode encapsulation_protocol_status,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void GenerateEncapsulationHeader(const EncapsulationData *const receive_data, const size_t command_specific_data_length, const size_t session_handle,
|
|
|
|
|
+ const EncapsulationProtocolErrorCode encapsulation_protocol_status, ENIPMessage *const outgoing_message) {
|
|
|
AddIntToMessage(receive_data->command_code, outgoing_message);
|
|
AddIntToMessage(receive_data->command_code, outgoing_message);
|
|
|
AddIntToMessage(command_specific_data_length, outgoing_message);
|
|
AddIntToMessage(command_specific_data_length, outgoing_message);
|
|
|
AddDintToMessage(session_handle, outgoing_message); //Session handle
|
|
AddDintToMessage(session_handle, outgoing_message); //Session handle
|
|
|
AddDintToMessage(encapsulation_protocol_status, outgoing_message); //Status
|
|
AddDintToMessage(encapsulation_protocol_status, outgoing_message); //Status
|
|
|
- memcpy(outgoing_message->current_message_position,
|
|
|
|
|
- receive_data->sender_context,
|
|
|
|
|
- kSenderContextSize); // sender context
|
|
|
|
|
|
|
+ memcpy(outgoing_message->current_message_position, receive_data->sender_context, kSenderContextSize); // sender context
|
|
|
outgoing_message->current_message_position += kSenderContextSize;
|
|
outgoing_message->current_message_position += kSenderContextSize;
|
|
|
outgoing_message->used_message_length += kSenderContextSize;
|
|
outgoing_message->used_message_length += kSenderContextSize;
|
|
|
AddDintToMessage(0, outgoing_message); // options
|
|
AddDintToMessage(0, outgoing_message); // options
|
|
@@ -325,66 +282,45 @@ void GenerateEncapsulationHeader(const EncapsulationData *const receive_data,
|
|
|
* @param receive_data pointer to structure with received data
|
|
* @param receive_data pointer to structure with received data
|
|
|
* @param outgoing_message The outgoing ENIP message
|
|
* @param outgoing_message The outgoing ENIP message
|
|
|
*/
|
|
*/
|
|
|
-void HandleReceivedListServicesCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void HandleReceivedListServicesCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
|
/* Create encapsulation header */
|
|
/* Create encapsulation header */
|
|
|
- const size_t kListServicesCommandSpecificDataLength = sizeof(CipUint) +
|
|
|
|
|
- sizeof(
|
|
|
|
|
- g_service_information);
|
|
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- kListServicesCommandSpecificDataLength,
|
|
|
|
|
- 0,
|
|
|
|
|
- /* Session handle will be ignored */
|
|
|
|
|
- kEncapsulationProtocolSuccess,
|
|
|
|
|
- /* Protocol status */
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ const size_t kListServicesCommandSpecificDataLength = sizeof(CipUint) + sizeof(g_service_information);
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, kListServicesCommandSpecificDataLength, 0,
|
|
|
|
|
+ /* Session handle will be ignored */
|
|
|
|
|
+ kEncapsulationProtocolSuccess,
|
|
|
|
|
+ /* Protocol status */
|
|
|
|
|
+ outgoing_message);
|
|
|
|
|
|
|
|
/* Command specific data copy Interface data to msg for sending */
|
|
/* Command specific data copy Interface data to msg for sending */
|
|
|
AddIntToMessage(1, outgoing_message); // Item count
|
|
AddIntToMessage(1, outgoing_message); // Item count
|
|
|
AddIntToMessage(g_service_information.type_code, outgoing_message);
|
|
AddIntToMessage(g_service_information.type_code, outgoing_message);
|
|
|
- AddIntToMessage( (EipUint16) (g_service_information.length - 4),
|
|
|
|
|
- outgoing_message );
|
|
|
|
|
- AddIntToMessage(g_service_information.encapsulation_protocol_version,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ AddIntToMessage((EipUint16) (g_service_information.length - 4), outgoing_message);
|
|
|
|
|
+ AddIntToMessage(g_service_information.encapsulation_protocol_version, outgoing_message);
|
|
|
AddIntToMessage(g_service_information.capability_flags, outgoing_message);
|
|
AddIntToMessage(g_service_information.capability_flags, outgoing_message);
|
|
|
- memcpy(outgoing_message->current_message_position,
|
|
|
|
|
- g_service_information.name_of_service,
|
|
|
|
|
- sizeof(g_service_information.name_of_service) );
|
|
|
|
|
- outgoing_message->current_message_position +=
|
|
|
|
|
- sizeof(g_service_information.name_of_service);
|
|
|
|
|
- outgoing_message->used_message_length +=
|
|
|
|
|
- sizeof(g_service_information.name_of_service);
|
|
|
|
|
|
|
+ memcpy(outgoing_message->current_message_position, g_service_information.name_of_service, sizeof(g_service_information.name_of_service));
|
|
|
|
|
+ outgoing_message->current_message_position += sizeof(g_service_information.name_of_service);
|
|
|
|
|
+ outgoing_message->used_message_length += sizeof(g_service_information.name_of_service);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HandleReceivedListInterfacesCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void HandleReceivedListInterfacesCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
|
/* Encapsulation header */
|
|
/* Encapsulation header */
|
|
|
const size_t kListInterfacesCommandSpecificDataLength = sizeof(CipUint);
|
|
const size_t kListInterfacesCommandSpecificDataLength = sizeof(CipUint);
|
|
|
|
|
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- kListInterfacesCommandSpecificDataLength,
|
|
|
|
|
- 0,
|
|
|
|
|
- /* Session handle will be ignored */
|
|
|
|
|
- kEncapsulationProtocolSuccess,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, kListInterfacesCommandSpecificDataLength, 0,
|
|
|
|
|
+ /* Session handle will be ignored */
|
|
|
|
|
+ kEncapsulationProtocolSuccess, outgoing_message);
|
|
|
/* Command specific data */
|
|
/* Command specific data */
|
|
|
AddIntToMessage(0x0000, outgoing_message); /* Set Item Count to 0: no Target Items follow. */
|
|
AddIntToMessage(0x0000, outgoing_message); /* Set Item Count to 0: no Target Items follow. */
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HandleReceivedListIdentityCommandTcp(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void HandleReceivedListIdentityCommandTcp(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
EncapsulateListIdentityResponseMessage(receive_data, outgoing_message);
|
|
EncapsulateListIdentityResponseMessage(receive_data, outgoing_message);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void HandleReceivedListIdentityCommandUdp(const int socket,
|
|
|
|
|
- const struct sockaddr_in *const from_address,
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void HandleReceivedListIdentityCommandUdp(const int socket, const struct sockaddr_in *const from_address, const EncapsulationData *const receive_data,
|
|
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
DelayedEncapsulationMessage *delayed_message_buffer = NULL;
|
|
DelayedEncapsulationMessage *delayed_message_buffer = NULL;
|
|
|
ENIPMessage *p_outgoing_message = NULL;
|
|
ENIPMessage *p_outgoing_message = NULL;
|
|
|
|
|
|
|
@@ -400,22 +336,17 @@ void HandleReceivedListIdentityCommandUdp(const int socket,
|
|
|
|
|
|
|
|
if(NULL != delayed_message_buffer) {
|
|
if(NULL != delayed_message_buffer) {
|
|
|
delayed_message_buffer->socket = socket;
|
|
delayed_message_buffer->socket = socket;
|
|
|
- memcpy( (&delayed_message_buffer->receiver), from_address,
|
|
|
|
|
- sizeof(struct sockaddr_in) );
|
|
|
|
|
|
|
+ memcpy((&delayed_message_buffer->receiver), from_address, sizeof(struct sockaddr_in));
|
|
|
|
|
|
|
|
- DetermineDelayTime(receive_data->communication_buffer_start,
|
|
|
|
|
- delayed_message_buffer);
|
|
|
|
|
|
|
+ DetermineDelayTime(receive_data->communication_buffer_start, delayed_message_buffer);
|
|
|
|
|
|
|
|
EncapsulateListIdentityResponseMessage(receive_data, p_outgoing_message);
|
|
EncapsulateListIdentityResponseMessage(receive_data, p_outgoing_message);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CipUint ListIdentityGetCipIdentityItemLength() {
|
|
CipUint ListIdentityGetCipIdentityItemLength() {
|
|
|
- return sizeof(CipUint) + sizeof(CipInt) + sizeof(CipUint) + sizeof(CipUdint) +
|
|
|
|
|
- 8 * sizeof(CipUsint) + sizeof(CipUint) + sizeof(CipUint) +
|
|
|
|
|
- sizeof(CipUint)
|
|
|
|
|
- + 2 * sizeof(CipUsint) + sizeof(CipWord) + sizeof(CipUdint) +
|
|
|
|
|
- sizeof(CipUsint) + g_identity.product_name.length + sizeof(CipUsint);
|
|
|
|
|
|
|
+ return sizeof(CipUint) + sizeof(CipInt) + sizeof(CipUint) + sizeof(CipUdint) + 8 * sizeof(CipUsint) + sizeof(CipUint) + sizeof(CipUint) + sizeof(CipUint)
|
|
|
|
|
+ + 2 * sizeof(CipUsint) + sizeof(CipWord) + sizeof(CipUdint) + sizeof(CipUsint) + g_identity.product_name.length + sizeof(CipUsint);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EncodeListIdentityCipIdentityItem(ENIPMessage *const outgoing_message) {
|
|
void EncodeListIdentityCipIdentityItem(ENIPMessage *const outgoing_message) {
|
|
@@ -427,9 +358,7 @@ void EncodeListIdentityCipIdentityItem(ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
|
AddIntToMessage(kSupportedProtocolVersion, outgoing_message);
|
|
AddIntToMessage(kSupportedProtocolVersion, outgoing_message);
|
|
|
|
|
|
|
|
- EncapsulateIpAddress(htons(kOpenerEthernetPort),
|
|
|
|
|
- g_tcpip.interface_configuration.ip_address,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ EncapsulateIpAddress(htons(kOpenerEthernetPort), g_tcpip.interface_configuration.ip_address, outgoing_message);
|
|
|
|
|
|
|
|
/** Array of USINT - length 8 shall be set to zero */
|
|
/** Array of USINT - length 8 shall be set to zero */
|
|
|
FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, 8, outgoing_message);
|
|
FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, 8, outgoing_message);
|
|
@@ -441,45 +370,32 @@ void EncodeListIdentityCipIdentityItem(ENIPMessage *const outgoing_message) {
|
|
|
AddSintToMessage(g_identity.revision.minor_revision, outgoing_message);
|
|
AddSintToMessage(g_identity.revision.minor_revision, outgoing_message);
|
|
|
AddIntToMessage(g_identity.status, outgoing_message);
|
|
AddIntToMessage(g_identity.status, outgoing_message);
|
|
|
AddDintToMessage(g_identity.serial_number, outgoing_message);
|
|
AddDintToMessage(g_identity.serial_number, outgoing_message);
|
|
|
- AddSintToMessage( (unsigned char) g_identity.product_name.length,
|
|
|
|
|
- outgoing_message );
|
|
|
|
|
|
|
+ AddSintToMessage((unsigned char) g_identity.product_name.length, outgoing_message);
|
|
|
//TODO Change to EncodeCipString
|
|
//TODO Change to EncodeCipString
|
|
|
- memcpy(outgoing_message->current_message_position,
|
|
|
|
|
- g_identity.product_name.string,
|
|
|
|
|
- g_identity.product_name.length);
|
|
|
|
|
|
|
+ memcpy(outgoing_message->current_message_position, g_identity.product_name.string, g_identity.product_name.length);
|
|
|
outgoing_message->current_message_position += g_identity.product_name.length;
|
|
outgoing_message->current_message_position += g_identity.product_name.length;
|
|
|
outgoing_message->used_message_length += g_identity.product_name.length;
|
|
outgoing_message->used_message_length += g_identity.product_name.length;
|
|
|
|
|
|
|
|
AddSintToMessage(g_identity.state, outgoing_message);
|
|
AddSintToMessage(g_identity.state, outgoing_message);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void EncapsulateListIdentityResponseMessage(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void EncapsulateListIdentityResponseMessage(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
|
- const CipUint kEncapsulationCommandListIdentityLength =
|
|
|
|
|
- ListIdentityGetCipIdentityItemLength() + sizeof(CipUint) + sizeof(CipUint) +
|
|
|
|
|
- sizeof(CipUint); /* Last element is item count */
|
|
|
|
|
|
|
+ const CipUint kEncapsulationCommandListIdentityLength = ListIdentityGetCipIdentityItemLength() + sizeof(CipUint) + sizeof(CipUint) + sizeof(CipUint); /* Last element is item count */
|
|
|
|
|
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- kEncapsulationCommandListIdentityLength,
|
|
|
|
|
- 0,
|
|
|
|
|
- /* Session handle will be ignored by receiver */
|
|
|
|
|
- kEncapsulationProtocolSuccess,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, kEncapsulationCommandListIdentityLength, 0,
|
|
|
|
|
+ /* Session handle will be ignored by receiver */
|
|
|
|
|
+ kEncapsulationProtocolSuccess, outgoing_message);
|
|
|
|
|
|
|
|
AddIntToMessage(1, outgoing_message); /* Item count: one item */
|
|
AddIntToMessage(1, outgoing_message); /* Item count: one item */
|
|
|
EncodeListIdentityCipIdentityItem(outgoing_message);
|
|
EncodeListIdentityCipIdentityItem(outgoing_message);
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void DetermineDelayTime(const EipByte *buffer_start,
|
|
|
|
|
- DelayedEncapsulationMessage *const delayed_message_buffer)
|
|
|
|
|
-{
|
|
|
|
|
|
|
+void DetermineDelayTime(const EipByte *buffer_start, DelayedEncapsulationMessage *const delayed_message_buffer) {
|
|
|
|
|
|
|
|
buffer_start += 12; /* start of the sender context */
|
|
buffer_start += 12; /* start of the sender context */
|
|
|
- EipUint16 maximum_delay_time = GetUintFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &buffer_start );
|
|
|
|
|
|
|
+ EipUint16 maximum_delay_time = GetUintFromMessage((const EipUint8** const ) &buffer_start);
|
|
|
|
|
|
|
|
if(0 == maximum_delay_time) {
|
|
if(0 == maximum_delay_time) {
|
|
|
maximum_delay_time = kListIdentityDefaultDelayTime;
|
|
maximum_delay_time = kListIdentityDefaultDelayTime;
|
|
@@ -490,21 +406,13 @@ void DetermineDelayTime(const EipByte *buffer_start,
|
|
|
delayed_message_buffer->time_out = rand() % maximum_delay_time;
|
|
delayed_message_buffer->time_out = rand() % maximum_delay_time;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void EncapsulateRegisterSessionCommandResponseMessage(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- const size_t session_handle,
|
|
|
|
|
- const EncapsulationProtocolErrorCode encapsulation_protocol_status,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void EncapsulateRegisterSessionCommandResponseMessage(const EncapsulationData *const receive_data, const size_t session_handle,
|
|
|
|
|
+ const EncapsulationProtocolErrorCode encapsulation_protocol_status, ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
|
/* Encapsulation header */
|
|
/* Encapsulation header */
|
|
|
- const size_t kListInterfacesCommandSpecificDataLength = sizeof(CipUint) +
|
|
|
|
|
- sizeof(CipUint);
|
|
|
|
|
|
|
+ const size_t kListInterfacesCommandSpecificDataLength = sizeof(CipUint) + sizeof(CipUint);
|
|
|
assert(kListInterfacesCommandSpecificDataLength == 4);
|
|
assert(kListInterfacesCommandSpecificDataLength == 4);
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- kListInterfacesCommandSpecificDataLength,
|
|
|
|
|
- session_handle,
|
|
|
|
|
- encapsulation_protocol_status,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, kListInterfacesCommandSpecificDataLength, session_handle, encapsulation_protocol_status, outgoing_message);
|
|
|
|
|
|
|
|
AddIntToMessage(1, outgoing_message); /* protocol version*/
|
|
AddIntToMessage(1, outgoing_message); /* protocol version*/
|
|
|
AddIntToMessage(0, outgoing_message); /* Options flag, shall be set to zero */
|
|
AddIntToMessage(0, outgoing_message); /* Options flag, shall be set to zero */
|
|
@@ -514,29 +422,23 @@ void EncapsulateRegisterSessionCommandResponseMessage(
|
|
|
* @param socket Socket this request is associated to. Needed for double register check
|
|
* @param socket Socket this request is associated to. Needed for double register check
|
|
|
* @param receive_data Pointer to received data with request/response.
|
|
* @param receive_data Pointer to received data with request/response.
|
|
|
*/
|
|
*/
|
|
|
-void HandleReceivedRegisterSessionCommand(int socket,
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+void HandleReceivedRegisterSessionCommand(int socket, const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
int session_index = 0;
|
|
int session_index = 0;
|
|
|
size_t session_handle = 0;
|
|
size_t session_handle = 0;
|
|
|
- EncapsulationProtocolErrorCode encapsulation_protocol_status =
|
|
|
|
|
- kEncapsulationProtocolSuccess;
|
|
|
|
|
|
|
+ EncapsulationProtocolErrorCode encapsulation_protocol_status = kEncapsulationProtocolSuccess;
|
|
|
|
|
|
|
|
- EipUint16 protocol_version = GetUintFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &receive_data->current_communication_buffer_position );
|
|
|
|
|
- EipUint16 option_flag = GetUintFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &receive_data->current_communication_buffer_position );
|
|
|
|
|
|
|
+ EipUint16 protocol_version = GetUintFromMessage((const EipUint8** const ) &receive_data->current_communication_buffer_position);
|
|
|
|
|
+ EipUint16 option_flag = GetUintFromMessage((const EipUint8** const ) &receive_data->current_communication_buffer_position);
|
|
|
|
|
|
|
|
/* check if requested protocol version is supported and the register session option flag is zero*/
|
|
/* check if requested protocol version is supported and the register session option flag is zero*/
|
|
|
- if( (0 < protocol_version) &&
|
|
|
|
|
- (protocol_version <= kSupportedProtocolVersion) && (0 == option_flag) ) { /*Option field should be zero*/
|
|
|
|
|
|
|
+ if((0 < protocol_version) && (protocol_version <= kSupportedProtocolVersion) && (0 == option_flag)) { /*Option field should be zero*/
|
|
|
/* check if the socket has already a session open */
|
|
/* check if the socket has already a session open */
|
|
|
for(size_t i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
|
|
for(size_t i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
|
|
|
if(g_registered_sessions[i] == socket) {
|
|
if(g_registered_sessions[i] == socket) {
|
|
|
/* the socket has already registered a session this is not allowed*/
|
|
/* the socket has already registered a session this is not allowed*/
|
|
|
OPENER_TRACE_INFO(
|
|
OPENER_TRACE_INFO(
|
|
|
- "Error: A session is already registered at socket %d\n",
|
|
|
|
|
- socket);
|
|
|
|
|
|
|
+ "Error: A session is already registered at socket %d\n",
|
|
|
|
|
+ socket);
|
|
|
session_handle = i + 1; /*return the already assigned session back, the cip spec is not clear about this needs to be tested*/
|
|
session_handle = i + 1; /*return the already assigned session back, the cip spec is not clear about this needs to be tested*/
|
|
|
encapsulation_protocol_status = kEncapsulationProtocolInvalidCommand;
|
|
encapsulation_protocol_status = kEncapsulationProtocolInvalidCommand;
|
|
|
session_index = kSessionStatusInvalid;
|
|
session_index = kSessionStatusInvalid;
|
|
@@ -548,12 +450,10 @@ void HandleReceivedRegisterSessionCommand(int socket,
|
|
|
session_index = GetFreeSessionIndex();
|
|
session_index = GetFreeSessionIndex();
|
|
|
if(kSessionStatusInvalid == session_index) /* no more sessions available */
|
|
if(kSessionStatusInvalid == session_index) /* no more sessions available */
|
|
|
{
|
|
{
|
|
|
- encapsulation_protocol_status =
|
|
|
|
|
- kEncapsulationProtocolInsufficientMemory;
|
|
|
|
|
|
|
+ encapsulation_protocol_status = kEncapsulationProtocolInsufficientMemory;
|
|
|
} else { /* successful session registered */
|
|
} else { /* successful session registered */
|
|
|
- SocketTimer *socket_timer = SocketTimerArrayGetEmptySocketTimer(
|
|
|
|
|
- g_timestamps,
|
|
|
|
|
- OPENER_NUMBER_OF_SUPPORTED_SESSIONS);
|
|
|
|
|
|
|
+ SocketTimer *socket_timer = SocketTimerArrayGetEmptySocketTimer(g_timestamps,
|
|
|
|
|
+ OPENER_NUMBER_OF_SUPPORTED_SESSIONS);
|
|
|
SocketTimerSetSocket(socket_timer, socket);
|
|
SocketTimerSetSocket(socket_timer, socket);
|
|
|
SocketTimerSetLastUpdate(socket_timer, g_actual_time);
|
|
SocketTimerSetLastUpdate(socket_timer, g_actual_time);
|
|
|
g_registered_sessions[session_index] = socket; /* store associated socket */
|
|
g_registered_sessions[session_index] = socket; /* store associated socket */
|
|
@@ -565,10 +465,7 @@ void HandleReceivedRegisterSessionCommand(int socket,
|
|
|
encapsulation_protocol_status = kEncapsulationProtocolUnsupportedProtocol;
|
|
encapsulation_protocol_status = kEncapsulationProtocolUnsupportedProtocol;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- EncapsulateRegisterSessionCommandResponseMessage(receive_data,
|
|
|
|
|
- session_handle,
|
|
|
|
|
- encapsulation_protocol_status,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ EncapsulateRegisterSessionCommandResponseMessage(receive_data, session_handle, encapsulation_protocol_status, outgoing_message);
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -579,13 +476,10 @@ void HandleReceivedRegisterSessionCommand(int socket,
|
|
|
*
|
|
*
|
|
|
* Close all corresponding TCP connections and delete session handle.
|
|
* Close all corresponding TCP connections and delete session handle.
|
|
|
*/
|
|
*/
|
|
|
-EipStatus HandleReceivedUnregisterSessionCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+EipStatus HandleReceivedUnregisterSessionCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
OPENER_TRACE_INFO("encap.c: Unregister Session Command\n");
|
|
OPENER_TRACE_INFO("encap.c: Unregister Session Command\n");
|
|
|
- if( (0 < receive_data->session_handle) && (receive_data->session_handle <=
|
|
|
|
|
- OPENER_NUMBER_OF_SUPPORTED_SESSIONS) )
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ if((0 < receive_data->session_handle) && (receive_data->session_handle <=
|
|
|
|
|
+ OPENER_NUMBER_OF_SUPPORTED_SESSIONS)) {
|
|
|
size_t i = receive_data->session_handle - 1;
|
|
size_t i = receive_data->session_handle - 1;
|
|
|
if(kEipInvalidSocket != g_registered_sessions[i]) {
|
|
if(kEipInvalidSocket != g_registered_sessions[i]) {
|
|
|
CloseTcpSocket(g_registered_sessions[i]);
|
|
CloseTcpSocket(g_registered_sessions[i]);
|
|
@@ -596,11 +490,7 @@ EipStatus HandleReceivedUnregisterSessionCommand(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* no such session registered */
|
|
/* no such session registered */
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- 0,
|
|
|
|
|
- receive_data->session_handle,
|
|
|
|
|
- kEncapsulationProtocolInvalidSessionHandle,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, 0, receive_data->session_handle, kEncapsulationProtocolInvalidSessionHandle, outgoing_message);
|
|
|
return kEipStatusOkSend;
|
|
return kEipStatusOkSend;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -609,34 +499,24 @@ EipStatus HandleReceivedUnregisterSessionCommand(
|
|
|
* @param originator_address Address of the originator as received from socket
|
|
* @param originator_address Address of the originator as received from socket
|
|
|
* @param outgoing_message The outgoing ENIP message
|
|
* @param outgoing_message The outgoing ENIP message
|
|
|
*/
|
|
*/
|
|
|
-EipStatus HandleReceivedSendUnitDataCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- const struct sockaddr *const originator_address,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+EipStatus HandleReceivedSendUnitDataCommand(const EncapsulationData *const receive_data, const struct sockaddr *const originator_address,
|
|
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
EipStatus return_value = kEipStatusOkSend;
|
|
EipStatus return_value = kEipStatusOkSend;
|
|
|
- /*EipStatus*/ return_value = kEipStatusOk; /* TODO: Shouldn't this be kEipStatusOk cause we must not send any response if data_length < 6? */
|
|
|
|
|
|
|
+ /*EipStatus*/return_value = kEipStatusOk; /* TODO: Shouldn't this be kEipStatusOk cause we must not send any response if data_length < 6? */
|
|
|
|
|
|
|
|
if(receive_data->data_length >= 6) {
|
|
if(receive_data->data_length >= 6) {
|
|
|
/* Command specific data UDINT .. Interface Handle, UINT .. Timeout, CPF packets */
|
|
/* Command specific data UDINT .. Interface Handle, UINT .. Timeout, CPF packets */
|
|
|
/* don't use the data yet */
|
|
/* don't use the data yet */
|
|
|
- GetDintFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &receive_data->current_communication_buffer_position ); /* skip over null interface handle*/
|
|
|
|
|
- GetIntFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &receive_data->current_communication_buffer_position ); /* skip over unused timeout value*/
|
|
|
|
|
- ( (EncapsulationData *const ) receive_data )->data_length -= 6; /* the rest is in CPF format*/
|
|
|
|
|
|
|
+ GetDintFromMessage((const EipUint8** const ) &receive_data->current_communication_buffer_position); /* skip over null interface handle*/
|
|
|
|
|
+ GetIntFromMessage((const EipUint8** const ) &receive_data->current_communication_buffer_position); /* skip over unused timeout value*/
|
|
|
|
|
+ ((EncapsulationData* const ) receive_data)->data_length -= 6; /* the rest is in CPF format*/
|
|
|
|
|
|
|
|
- if(kSessionStatusValid == CheckRegisteredSessions(receive_data) ) /* see if the EIP session is registered*/
|
|
|
|
|
|
|
+ if(kSessionStatusValid == CheckRegisteredSessions(receive_data)) /* see if the EIP session is registered*/
|
|
|
{
|
|
{
|
|
|
- return_value = NotifyConnectedCommonPacketFormat(receive_data,
|
|
|
|
|
- originator_address,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ return_value = NotifyConnectedCommonPacketFormat(receive_data, originator_address, outgoing_message);
|
|
|
} else { /* received a package with non registered session handle */
|
|
} else { /* received a package with non registered session handle */
|
|
|
InitializeENIPMessage(outgoing_message);
|
|
InitializeENIPMessage(outgoing_message);
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- 0,
|
|
|
|
|
- receive_data->session_handle,
|
|
|
|
|
- kEncapsulationProtocolInvalidSessionHandle,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, 0, receive_data->session_handle, kEncapsulationProtocolInvalidSessionHandle, outgoing_message);
|
|
|
return_value = kEipStatusOkSend; /* TODO: Needs to be here if line with first TODO of this function is adjusted. */
|
|
return_value = kEipStatusOkSend; /* TODO: Needs to be here if line with first TODO of this function is adjusted. */
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -651,50 +531,34 @@ EipStatus HandleReceivedSendUnitDataCommand(
|
|
|
* kEipStatusOkSend .. success & need to send response
|
|
* kEipStatusOkSend .. success & need to send response
|
|
|
* kEipStatusError .. error
|
|
* kEipStatusError .. error
|
|
|
*/
|
|
*/
|
|
|
-EipStatus HandleReceivedSendRequestResponseDataCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- const struct sockaddr *const originator_address,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+EipStatus HandleReceivedSendRequestResponseDataCommand(const EncapsulationData *const receive_data, const struct sockaddr *const originator_address,
|
|
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
EipStatus return_value = kEipStatusOkSend;
|
|
EipStatus return_value = kEipStatusOkSend;
|
|
|
- /* EipStatus*/ return_value = kEipStatusOk; /* TODO: Shouldn't this be kEipStatusOk cause we must not send any response if data_length < 6? */
|
|
|
|
|
|
|
+ /* EipStatus*/return_value = kEipStatusOk; /* TODO: Shouldn't this be kEipStatusOk cause we must not send any response if data_length < 6? */
|
|
|
|
|
|
|
|
if(receive_data->data_length >= 6) {
|
|
if(receive_data->data_length >= 6) {
|
|
|
/* Command specific data UDINT .. Interface Handle, UINT .. Timeout, CPF packets */
|
|
/* Command specific data UDINT .. Interface Handle, UINT .. Timeout, CPF packets */
|
|
|
/* don't use the data yet */
|
|
/* don't use the data yet */
|
|
|
- GetDintFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &receive_data->current_communication_buffer_position ); /* skip over null interface handle*/
|
|
|
|
|
- GetIntFromMessage(
|
|
|
|
|
- (const EipUint8 **const ) &receive_data->current_communication_buffer_position ); /* skip over unused timeout value*/
|
|
|
|
|
- ( (EncapsulationData *const ) receive_data )->data_length -= 6; /* the rest is in CPF format*/
|
|
|
|
|
|
|
+ GetDintFromMessage((const EipUint8** const ) &receive_data->current_communication_buffer_position); /* skip over null interface handle*/
|
|
|
|
|
+ GetIntFromMessage((const EipUint8** const ) &receive_data->current_communication_buffer_position); /* skip over unused timeout value*/
|
|
|
|
|
+ ((EncapsulationData* const ) receive_data)->data_length -= 6; /* the rest is in CPF format*/
|
|
|
|
|
|
|
|
- if(kSessionStatusValid == CheckRegisteredSessions(receive_data) ) /* see if the EIP session is registered*/
|
|
|
|
|
|
|
+ if(kSessionStatusValid == CheckRegisteredSessions(receive_data)) /* see if the EIP session is registered*/
|
|
|
{
|
|
{
|
|
|
- return_value = NotifyCommonPacketFormat(receive_data,
|
|
|
|
|
- originator_address,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ return_value = NotifyCommonPacketFormat(receive_data, originator_address, outgoing_message);
|
|
|
} else { /* received a package with non registered session handle */
|
|
} else { /* received a package with non registered session handle */
|
|
|
InitializeENIPMessage(outgoing_message);
|
|
InitializeENIPMessage(outgoing_message);
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- 0,
|
|
|
|
|
- receive_data->session_handle,
|
|
|
|
|
- kEncapsulationProtocolInvalidSessionHandle,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, 0, receive_data->session_handle, kEncapsulationProtocolInvalidSessionHandle, outgoing_message);
|
|
|
return_value = kEipStatusOkSend; /* TODO: Needs to be here if line with first TODO of this function is adjusted. */
|
|
return_value = kEipStatusOkSend; /* TODO: Needs to be here if line with first TODO of this function is adjusted. */
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return return_value;
|
|
return return_value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-EipStatus HandleReceivedInvalidCommand(
|
|
|
|
|
- const EncapsulationData *const receive_data,
|
|
|
|
|
- ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
+EipStatus HandleReceivedInvalidCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
|
|
/* Encapsulation header */
|
|
/* Encapsulation header */
|
|
|
- GenerateEncapsulationHeader(receive_data,
|
|
|
|
|
- 0,
|
|
|
|
|
- receive_data->session_handle,
|
|
|
|
|
- kEncapsulationProtocolInvalidCommand,
|
|
|
|
|
- outgoing_message);
|
|
|
|
|
|
|
+ GenerateEncapsulationHeader(receive_data, 0, receive_data->session_handle, kEncapsulationProtocolInvalidCommand, outgoing_message);
|
|
|
return kEipStatusOkSend;
|
|
return kEipStatusOkSend;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
@@ -704,8 +568,7 @@ EipStatus HandleReceivedInvalidCommand(
|
|
|
* kInvalidSession .. no free session available
|
|
* kInvalidSession .. no free session available
|
|
|
*/
|
|
*/
|
|
|
int GetFreeSessionIndex(void) {
|
|
int GetFreeSessionIndex(void) {
|
|
|
- for(size_t session_index = 0;
|
|
|
|
|
- session_index < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; session_index++) {
|
|
|
|
|
|
|
+ for(size_t session_index = 0; session_index < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; session_index++) {
|
|
|
if(kEipInvalidSocket == g_registered_sessions[session_index]) {
|
|
if(kEipInvalidSocket == g_registered_sessions[session_index]) {
|
|
|
return session_index;
|
|
return session_index;
|
|
|
}
|
|
}
|
|
@@ -722,24 +585,18 @@ int GetFreeSessionIndex(void) {
|
|
|
* >0 .. more than one packet received
|
|
* >0 .. more than one packet received
|
|
|
* <0 .. only fragment of data portion received
|
|
* <0 .. only fragment of data portion received
|
|
|
*/
|
|
*/
|
|
|
-EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer,
|
|
|
|
|
- int receive_buffer_length,
|
|
|
|
|
- EncapsulationData *const encapsulation_data)
|
|
|
|
|
-{
|
|
|
|
|
- encapsulation_data->communication_buffer_start = (EipUint8 *) receive_buffer;
|
|
|
|
|
|
|
+EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer, int receive_buffer_length, EncapsulationData *const encapsulation_data) {
|
|
|
|
|
+ encapsulation_data->communication_buffer_start = (EipUint8*) receive_buffer;
|
|
|
encapsulation_data->command_code = GetUintFromMessage(&receive_buffer);
|
|
encapsulation_data->command_code = GetUintFromMessage(&receive_buffer);
|
|
|
encapsulation_data->data_length = GetUintFromMessage(&receive_buffer);
|
|
encapsulation_data->data_length = GetUintFromMessage(&receive_buffer);
|
|
|
encapsulation_data->session_handle = GetUdintFromMessage(&receive_buffer);
|
|
encapsulation_data->session_handle = GetUdintFromMessage(&receive_buffer);
|
|
|
encapsulation_data->status = GetUdintFromMessage(&receive_buffer);
|
|
encapsulation_data->status = GetUdintFromMessage(&receive_buffer);
|
|
|
|
|
|
|
|
- memcpy(encapsulation_data->sender_context, receive_buffer,
|
|
|
|
|
- kSenderContextSize);
|
|
|
|
|
|
|
+ memcpy(encapsulation_data->sender_context, receive_buffer, kSenderContextSize);
|
|
|
receive_buffer += kSenderContextSize;
|
|
receive_buffer += kSenderContextSize;
|
|
|
encapsulation_data->options = GetUdintFromMessage(&receive_buffer);
|
|
encapsulation_data->options = GetUdintFromMessage(&receive_buffer);
|
|
|
- encapsulation_data->current_communication_buffer_position =
|
|
|
|
|
- (EipUint8 *) receive_buffer;
|
|
|
|
|
- return (receive_buffer_length - ENCAPSULATION_HEADER_LENGTH -
|
|
|
|
|
- encapsulation_data->data_length);
|
|
|
|
|
|
|
+ encapsulation_data->current_communication_buffer_position = (EipUint8*) receive_buffer;
|
|
|
|
|
+ return (receive_buffer_length - ENCAPSULATION_HEADER_LENGTH - encapsulation_data->data_length);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** @brief Check if received package belongs to registered session.
|
|
/** @brief Check if received package belongs to registered session.
|
|
@@ -747,30 +604,26 @@ EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer,
|
|
|
* @return 0 .. Session registered
|
|
* @return 0 .. Session registered
|
|
|
* kInvalidSession .. invalid session -> return unsupported command received
|
|
* kInvalidSession .. invalid session -> return unsupported command received
|
|
|
*/
|
|
*/
|
|
|
-SessionStatus CheckRegisteredSessions(
|
|
|
|
|
- const EncapsulationData *const receive_data) {
|
|
|
|
|
|
|
+SessionStatus CheckRegisteredSessions(const EncapsulationData *const receive_data) {
|
|
|
|
|
|
|
|
-/* Skip the check when fuzzing
|
|
|
|
|
- in order to increase our code coverage
|
|
|
|
|
- we are simply bypassing all the session checks
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ /* Skip the check when fuzzing
|
|
|
|
|
+ in order to increase our code coverage
|
|
|
|
|
+ we are simply bypassing all the session checks
|
|
|
|
|
+ */
|
|
|
#ifdef FUZZING_AFL
|
|
#ifdef FUZZING_AFL
|
|
|
return kSessionStatusValid;
|
|
return kSessionStatusValid;
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
- if( (0 < receive_data->session_handle) && (receive_data->session_handle <=
|
|
|
|
|
- OPENER_NUMBER_OF_SUPPORTED_SESSIONS) )
|
|
|
|
|
- {
|
|
|
|
|
- if(kEipInvalidSocket !=
|
|
|
|
|
- g_registered_sessions[receive_data->session_handle - 1]) {
|
|
|
|
|
|
|
+ if((0 < receive_data->session_handle) && (receive_data->session_handle <=
|
|
|
|
|
+ OPENER_NUMBER_OF_SUPPORTED_SESSIONS)) {
|
|
|
|
|
+ if(kEipInvalidSocket != g_registered_sessions[receive_data->session_handle - 1]) {
|
|
|
return kSessionStatusValid;
|
|
return kSessionStatusValid;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return kSessionStatusInvalid;
|
|
return kSessionStatusInvalid;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void CloseSessionBySessionHandle(
|
|
|
|
|
- const CipConnectionObject *const connection_object) {
|
|
|
|
|
|
|
+void CloseSessionBySessionHandle(const CipConnectionObject *const connection_object) {
|
|
|
OPENER_TRACE_INFO("encap.c: Close session by handle\n");
|
|
OPENER_TRACE_INFO("encap.c: Close session by handle\n");
|
|
|
size_t session_handle = connection_object->associated_encapsulation_session;
|
|
size_t session_handle = connection_object->associated_encapsulation_session;
|
|
|
CloseTcpSocket(g_registered_sessions[session_handle - 1]);
|
|
CloseTcpSocket(g_registered_sessions[session_handle - 1]);
|
|
@@ -787,7 +640,7 @@ void CloseSession(int socket) {
|
|
|
CloseClass3ConnectionBasedOnSession(i + 1);
|
|
CloseClass3ConnectionBasedOnSession(i + 1);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
- } OPENER_TRACE_INFO("encap.c: Close session done\n");
|
|
|
|
|
|
|
+ }OPENER_TRACE_INFO("encap.c: Close session done\n");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RemoveSession(const int socket) {
|
|
void RemoveSession(const int socket) {
|
|
@@ -798,7 +651,7 @@ void RemoveSession(const int socket) {
|
|
|
CloseClass3ConnectionBasedOnSession(i + 1);
|
|
CloseClass3ConnectionBasedOnSession(i + 1);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
- } OPENER_TRACE_INFO("encap.c: Session removed\n");
|
|
|
|
|
|
|
+ }OPENER_TRACE_INFO("encap.c: Session removed\n");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EncapsulationShutDown(void) {
|
|
void EncapsulationShutDown(void) {
|
|
@@ -817,37 +670,29 @@ void ManageEncapsulationMessages(const MilliSeconds elapsed_time) {
|
|
|
g_delayed_encapsulation_messages[i].time_out -= elapsed_time;
|
|
g_delayed_encapsulation_messages[i].time_out -= elapsed_time;
|
|
|
if(0 >= g_delayed_encapsulation_messages[i].time_out) {
|
|
if(0 >= g_delayed_encapsulation_messages[i].time_out) {
|
|
|
/* If delay is reached or passed, send the UDP message */
|
|
/* If delay is reached or passed, send the UDP message */
|
|
|
- sendto(g_delayed_encapsulation_messages[i].socket,
|
|
|
|
|
- (char *) g_delayed_encapsulation_messages[i].outgoing_message.message_buffer,
|
|
|
|
|
- g_delayed_encapsulation_messages[i].outgoing_message.used_message_length,
|
|
|
|
|
- 0,
|
|
|
|
|
- (struct sockaddr *) &(g_delayed_encapsulation_messages[i].
|
|
|
|
|
- receiver),
|
|
|
|
|
- sizeof(struct sockaddr) );
|
|
|
|
|
|
|
+ sendto(g_delayed_encapsulation_messages[i].socket, (char*) g_delayed_encapsulation_messages[i].outgoing_message.message_buffer,
|
|
|
|
|
+ g_delayed_encapsulation_messages[i].outgoing_message.used_message_length, 0, (struct sockaddr*) &(g_delayed_encapsulation_messages[i].receiver),
|
|
|
|
|
+ sizeof(struct sockaddr));
|
|
|
g_delayed_encapsulation_messages[i].socket = kEipInvalidSocket;
|
|
g_delayed_encapsulation_messages[i].socket = kEipInvalidSocket;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void CloseEncapsulationSessionBySockAddr(
|
|
|
|
|
- const CipConnectionObject *const connection_object) {
|
|
|
|
|
|
|
+void CloseEncapsulationSessionBySockAddr(const CipConnectionObject *const connection_object) {
|
|
|
for(size_t i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
|
|
for(size_t i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
|
|
|
if(kEipInvalidSocket != g_registered_sessions[i]) {
|
|
if(kEipInvalidSocket != g_registered_sessions[i]) {
|
|
|
struct sockaddr_in encapsulation_session_addr = { 0 };
|
|
struct sockaddr_in encapsulation_session_addr = { 0 };
|
|
|
socklen_t addrlength = sizeof(encapsulation_session_addr);
|
|
socklen_t addrlength = sizeof(encapsulation_session_addr);
|
|
|
- if(getpeername(g_registered_sessions[i],
|
|
|
|
|
- (struct sockaddr *) &encapsulation_session_addr,
|
|
|
|
|
- &addrlength) < 0) { /* got error */
|
|
|
|
|
|
|
+ if(getpeername(g_registered_sessions[i], (struct sockaddr*) &encapsulation_session_addr, &addrlength) < 0) { /* got error */
|
|
|
int error_code = GetSocketErrorNumber();
|
|
int error_code = GetSocketErrorNumber();
|
|
|
char *error_message = GetErrorMessage(error_code);
|
|
char *error_message = GetErrorMessage(error_code);
|
|
|
OPENER_TRACE_ERR(
|
|
OPENER_TRACE_ERR(
|
|
|
- "encap.c: error on getting peer name on closing session: %d - %s\n",
|
|
|
|
|
- error_code, error_message);
|
|
|
|
|
|
|
+ "encap.c: error on getting peer name on closing session: %d - %s\n",
|
|
|
|
|
+ error_code, error_message);
|
|
|
FreeErrorMessage(error_message);
|
|
FreeErrorMessage(error_message);
|
|
|
}
|
|
}
|
|
|
- if(encapsulation_session_addr.sin_addr.s_addr ==
|
|
|
|
|
- connection_object->originator_address.sin_addr.s_addr) {
|
|
|
|
|
|
|
+ if(encapsulation_session_addr.sin_addr.s_addr == connection_object->originator_address.sin_addr.s_addr) {
|
|
|
CloseSession(g_registered_sessions[i]);
|
|
CloseSession(g_registered_sessions[i]);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -867,10 +712,8 @@ void CloseClass3ConnectionBasedOnSession(size_t encapsulation_session_handle) {
|
|
|
DoublyLinkedListNode *node = connection_list.first;
|
|
DoublyLinkedListNode *node = connection_list.first;
|
|
|
while(NULL != node) {
|
|
while(NULL != node) {
|
|
|
CipConnectionObject *connection_object = node->data;
|
|
CipConnectionObject *connection_object = node->data;
|
|
|
- if(kConnectionObjectTransportClassTriggerTransportClass3 ==
|
|
|
|
|
- ConnectionObjectGetTransportClassTriggerTransportClass(connection_object)
|
|
|
|
|
- && connection_object->associated_encapsulation_session ==
|
|
|
|
|
- encapsulation_session_handle) {
|
|
|
|
|
|
|
+ if(kConnectionObjectTransportClassTriggerTransportClass3 == ConnectionObjectGetTransportClassTriggerTransportClass(connection_object)
|
|
|
|
|
+ && connection_object->associated_encapsulation_session == encapsulation_session_handle) {
|
|
|
connection_object->connection_close_function(connection_object);
|
|
connection_object->connection_close_function(connection_object);
|
|
|
}
|
|
}
|
|
|
node = node->next;
|
|
node = node->next;
|