OpENer - Open Source EtherNet/IP(TM) I/O Target Stack  2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpf.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (c) 2009, Rockwell Automation, Inc.
3  * All rights reserved.
4  *
5  ******************************************************************************/
6 #include <string.h>
7 
8 #include "cpf.h"
9 
10 #include "opener_api.h"
11 #include "cipcommon.h"
12 #include "cipmessagerouter.h"
13 #include "endianconv.h"
14 #include "ciperror.h"
15 #include "cipconnectionmanager.h"
16 #include "trace.h"
17 #include "encap.h"
18 
19 const size_t item_count_field_size = 2;
23 
27  const struct sockaddr *const originator_address,
28  ENIPMessage *const outgoing_message) {
29  int return_value = kEipStatusError;
30 
31  if (kEipStatusError == ( return_value = CreateCommonPacketFormatStructure(
32  received_data->
33  current_communication_buffer_position,
34  received_data->data_length,
35  &g_common_packet_format_data_item) ) ) {
36  OPENER_TRACE_ERR("notifyCPF: error from createCPFstructure\n");
37  } else {
38  return_value = kEipStatusOk; /* In cases of errors we normally need to send an error response */
39  if (g_common_packet_format_data_item.address_item.type_id
40  == kCipItemIdNullAddress) /* check if NullAddressItem received, otherwise it is no unconnected message and should not be here*/
41  { /* found null address item*/
42  if (g_common_packet_format_data_item.data_item.type_id
43  == kCipItemIdUnconnectedDataItem) { /* unconnected data item received*/
44  return_value = NotifyMessageRouter(
45  g_common_packet_format_data_item.data_item.data,
46  g_common_packet_format_data_item.data_item.length,
47  originator_address,
48  received_data->session_handle);
49  if (return_value != kEipStatusError) {
50  SkipEncapsulationHeader(outgoing_message);
51  return_value = AssembleLinearMessage(
52  &g_message_router_response, &g_common_packet_format_data_item,
53  outgoing_message);
54 
55  CipOctet *buffer = outgoing_message->current_message_position;
56  outgoing_message->current_message_position =
57  outgoing_message->message_buffer;
58  GenerateEncapsulationHeader(received_data,
59  return_value,
60  received_data->session_handle,
62  outgoing_message);
63  outgoing_message->current_message_position = buffer;
64  return_value = outgoing_message->used_message_length;
65  }
66  } else {
67  /* wrong data item detected*/
69  "notifyCPF: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
70  GenerateEncapsulationHeader(received_data,
71  return_value,
72  received_data->session_handle,
74  outgoing_message);
75  return_value = outgoing_message->used_message_length;
76  }
77  } else {
79  "notifyCPF: got something besides the expected CIP_ITEM_ID_NULL\n");
80  GenerateEncapsulationHeader(received_data,
81  return_value,
82  received_data->session_handle,
84  outgoing_message);
85  return_value = outgoing_message->used_message_length;
86  }
87  }
88  return return_value;
89 }
90 
92  const EncapsulationData *const received_data,
93  const struct sockaddr *const originator_address,
94  ENIPMessage *const outgoing_message) {
95 
96  int return_value = CreateCommonPacketFormatStructure(
98  received_data->data_length, &g_common_packet_format_data_item);
99 
100  if (kEipStatusError == return_value) {
101  OPENER_TRACE_ERR("notifyConnectedCPF: error from createCPFstructure\n");
102  } else {
103  return_value = kEipStatusError; /* For connected explicit messages status always has to be 0*/
104  if (g_common_packet_format_data_item.address_item.type_id
105  == kCipItemIdConnectionAddress) /* check if ConnectedAddressItem received, otherwise it is no connected message and should not be here*/
106  { /* ConnectedAddressItem item */
107  CipConnectionObject *connection_object = GetConnectedObject(
108  g_common_packet_format_data_item.address_item.data
110  if (NULL != connection_object) {
111  /* reset the watchdog timer */
113 
114  /*TODO check connection id and sequence count */
115  if (g_common_packet_format_data_item.data_item.type_id
116  == kCipItemIdConnectedDataItem) { /* connected data item received*/
117  EipUint8 *buffer = g_common_packet_format_data_item.data_item.data;
118  g_common_packet_format_data_item.address_item.data.sequence_number =
119  (EipUint32) GetIntFromMessage( (const EipUint8 **const)&buffer );
121  "Class 3 sequence number: %d, last sequence number: %d\n",
122  g_common_packet_format_data_item.address_item.data.sequence_number,
123  connection_object->sequence_count_consuming);
124  if(connection_object->sequence_count_consuming ==
125  g_common_packet_format_data_item.address_item.data.sequence_number)
126  {
127  memcpy(outgoing_message,
128  &(connection_object->last_reply_sent),
129  sizeof(ENIPMessage) );
130  outgoing_message->current_message_position =
131  outgoing_message->message_buffer;
132  /* Regenerate encapsulation header for new message */
133  outgoing_message->used_message_length -=
135  GenerateEncapsulationHeader(received_data,
136  outgoing_message->used_message_length,
137  received_data->session_handle,
139  outgoing_message);
140  outgoing_message->current_message_position = buffer;
141  /* End regenerate encapsulation header for new message */
142  return outgoing_message->used_message_length;
143  }
144  connection_object->sequence_count_consuming =
145  g_common_packet_format_data_item.address_item.data.sequence_number;
146 
148 
149  return_value = NotifyMessageRouter(
150  buffer,
151  g_common_packet_format_data_item.data_item.length - 2,
152  originator_address,
153  received_data->session_handle);
154 
155  if (return_value != kEipStatusError) {
156  g_common_packet_format_data_item.address_item.data
157  .connection_identifier = connection_object
159  SkipEncapsulationHeader(outgoing_message);
160  return_value = AssembleLinearMessage(
161  &g_message_router_response, &g_common_packet_format_data_item,
162  outgoing_message);
163 
164  CipOctet *buffer = outgoing_message->current_message_position;
165  outgoing_message->current_message_position =
166  outgoing_message->message_buffer;
167  GenerateEncapsulationHeader(received_data,
168  return_value,
169  received_data->session_handle,
171  outgoing_message);
172  outgoing_message->current_message_position = buffer;
173  memcpy(&connection_object->last_reply_sent,
174  outgoing_message,
175  sizeof(ENIPMessage) );
176  return_value = outgoing_message->used_message_length;
177  }
178  } else {
179  /* wrong data item detected*/
181  "notifyConnectedCPF: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
182  }
183  } else {
185  "notifyConnectedCPF: connection with given ID could not be found\n");
186  }
187  } else {
189  "notifyConnectedCPF: got something besides the expected CIP_ITEM_ID_NULL\n");
190  }
191  }
192  return outgoing_message->used_message_length;
193 }
194 
205  const EipUint8 *data,
206  size_t data_length,
207  CipCommonPacketFormatData *common_packet_format_data) {
208 
209  common_packet_format_data->address_info_item[0].type_id = 0;
210  common_packet_format_data->address_info_item[1].type_id = 0;
211 
212  int length_count = 0;
213  CipUint item_count = GetIntFromMessage(&data);
214  OPENER_ASSERT(4U >= item_count) /* Sanitizing data - probably needs to be changed for productive code */
215  common_packet_format_data->item_count = item_count;
216  length_count += 2;
217  if (common_packet_format_data->item_count >= 1U) {
218  common_packet_format_data->address_item.type_id = GetIntFromMessage(&data);
219  common_packet_format_data->address_item.length = GetIntFromMessage(&data);
220  length_count += 4;
221  if (common_packet_format_data->address_item.length >= 4) {
222  common_packet_format_data->address_item.data.connection_identifier =
223  GetDintFromMessage(&data);
224  length_count += 4;
225  }
226  if (common_packet_format_data->address_item.length == 8) {
227  common_packet_format_data->address_item.data.sequence_number =
228  GetDintFromMessage(&data);
229  length_count += 4;
230  }
231  }
232  if (common_packet_format_data->item_count >= 2) {
233  common_packet_format_data->data_item.type_id = GetIntFromMessage(&data);
234  common_packet_format_data->data_item.length = GetIntFromMessage(&data);
235  common_packet_format_data->data_item.data = (EipUint8 *)data;
236  data += common_packet_format_data->data_item.length;
237  length_count += (4 + common_packet_format_data->data_item.length);
238 
239  for (size_t j = 0; j < (common_packet_format_data->item_count - 2); j++) /* TODO there needs to be a limit check here???*/
240  {
241  common_packet_format_data->address_info_item[j].type_id =
243  &data);
244  OPENER_TRACE_INFO("Sockaddr type id: %x\n",
245  common_packet_format_data->address_info_item[j].type_id);
246  length_count += 2;
247  if ( (common_packet_format_data->address_info_item[j].type_id
249  || (common_packet_format_data->address_info_item[j].type_id
251  common_packet_format_data->address_info_item[j].length =
252  GetIntFromMessage(&data);
253  common_packet_format_data->address_info_item[j].sin_family =
254  GetIntFromMessage(&data);
255  common_packet_format_data->address_info_item[j].sin_port =
256  GetIntFromMessage(&data);
257  common_packet_format_data->address_info_item[j].sin_addr =
258  GetDintFromMessage(&data);
259  for (size_t i = 0; i < 8; i++) {
260  common_packet_format_data->address_info_item[j].nasin_zero[i] = *data;
261  data++;
262  }
263  length_count += 18;
264  } else { /* no sockaddr item found */
265  common_packet_format_data->address_info_item[j].type_id = 0; /* mark as not set */
266  data -= 2;
267  }
268  }
269  }
270  /* set the addressInfoItems to not set if they were not received */
271  if (common_packet_format_data->item_count < 4) {
272  common_packet_format_data->address_info_item[1].type_id = 0;
273  if (common_packet_format_data->item_count < 3) {
274  common_packet_format_data->address_info_item[0].type_id = 0;
275  }
276  }
277  if (length_count == data_length) { /* length of data is equal to length of Addr and length of Data */
278  return kEipStatusOk;
279  } else {
281  "something is wrong with the length in Message Router @ CreateCommonPacketFormatStructure\n");
282  if (common_packet_format_data->item_count > 2) {
283  /* there is an optional packet in data stream which is not sockaddr item */
284  return kEipStatusOk;
285  } else { /* something with the length was wrong */
286  return kEipStatusError;
287  }
288  }
289 }
290 
297 int EncodeNullAddressItem(ENIPMessage *const outgoing_message) {
298  outgoing_message->used_message_length += AddIntToMessage(
300  &outgoing_message->current_message_position);
301  /* null address item -> address length set to 0 */
302  outgoing_message->used_message_length += AddIntToMessage(0,
303  &outgoing_message->current_message_position);
304  return outgoing_message->used_message_length;
305 }
306 
315  const CipCommonPacketFormatData *const common_packet_format_data_item,
316  ENIPMessage *const outgoing_message) {
317  /* connected data item -> address length set to 4 and copy ConnectionIdentifier */
318  outgoing_message->used_message_length += AddIntToMessage(
320  &outgoing_message->current_message_position);
321  outgoing_message->used_message_length += AddIntToMessage(4,
322  &outgoing_message->current_message_position);
323  outgoing_message->used_message_length += AddDintToMessage(
324  common_packet_format_data_item->address_item.data.connection_identifier,
325  &outgoing_message->current_message_position);
326  return outgoing_message->used_message_length;
327 }
328 
338  const CipCommonPacketFormatData *const common_packet_format_data_item,
339  ENIPMessage *const outgoing_message) {
340  /* sequenced address item -> address length set to 8 and copy ConnectionIdentifier and SequenceNumber */
341  outgoing_message->used_message_length += AddIntToMessage(
343  &outgoing_message->current_message_position);
344  outgoing_message->used_message_length += AddIntToMessage(
346  &outgoing_message->current_message_position);
347  outgoing_message->used_message_length += AddDintToMessage(
348  common_packet_format_data_item->address_item.data.connection_identifier,
349  &outgoing_message->current_message_position);
350  outgoing_message->used_message_length += AddDintToMessage(
351  common_packet_format_data_item->address_item.data.sequence_number,
352  &outgoing_message->current_message_position);
353  return outgoing_message->used_message_length;
354 }
355 
365  const CipCommonPacketFormatData *const common_packet_format_data_item,
366  ENIPMessage *const outgoing_message) {
367  outgoing_message->used_message_length += AddIntToMessage(
368  common_packet_format_data_item->item_count,
369  &outgoing_message->current_message_position); /* item count */
370  return outgoing_message->used_message_length;
371 }
372 
382  const CipCommonPacketFormatData *const common_packet_format_data_item,
383  ENIPMessage *const outgoing_message) {
384  outgoing_message->used_message_length += AddIntToMessage(
385  common_packet_format_data_item->data_item.type_id,
386  &outgoing_message->current_message_position);
387  return outgoing_message->used_message_length;
388 }
389 
399  const CipCommonPacketFormatData *const common_packet_format_data_item,
400  ENIPMessage *const outgoing_message) {
401  outgoing_message->used_message_length += AddIntToMessage(
402  common_packet_format_data_item->data_item.length,
403  &outgoing_message->current_message_position);
404  return outgoing_message->used_message_length;
405 }
406 
416  const CipCommonPacketFormatData *const common_packet_format_data_item,
417  ENIPMessage *const outgoing_message) {
418  for (size_t i = 0; i < common_packet_format_data_item->data_item.length;
419  i++) {
420  outgoing_message->used_message_length += AddSintToMessage(
421  *(common_packet_format_data_item->data_item.data + i),
422  &outgoing_message->current_message_position);
423  }
424  return outgoing_message->used_message_length;
425 }
426 
437  const CipMessageRouterResponse *const message_router_response,
438  ENIPMessage *const outgoing_message) {
439  outgoing_message->used_message_length += AddIntToMessage(
440  (EipUint16) ( message_router_response->data_length + 4 + 2 /* TODO: Magic numbers */
441  + (2 * message_router_response->size_of_additional_status) ),
442  &outgoing_message->current_message_position);
443  return outgoing_message->used_message_length;
444 }
445 
456  const CipCommonPacketFormatData *const common_packet_format_data_item,
457  ENIPMessage *const outgoing_message) {
458  outgoing_message->used_message_length += AddIntToMessage(
459  (EipUint16) common_packet_format_data_item->address_item.data
461  &outgoing_message->current_message_position);
462  return outgoing_message->used_message_length;
463 }
464 
474  const CipMessageRouterResponse *const message_router_response,
475  ENIPMessage *const outgoing_message) {
476  outgoing_message->used_message_length += AddSintToMessage(
477  message_router_response->reply_service,
478  &outgoing_message->current_message_position);
479  return outgoing_message->used_message_length;
480 }
481 
491  const CipMessageRouterResponse *const message_router_response,
492  ENIPMessage *const outgoing_message) {
493  outgoing_message->used_message_length += AddSintToMessage(
494  message_router_response->reserved,
495  &outgoing_message->current_message_position);
496  return outgoing_message->used_message_length;
497 }
498 
508  const CipMessageRouterResponse *const message_router_response,
509  ENIPMessage *const outgoing_message) {
510  outgoing_message->used_message_length += AddSintToMessage(
511  message_router_response->general_status,
512  &outgoing_message->current_message_position);
513  return outgoing_message->used_message_length;
514 }
515 
526  const CipMessageRouterResponse *const message_router_response,
527  ENIPMessage *const outgoing_message) {
528  outgoing_message->used_message_length += AddSintToMessage(
529  message_router_response->size_of_additional_status,
530  &outgoing_message->current_message_position);
531  return outgoing_message->used_message_length;
532 }
533 
543  const CipMessageRouterResponse *const message_router_response,
544  ENIPMessage *const outgoing_message) {
545  for (size_t i = 0; i < message_router_response->size_of_additional_status && i < MAX_SIZE_OF_ADD_STATUS;i++) {
546  outgoing_message->used_message_length += AddIntToMessage(
547  message_router_response->additional_status[i],
548  &outgoing_message->current_message_position);
549  }
550  return outgoing_message->used_message_length;
551 }
552 
566  const CipMessageRouterResponse *const message_router_response,
567  ENIPMessage *const outgoing_message) {
568  EncodeExtendedStatusLength(message_router_response, outgoing_message);
569  EncodeExtendedStatusDataItems(message_router_response, outgoing_message);
570 
571  return outgoing_message->used_message_length;
572 }
573 
583  const CipMessageRouterResponse *const message_router_response,
584  ENIPMessage *const outgoing_message) {
585  outgoing_message->used_message_length += AddIntToMessage(
586  (EipUint16) ( message_router_response->data_length + 4 /* TODO: Magic number */
587  + (2 * message_router_response->size_of_additional_status) ),
588  &outgoing_message->current_message_position);
589  return outgoing_message->used_message_length;
590 }
591 
599  const CipMessageRouterResponse *const message_router_response,
600  ENIPMessage *const outgoing_message) {
601  for (size_t i = 0; i < message_router_response->data_length; i++) {
602  outgoing_message->used_message_length +=
603  AddSintToMessage( (message_router_response->data)[i],
604  &outgoing_message->current_message_position );
605  }
606  return outgoing_message->used_message_length;
607 }
608 
619  int item_type,
620  const CipCommonPacketFormatData *const common_packet_format_data_item,
621  ENIPMessage *const outgoing_message) {
622  OPENER_ASSERT(item_type == 0 || item_type == 1)
623  outgoing_message->used_message_length += AddIntToMessage(
624  common_packet_format_data_item->address_info_item[item_type].type_id,
625  &outgoing_message->current_message_position);
626 
627  return outgoing_message->used_message_length;
628 }
629 
640  int item_type,
641  const CipCommonPacketFormatData *const common_packet_format_data_item,
642  ENIPMessage *const outgoing_message) {
643  outgoing_message->used_message_length += AddIntToMessage(
644  common_packet_format_data_item->address_info_item[item_type].length,
645  &outgoing_message->current_message_position);
646  return outgoing_message->used_message_length;
647 }
648 
650  const CipMessageRouterResponse *const message_router_response,
651  const CipCommonPacketFormatData *const common_packet_format_data_item,
652  ENIPMessage *const outgoing_message) {
653 
654  if (message_router_response) {
655  /* add Interface Handle and Timeout = 0 -> only for SendRRData and SendUnitData necessary */
656  outgoing_message->used_message_length += AddDintToMessage(0,
657  &outgoing_message->current_message_position);
658  outgoing_message->used_message_length += AddIntToMessage(0,
659  &outgoing_message->current_message_position);
660  }
661 
662  EncodeItemCount(common_packet_format_data_item, outgoing_message);
663 
664  /* process Address Item */
665  switch (common_packet_format_data_item->address_item.type_id) {
666  case kCipItemIdNullAddress: {
667  EncodeNullAddressItem(outgoing_message);
668  break;
669  }
671  EncodeConnectedAddressItem(common_packet_format_data_item,
672  outgoing_message);
673  break;
674  }
676  EncodeSequencedAddressItem(common_packet_format_data_item,
677  outgoing_message);
678  break;
679  }
680  default:
681  OPENER_TRACE_INFO("Unknown CIP Item in AssembleLinearMessage");
682  return kEipStatusError;
683  }
684 
685  /* process Data Item */
686  if ( (common_packet_format_data_item->data_item.type_id
688  || (common_packet_format_data_item->data_item.type_id
690 
691  if (message_router_response) {
692  EncodeDataItemType(common_packet_format_data_item,
693  outgoing_message);
694 
695  if (common_packet_format_data_item->data_item.type_id
696  == kCipItemIdConnectedDataItem) { /* Connected Item */
697  EncodeConnectedDataItemLength(message_router_response,
698  outgoing_message);
699  EncodeSequenceNumber(&g_common_packet_format_data_item,
700  outgoing_message);
701 
702  } else { /* Unconnected Item */
703  EncodeUnconnectedDataItemLength(message_router_response,
704  outgoing_message);
705  }
706 
707  /* write message router response into linear memory */
708  EncodeReplyService(message_router_response, outgoing_message);
709  EncodeReservedFieldOfLengthByte(message_router_response,
710  outgoing_message);
711  EncodeGeneralStatus(message_router_response, outgoing_message);
712  EncodeExtendedStatus(message_router_response, outgoing_message);
713  EncodeMessageRouterResponseData(message_router_response,
714  outgoing_message);
715  } else { /* connected IO Message to send */
716  EncodeDataItemType(common_packet_format_data_item,
717  outgoing_message);
718 
719  EncodeDataItemLength(common_packet_format_data_item,
720  outgoing_message);
721 
722  EncodeDataItemData(common_packet_format_data_item,
723  outgoing_message);
724  }
725  }
726 
727  /* process SockAddr Info Items */
728  /* make sure first the O->T and then T->O appears on the wire.
729  * EtherNet/IP specification doesn't demand it, but there are EIP
730  * devices which depend on CPF items to appear in the order of their
731  * ID number */
734  for (int j = 0; j < 2; j++) {
735  if (common_packet_format_data_item->address_info_item[j].type_id
736  == type) {
738  j, common_packet_format_data_item, outgoing_message);
739 
740  EncodeSockaddrInfoLength(j,common_packet_format_data_item,
741  outgoing_message);
742 
743  outgoing_message->used_message_length += EncapsulateIpAddress(
744  common_packet_format_data_item->address_info_item[j].sin_port,
745  common_packet_format_data_item->address_info_item[j].sin_addr,
746  &outgoing_message->current_message_position);
747 
748  outgoing_message->used_message_length +=
750  0, 8, &outgoing_message->current_message_position);
751  break;
752  }
753  }
754  }
755  return outgoing_message->used_message_length;
756 }
757 
759  const CipCommonPacketFormatData *const common_packet_format_data_item,
760  ENIPMessage *const outgoing_message) {
761  return AssembleLinearMessage(0, common_packet_format_data_item,
762  outgoing_message);
763 }
CipInt sin_family
Definition: cpf.h:59
int EncodeDataItemData(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Definition: cpf.c:415
EipUint16 type_id
Definition: cpf.h:48
int EncodeSequencedAddressItem(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Encodes a sequenced address item into the message.
Definition: cpf.c:337
int EncodeSockaddrInfoLength(int item_type, const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Encodes the sockaddr info length into the message.
Definition: cpf.c:639
EipStatus CreateCommonPacketFormatStructure(const EipUint8 *data, size_t data_length, CipCommonPacketFormatData *common_packet_format_data)
Creates Common Packet Format structure out of data.
Definition: cpf.c:204
Tracing infrastructure for OpENer.
EipStatus NotifyMessageRouter(EipUint8 *data, int data_length, const struct sockaddr *const originator_address, const int encapsulation_session)
Notify the MessageRouter that an explicit message (connected or unconnected) has been received...
EipUint16 additional_status[MAX_SIZE_OF_ADD_STATUS]
Definition: ciptypes.h:207
int FillNextNMessageOctetsWithValueAndMoveToNextPosition(CipOctet value, unsigned int amount_of_filled_bytes, CipOctet **message)
Definition: endianconv.c:271
int EncodeExtendedStatusLength(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the length of the extended status data part.
Definition: cpf.c:525
CipOctet message_buffer[PC_OPENER_ETHERNET_BUFFER_SIZE]
Definition: enipmessage.h:12
const EipUint8 * current_communication_buffer_position
Definition: encap.h:49
int EncodeExtendedStatus(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the extended status (length and data) into the message.
Definition: cpf.c:565
SocketAddressInfoItem address_info_item[2]
Definition: cpf.h:71
#define OPENER_ASSERT(assertion)
EipUint16 length
Definition: cpf.h:49
int EncodeUnconnectedDataItemLength(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encode the data item length of the unconnected data segment.
Definition: cpf.c:582
DataItem data_item
Definition: cpf.h:70
EipUint32 GetDintFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT32 from *buffer and converts little endian to host.
Definition: endianconv.c:83
CipOctet * current_message_position
Definition: enipmessage.h:13
CipCommonPacketFormatData g_common_packet_format_data_item
Data storage for the any CPF data Currently we are single threaded and need only one CPF at the time...
Definition: cpf.c:24
int EncodeDataItemType(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Definition: cpf.c:381
void ConnectionObjectResetInactivityWatchdogTimerValue(CipConnectionObject *const connection_object)
Responsible for Endianess conversion.
#define OPENER_TRACE_ERR(...)
Definition: trace.h:86
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)
Definition: encap.c:317
CipUint length
Definition: cpf.h:58
AddressData data
Definition: cpf.h:44
CipUint sin_port
Definition: cpf.h:60
CipUint type_id
Definition: cpf.h:57
#define MAX_SIZE_OF_ADD_STATUS
Definition: ciptypes.h:194
CipUdint sin_addr
Definition: cpf.h:61
int EncodeItemCount(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Adds the item count to the message frame.
Definition: cpf.c:364
int EncodeConnectedDataItemLength(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the Connected Data item length.
Definition: cpf.c:436
int AssembleIOMessage(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Definition: cpf.c:758
int EncodeSockaddrInfoItemTypeId(int item_type, const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Encodes the sockaddr info type id into the message.
Definition: cpf.c:618
uint8_t CipOctet
Data types as defined in the CIP Specification Vol 1 Appendix C.
Definition: typedefs.h:41
CipUint length
Definition: cpf.h:43
int AddIntToMessage(const EipUint16 data, EipUint8 **const buffer)
converts UINT16 data from host to little endian an writes it to buffer.
Definition: endianconv.c:117
EipStatus
EIP stack status enum.
Definition: typedefs.h:93
int EncodeGeneralStatus(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the general status of a Router Response.
Definition: cpf.c:507
uint8_t EipUint8
Definition: typedefs.h:32
CipMessageRouterResponse g_message_router_response
Structure for storing the Response generated by an explict message.
uint32_t EipUint32
Definition: typedefs.h:34
int AddDintToMessage(const EipUint32 data, EipUint8 **const buffer)
Converts UINT32 data from host to little endian and writes it to buffer.
Definition: endianconv.c:132
int EncodeConnectedAddressItem(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Definition: cpf.c:314
#define OPENER_TRACE_INFO(...)
Definition: trace.h:89
int AddSintToMessage(const EipUint8 data, EipUint8 **const buffer)
converts UINT8 data from host to little endian an writes it to buffer.
Definition: endianconv.c:103
void SkipEncapsulationHeader(ENIPMessage *const outgoing_message)
Definition: encap.c:312
int EncodeMessageRouterResponseData(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the Message Router Response data.
Definition: cpf.c:598
int NotifyConnectedCommonPacketFormat(const EncapsulationData *const received_data, const struct sockaddr *const originator_address, ENIPMessage *const outgoing_message)
Definition: cpf.c:91
int EncodeSequenceNumber(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Encodes a sequence number into the message.
Definition: cpf.c:455
int EncodeDataItemLength(const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Definition: cpf.c:398
#define ENCAPSULATION_HEADER_LENGTH
Definition: encap.h:22
EipUint32 sequence_number
Definition: cpf.h:38
EipUint16 item_count
Definition: cpf.h:68
CipUdint session_handle
Definition: encap.h:44
int EncodeReplyService(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the reply service code for the requested service.
Definition: cpf.c:473
int EncodeNullAddressItem(ENIPMessage *const outgoing_message)
Encodes a Null Address Item into the message frame.
Definition: cpf.c:297
AddressItem address_item
Definition: cpf.h:69
const size_t item_count_field_size
Definition: cpf.c:19
#define OPENER_TRACE_WARN(...)
Definition: trace.h:87
CipUint data_length
Definition: encap.h:43
This file contains the public interface of the encapsulation layer.
size_t EncodeExtendedStatusDataItems(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the extended status data items.
Definition: cpf.c:542
int AssembleLinearMessage(const CipMessageRouterResponse *const message_router_response, const CipCommonPacketFormatData *const common_packet_format_data_item, ENIPMessage *const outgoing_message)
Copy data from message_router_response struct and common_packet_format_data_item into ENIPMessage str...
Definition: cpf.c:649
CipConnectionObject * GetConnectedObject(const EipUint32 connection_id)
Get a connected object dependent on requested ConnectionID.
EipUint8 * data
Definition: cpf.h:50
const size_t item_data_type_id_field_length
Definition: cpf.c:20
CipUint type_id
Definition: cpf.h:42
uint16_t CipUint
Definition: typedefs.h:47
EipUint32 connection_identifier
Definition: cpf.h:37
EipUint16 GetIntFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT16 from *buffer and converts little endian to host.
Definition: endianconv.c:57
CipUsint nasin_zero[8]
Definition: cpf.h:62
size_t used_message_length
Definition: enipmessage.h:14
CIP Message Router Response.
Definition: ciptypes.h:199
int EncapsulateIpAddress(EipUint16 port, EipUint32 address, EipByte **communication_buffer)
Encapsulate the sockaddr information as necessary for the Common Packet Format data items...
Definition: endianconv.c:197
A variant of a CPF packet, including item count, one address item, one data item, and two Sockaddr In...
Definition: cpf.h:67
uint16_t EipUint16
Definition: typedefs.h:33
const size_t sequenced_address_item_length
Definition: cpf.c:22
int NotifyCommonPacketFormat(EncapsulationData *const received_data, const struct sockaddr *const originator_address, ENIPMessage *const outgoing_message)
Definition: cpf.c:26
int EncodeReservedFieldOfLengthByte(const CipMessageRouterResponse *const message_router_response, ENIPMessage *const outgoing_message)
Encodes the reserved byte in the message router response.
Definition: cpf.c:490
CipUsint size_of_additional_status
Definition: ciptypes.h:205