cipforwardopen.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*******************************************************************************
  2. * Copyright (c) 2016, Rockwell Automation, Inc.
  3. * All rights reserved.
  4. *
  5. ******************************************************************************/
  6. #include "cipforwardopen.h"
  7. #include "endianconv.h"
  8. typedef struct cip_forward_open_data {
  9. CipByte priority_time_tick;
  10. CipUsint timeout_ticks;
  11. CipUdint originiator_to_target_network_connection_id;
  12. CipUdint target_to_originator_network_connection_id;
  13. CipUint connection_serial_number;
  14. CipUint originator_vendor_id;
  15. CipUdint originator_serial_number;
  16. CipUsint connection_timeout_multiplier;
  17. CipUdint originator_to_target_requested_packet_interval;
  18. CipWord originator_to_target_network_connection_parameters;
  19. CipUdint target_to_originator_requested_packet_interval;
  20. CipWord target_to_originator_network_connection_parameters;
  21. CipByte transport_class_and_trigger;
  22. CipUsint connection_path_size;
  23. const CipOctet *connection_path;
  24. } CipForwardOpenData;
  25. const size_t CipForwardOpenDataSize = sizeof(CipForwardOpenData);
  26. const CipOctet *CipForwardOpenGetForwardOpenDataFromMessage(
  27. CipForwardOpenData *const data, const CipOctet **const message) {
  28. const CipOctet **message_runner = message;
  29. data->priority_time_tick = GetByteFromMessage(message_runner);
  30. data->timeout_ticks = GetUsintFromMessage(message_runner);
  31. data->originiator_to_target_network_connection_id = GetUdintFromMessage(
  32. message_runner);
  33. data->target_to_originator_network_connection_id = GetUdintFromMessage(
  34. message_runner);
  35. data->connection_serial_number = GetUintFromMessage(message_runner);
  36. data->originator_vendor_id = GetUintFromMessage(message_runner);
  37. data->originator_serial_number = GetUdintFromMessage(message_runner);
  38. data->connection_timeout_multiplier = GetUsintFromMessage(message_runner);
  39. *message_runner += 3; //Move pointer over the reserved space
  40. data->originator_to_target_requested_packet_interval = GetUdintFromMessage(
  41. message_runner);
  42. data->originator_to_target_network_connection_parameters = GetWordFromMessage(
  43. message_runner);
  44. data->target_to_originator_requested_packet_interval = GetUdintFromMessage(
  45. message_runner);
  46. data->target_to_originator_network_connection_parameters = GetWordFromMessage(
  47. message_runner);
  48. data->transport_class_and_trigger = GetByteFromMessage(message_runner);
  49. data->connection_path_size = GetUsintFromMessage(message_runner);
  50. data->connection_path = *message_runner;
  51. *message_runner = *message_runner + data->connection_path_size *
  52. sizeof(CipOctet);
  53. return *message_runner;
  54. }
  55. CipForwardOpenPriorityTickTime CipForwardOpenGetPriorityTickTime(
  56. CipForwardOpenData *forward_open_data) {
  57. const CipByte kPriorityMask = 0x10;
  58. if( kPriorityMask ==
  59. ( (forward_open_data->priority_time_tick) & kPriorityMask ) ) {
  60. return kCipForwardOpenPriorityTickTimeReserved;
  61. }
  62. else {
  63. return kCipForwardOpenPriorityTickTimeNormal;
  64. }
  65. }
  66. uint8_t CipForwardOpenGetTickTime(CipForwardOpenData *forward_open_data) {
  67. const CipByte kTickTimeMask = 0x0F;
  68. return (forward_open_data->priority_time_tick & kTickTimeMask);
  69. }
  70. CipUsint CipForwardOpenGetTimeoutTick(CipForwardOpenData *forward_open_data) {
  71. return forward_open_data->timeout_ticks;
  72. }
  73. MilliSeconds CipForwardOpenGetTimeoutInMilliseconds(
  74. CipForwardOpenData *forward_open_data) {
  75. return CipForwardOpenGetTimeoutTick(forward_open_data) * 1 <<
  76. CipForwardOpenGetTickTime(forward_open_data);
  77. }
  78. CipUdint CipForwardOpenGetOriginatorToTargetNetworkConnectionId(
  79. CipForwardOpenData *forward_open_data) {
  80. return forward_open_data->originiator_to_target_network_connection_id;
  81. }
  82. CipUdint CipForwardOpenGetTargetToOriginatorNetworkConnectionId(
  83. CipForwardOpenData *forward_open_data) {
  84. return forward_open_data->target_to_originator_network_connection_id;
  85. }
  86. CipUint CipForwardOpenGetConnectionSerialNumber(
  87. CipForwardOpenData *forward_open_data) {
  88. return forward_open_data->connection_serial_number;
  89. }
  90. CipUint CipForwardOpenGetOriginatorVendorId(
  91. CipForwardOpenData *forward_open_data) {
  92. return forward_open_data->originator_vendor_id;
  93. }
  94. CipUdint CipForwardOpenGetOriginatorSerialNumber(
  95. CipForwardOpenData *forward_open_data) {
  96. return forward_open_data->originator_serial_number;
  97. }
  98. uint16_t CipForwardOpenGetTimeoutMultiplier(
  99. CipForwardOpenData *forward_open_data) {
  100. if (8 > forward_open_data->connection_timeout_multiplier) {
  101. return 4 << forward_open_data->connection_timeout_multiplier;
  102. }
  103. return 0;
  104. }
  105. MicroSeconds CipForwardOpenGetOriginatorToTargetRequestedPacketInterval(
  106. CipForwardOpenData *forward_open_data) {
  107. return forward_open_data->originator_to_target_requested_packet_interval;
  108. }
  109. CipWord CipForwardOpenGetOriginatorToTargetNetworkConnectionParameters(
  110. CipForwardOpenData *forward_open_data) {
  111. return forward_open_data->originator_to_target_network_connection_parameters;
  112. }
  113. static bool GetRedundantOwner(const CipWord connection_parameters) {
  114. const CipWord kRedundantOwnerMask = 0x8000;
  115. if ( kRedundantOwnerMask == (kRedundantOwnerMask & connection_parameters) ) {
  116. return true;
  117. }
  118. return false;
  119. }
  120. bool CipForwardOpenGetOriginatorToTargetRedundantOwner(
  121. CipForwardOpenData *forward_open_data) {
  122. return GetRedundantOwner( CipForwardOpenGetOriginatorToTargetNetworkConnectionParameters(
  123. forward_open_data) );
  124. }
  125. static CipForwardOpenConnectionType GetConnectionType(
  126. CipWord connection_parameters) {
  127. #define NULL_CONNECTION_TYPE 0x0000
  128. #define MULTICAST_CONNECTION_TYPE 0x2000
  129. #define POINT_TO_POINT_CONNECTION_TYPE 0x4000
  130. const CipWord kConnectionTypeMask = 0x6000;
  131. const CipWord kConnectionType = kConnectionTypeMask & connection_parameters;
  132. CipForwardOpenConnectionType type = kCipForwardOpenConnectionTypeReserved;
  133. switch(kConnectionType) {
  134. case NULL_CONNECTION_TYPE: type = kCipForwardOpenConnectionTypeNull; break;
  135. case MULTICAST_CONNECTION_TYPE: type =
  136. kCipForwardOpenConnectionTypeMulticastConnection; break;
  137. case POINT_TO_POINT_CONNECTION_TYPE: type =
  138. kCipForwardOpenConnectionTypePointToPointConnection; break;
  139. default: type = kCipForwardOpenConnectionTypeReserved; break;
  140. }
  141. return type;
  142. #undef NULL_CONNECTION_TYPE
  143. #undef MULTICAST_CONNECTION_TYPE
  144. #undef POINT_TO_POINT_CONNECTION_TYPE
  145. }
  146. CipForwardOpenConnectionType CipForwardOpenGetOriginatorToTargetConnectionType(
  147. CipForwardOpenData *forward_open_data) {
  148. return GetConnectionType( CipForwardOpenGetOriginatorToTargetNetworkConnectionParameters(
  149. forward_open_data) );
  150. }
  151. static CipForwardOpenConnectionPriority GetConnectionPriority(
  152. const CipWord connection_parameters) {
  153. #define LOW_PRIORITY 0x0000
  154. #define HIGH_PRIORITY 0x0800
  155. #define SCHEDULED_PRIORITY 0x1000
  156. #define URGENT_PRIORITY 0x1800
  157. const CipWord kPriorityMask = 0x1800;
  158. const CipWord kPriority = kPriorityMask & connection_parameters;
  159. CipForwardOpenConnectionPriority priority =
  160. kCipForwardOpenConnectionPriorityLow;
  161. switch(kPriority) {
  162. case LOW_PRIORITY: priority = kCipForwardOpenConnectionPriorityLow; break;
  163. case HIGH_PRIORITY: priority = kCipForwardOpenConnectionPriorityHigh; break;
  164. case SCHEDULED_PRIORITY: priority =
  165. kCipForwardOpenConnectionPriorityScheduled; break;
  166. case URGENT_PRIORITY: priority = kCipForwardOpenConnectionPriorityUrgent;
  167. break;
  168. }
  169. return priority;
  170. #undef LOW_PRIORITY
  171. #undef HIGH_PRIORITY
  172. #undef SCHEDULED_PRIORITY
  173. #undef URGENT_PRIORITY
  174. }
  175. CipForwardOpenConnectionPriority
  176. CipForwardOpenGetOriginatorToTargetConnectionPriority(
  177. CipForwardOpenData *forward_open_data) {
  178. return GetConnectionPriority( CipForwardOpenGetOriginatorToTargetNetworkConnectionParameters(
  179. forward_open_data) );
  180. }
  181. static CipForwardOpenConnectionSizeType GetConnectionSizeType(
  182. CipWord connection_parameters) {
  183. #define CONNECTION_SIZE_TYPE_FIXED 0x0000
  184. #define CONNECTION_SIZE_TYPE_VARIABLE 0x0200
  185. const CipWord kConnectionSizeTypeMask = 0x0200;
  186. const CipWord kConnectionSizeType = kConnectionSizeTypeMask &
  187. connection_parameters;
  188. CipForwardOpenConnectionSizeType type =
  189. kCipForwardOpenConnectionSizeTypeFixed;
  190. switch (kConnectionSizeType) {
  191. case CONNECTION_SIZE_TYPE_FIXED: type =
  192. kCipForwardOpenConnectionSizeTypeFixed; break;
  193. case CONNECTION_SIZE_TYPE_VARIABLE: type =
  194. kCipForwardOpenConnectionSizeTypeVariable; break;
  195. }
  196. return type;
  197. #undef CONNECTION_SIZE_TYPE_FIXED
  198. #undef CONNECTION_SIZE_TYPE_VARIABLE
  199. }
  200. CipForwardOpenConnectionSizeType
  201. CipForwardOpenGetOriginatorToTargetConnectionSizeType(
  202. CipForwardOpenData *forward_open_data) {
  203. return GetConnectionSizeType( CipForwardOpenGetOriginatorToTargetNetworkConnectionParameters(
  204. forward_open_data) );
  205. }
  206. static uint16_t GetConnectionSize(CipWord connection_parameters) {
  207. const CipWord kConnectionSizeMask = 0x01FF;
  208. return kConnectionSizeMask & connection_parameters;
  209. }
  210. uint16_t CipForwardOpenGetOriginatorToTargetConnectionSize(
  211. CipForwardOpenData *forward_open_data) {
  212. return GetConnectionSize( CipForwardOpenGetOriginatorToTargetNetworkConnectionParameters(
  213. forward_open_data) );
  214. }
  215. MicroSeconds CipForwardOpenGetTargetToOriginatorRequestedPacketInterval(
  216. CipForwardOpenData *forward_open_data) {
  217. return forward_open_data->target_to_originator_requested_packet_interval;
  218. }
  219. CipWord CipForwardOpenGetTargetToOriginatorNetworkConnectionParameters(
  220. CipForwardOpenData *forward_open_data) {
  221. return forward_open_data->target_to_originator_network_connection_parameters;
  222. }
  223. bool CipForwardOpenGetTargetToOriginatorRedundantOwner(
  224. CipForwardOpenData *forward_open_data) {
  225. return GetRedundantOwner( CipForwardOpenGetTargetToOriginatorNetworkConnectionParameters(
  226. forward_open_data) );
  227. }
  228. CipForwardOpenConnectionType CipForwardOpenGetTargetToOriginatorConnectionType(
  229. CipForwardOpenData *forward_open_data) {
  230. return GetConnectionType( CipForwardOpenGetTargetToOriginatorNetworkConnectionParameters(
  231. forward_open_data) );
  232. }
  233. CipForwardOpenConnectionPriority
  234. CipForwardOpenGetTargetToOriginatorConnectionPriority(
  235. CipForwardOpenData *forward_open_data) {
  236. return GetConnectionPriority( CipForwardOpenGetTargetToOriginatorNetworkConnectionParameters(
  237. forward_open_data) );
  238. }
  239. CipForwardOpenConnectionSizeType
  240. CipForwardOpenGetTargetToOriginatorConnectionSizeType(
  241. CipForwardOpenData *forward_open_data) {
  242. return GetConnectionSizeType( CipForwardOpenGetTargetToOriginatorNetworkConnectionParameters(
  243. forward_open_data) );
  244. }
  245. uint16_t CipForwardOpenGetTargetToOriginatorConnectionSize(
  246. CipForwardOpenData *forward_open_data) {
  247. return GetConnectionSize( CipForwardOpenGetTargetToOriginatorNetworkConnectionParameters(
  248. forward_open_data) );
  249. }
  250. CipConnectionObjectTransportClassTriggerDirection
  251. CipForwardOpenGetTransportClassTriggerDirection(
  252. CipForwardOpenData *forward_open_data) {
  253. #define DIRECTION_CLIENT 0x00
  254. #define DIRECTION_SERVER 0x80
  255. const CipByte kDirectionMask = 0x80;
  256. const CipByte kDirection = kDirectionMask &
  257. forward_open_data->transport_class_and_trigger;
  258. CipConnectionObjectTransportClassTriggerDirection direction =
  259. kCipConnectionObjectTransportClassTriggerDirectionClient;
  260. switch(kDirection) {
  261. case DIRECTION_CLIENT: direction =
  262. kCipConnectionObjectTransportClassTriggerDirectionClient; break;
  263. case DIRECTION_SERVER: direction =
  264. kCipConnectionObjectTransportClassTriggerDirectionServer; break;
  265. }
  266. return direction;
  267. #undef DIRECTION_CLIENT
  268. #undef DIRECTION_SERVER
  269. }
  270. CipConnectionObjectTransportClassTriggerProductionTrigger
  271. CipForwardOpenGetTransportClassTriggerProductionTrigger(
  272. CipForwardOpenData *forward_open_data) {
  273. #define PRODUCTION_TRIGGER_CYCLIC 0x00
  274. #define PRODUCTION_TRIGGER_CHANGE_OF_STATE 0x10
  275. #define PRODUCTION_TRIGGER_APPLICATION_OBJECT 0x20
  276. const CipByte kProductionTriggerMask = 0x70;
  277. const CipByte kProductionTrigger = kProductionTriggerMask &
  278. forward_open_data->
  279. transport_class_and_trigger;
  280. CipConnectionObjectTransportClassTriggerProductionTrigger trigger =
  281. kCipConnectionObjectTransportClassTriggerProductionTriggerCyclic;
  282. switch(kProductionTrigger) {
  283. case PRODUCTION_TRIGGER_CYCLIC: trigger =
  284. kCipConnectionObjectTransportClassTriggerProductionTriggerCyclic; break;
  285. case PRODUCTION_TRIGGER_CHANGE_OF_STATE: trigger =
  286. kCipConnectionObjectTransportClassTriggerProductionTriggerChangeOfState;
  287. break;
  288. case PRODUCTION_TRIGGER_APPLICATION_OBJECT: trigger =
  289. kCipConnectionObjectTransportClassTriggerProductionTriggerApplicationObject;
  290. break;
  291. }
  292. return trigger;
  293. #undef PRODUCTION_TRIGGER_CYCLIC
  294. #undef PRODUCTION_TRIGGER_CHANGE_OF_STATE
  295. #undef PRODUCTION_TRIGGER_APPLICATION_OBJECT
  296. }
  297. CipConnectionObjectTransportClassTriggerClass
  298. CipForwardOpenGetTransportClassTriggerClass(
  299. CipForwardOpenData *forward_open_data) {
  300. #define TRANSPORT_CLASS_0 0x00
  301. #define TRANSPORT_CLASS_1 0x01
  302. #define TRANSPORT_CLASS_2 0x02
  303. #define TRANSPORT_CLASS_3 0x03
  304. const CipByte kTransportClassMask = 0x0F;
  305. const CipByte kTransportClass = kTransportClassMask &
  306. forward_open_data->transport_class_and_trigger;
  307. CipConnectionObjectTransportClassTriggerClass transport_class =
  308. kCipConnectionObjectTransportClassTriggerClass0;
  309. switch(kTransportClass) {
  310. case TRANSPORT_CLASS_0: transport_class =
  311. kCipConnectionObjectTransportClassTriggerClass0; break;
  312. case TRANSPORT_CLASS_1: transport_class =
  313. kCipConnectionObjectTransportClassTriggerClass1; break;
  314. case TRANSPORT_CLASS_2: transport_class =
  315. kCipConnectionObjectTransportClassTriggerClass2; break;
  316. case TRANSPORT_CLASS_3: transport_class =
  317. kCipConnectionObjectTransportClassTriggerClass3; break;
  318. }
  319. return transport_class;
  320. #undef TRANSPORT_CLASS_0
  321. #undef TRANSPORT_CLASS_1
  322. #undef TRANSPORT_CLASS_2
  323. #undef TRANSPORT_CLASS_3
  324. }
  325. CipUsint CipForwardOpenGetConnectionPathSizeInWords(
  326. CipForwardOpenData *forward_open_data) {
  327. return forward_open_data->connection_path_size;
  328. }
  329. const CipOctet *CipForwardOpenGetConnectionPath(
  330. CipForwardOpenData *forward_open_data) {
  331. return forward_open_data->connection_path;
  332. }