cipstringi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*******************************************************************************
  2. * Copyright (c) 2022, Rockwell Automation, Inc.
  3. * All rights reserved.
  4. *
  5. ******************************************************************************/
  6. #include <string.h>
  7. #include "cipstringi.h"
  8. #include "opener_api.h"
  9. #include "cipstring.h"
  10. #include "trace.h"
  11. #include "endianconv.h"
  12. void CipStringIDelete(CipStringI *const string) {
  13. for(size_t i = 0; i < string->number_of_strings; ++i) {
  14. string->array_of_string_i_structs[i].language_char_1 = '\0';
  15. string->array_of_string_i_structs[i].language_char_2 = '\0';
  16. string->array_of_string_i_structs[i].language_char_3 = '\0';
  17. string->array_of_string_i_structs[i].character_set = '\0';
  18. switch(string->array_of_string_i_structs[i].char_string_struct) {
  19. case kCipShortString:
  20. ClearCipShortString(
  21. (CipShortString *) &string->array_of_string_i_structs[i].string );
  22. break;
  23. case kCipString:
  24. ClearCipString(
  25. (CipString *) &string->array_of_string_i_structs[i].string );
  26. break;
  27. case kCipString2:
  28. ClearCipString2(
  29. (CipString2 *) &string->array_of_string_i_structs[i].string );
  30. break;
  31. case kCipStringN:
  32. ClearCipStringN(
  33. (CipStringN *) &string->array_of_string_i_structs[i].string );
  34. break;
  35. default:
  36. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  37. }
  38. string->array_of_string_i_structs[i].char_string_struct = 0x00;
  39. }
  40. string->number_of_strings = 0;
  41. CipFree(string->array_of_string_i_structs);
  42. string->array_of_string_i_structs = NULL;
  43. }
  44. bool CipStringIsAnyStringEmpty(const CipStringI *const string) {
  45. for(size_t i = 0; i < string->number_of_strings; ++i) {
  46. size_t length = 0;
  47. void *pointer_to_string = string->array_of_string_i_structs[i].string;
  48. switch(string->array_of_string_i_structs[i].char_string_struct) {
  49. case kCipShortString:
  50. length = ( (CipShortString *) pointer_to_string )->length;
  51. break;
  52. case kCipString:
  53. length = ( (CipString *) pointer_to_string )->length;
  54. break;
  55. case kCipString2:
  56. length = ( (CipString2 *) pointer_to_string )->length;
  57. break;
  58. case kCipStringN:
  59. length = ( (CipStringN *) pointer_to_string )->length;
  60. break;
  61. default:
  62. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  63. }
  64. if(0 == length) {
  65. return true;
  66. }
  67. }
  68. return false;
  69. }
  70. void *CipStringICreateStringStructure(CipStringIStruct *const to) {
  71. switch(to->char_string_struct) {
  72. case kCipShortString:
  73. return to->string = CipCalloc(1, sizeof(CipShortString) );
  74. case kCipString:
  75. return to->string = CipCalloc(1, sizeof(CipString) );
  76. case kCipString2:
  77. return to->string = CipCalloc(1, sizeof(CipString2) );
  78. case kCipStringN:
  79. return to->string = CipCalloc(1, sizeof(CipStringN) );
  80. default:
  81. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  82. }
  83. return NULL;
  84. }
  85. void CipStringIDeepCopyInternalString(CipStringIStruct *const to,
  86. const CipStringIStruct *const from) {
  87. switch(to->char_string_struct) {
  88. case kCipShortString: {
  89. CipShortString *toString = (CipShortString *) to->string;
  90. CipShortString *fromString = (CipShortString *) from->string;
  91. toString->length = fromString->length;
  92. toString->string = CipCalloc(toString->length, sizeof(CipOctet) );
  93. memcpy(toString->string,
  94. fromString->string,
  95. sizeof(CipOctet) * toString->length);
  96. }
  97. break;
  98. case kCipString: {
  99. CipString *toString = (CipString *) to->string;
  100. CipString *fromString = (CipString *) from->string;
  101. toString->length = fromString->length;
  102. toString->string = CipCalloc(toString->length, sizeof(CipOctet) );
  103. memcpy(toString->string,
  104. fromString->string,
  105. sizeof(CipOctet) * toString->length);
  106. }
  107. break;
  108. case kCipString2: {
  109. CipString2 *toString = (CipString2 *) to->string;
  110. CipString2 *fromString = (CipString2 *) from->string;
  111. toString->length = fromString->length;
  112. toString->string = CipCalloc(toString->length, 2 * sizeof(CipOctet) );
  113. memcpy(toString->string,
  114. fromString->string,
  115. 2 * sizeof(CipOctet) * toString->length);
  116. }
  117. break;
  118. case kCipStringN: {
  119. CipStringN *toString = (CipStringN *) to->string;
  120. CipStringN *fromString = (CipStringN *) from->string;
  121. toString->length = fromString->length;
  122. toString->size = fromString->size;
  123. toString->string =
  124. CipCalloc(toString->length, toString->size * sizeof(CipOctet) );
  125. memcpy(toString->string, fromString->string,
  126. toString->size * sizeof(CipOctet) * toString->length);
  127. }
  128. break;
  129. default:
  130. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  131. }
  132. }
  133. void CipStringICopy(CipStringI *const to,
  134. const CipStringI *const from) {
  135. to->number_of_strings = from->number_of_strings;
  136. to->array_of_string_i_structs =
  137. CipCalloc(to->number_of_strings, sizeof(CipStringIStruct) );
  138. for(size_t i = 0; i < to->number_of_strings; ++i) {
  139. CipStringIStruct *const toStruct = to->array_of_string_i_structs + i;
  140. CipStringIStruct *const fromStruct = from->array_of_string_i_structs + i;
  141. toStruct->language_char_1 = fromStruct->language_char_1;
  142. toStruct->language_char_2 = fromStruct->language_char_2;
  143. toStruct->language_char_3 = fromStruct->language_char_3;
  144. toStruct->char_string_struct = fromStruct->char_string_struct;
  145. toStruct->character_set = fromStruct->character_set;
  146. CipStringICreateStringStructure(toStruct);
  147. CipStringIDeepCopyInternalString(toStruct, fromStruct);
  148. }
  149. }
  150. void CipStringIDecodeFromMessage(CipStringI *data_to,
  151. CipMessageRouterRequest *const message_router_request)
  152. {
  153. CipStringI *target_stringI = data_to;
  154. target_stringI->number_of_strings = GetUsintFromMessage(
  155. &message_router_request->data);
  156. target_stringI->array_of_string_i_structs = CipCalloc(
  157. target_stringI->number_of_strings, sizeof(CipStringIStruct) );
  158. for (size_t i = 0; i < target_stringI->number_of_strings; ++i) {
  159. target_stringI->array_of_string_i_structs[i].language_char_1 =
  160. GetUsintFromMessage(&message_router_request->data);
  161. target_stringI->array_of_string_i_structs[i].language_char_2 =
  162. GetUsintFromMessage(&message_router_request->data);
  163. target_stringI->array_of_string_i_structs[i].language_char_3 =
  164. GetUsintFromMessage(&message_router_request->data);
  165. target_stringI->array_of_string_i_structs[i].char_string_struct =
  166. GetUsintFromMessage(&message_router_request->data);
  167. target_stringI->array_of_string_i_structs[i].character_set =
  168. GetUintFromMessage(&message_router_request->data);
  169. switch (target_stringI->array_of_string_i_structs[i].char_string_struct) {
  170. case kCipShortString: {
  171. target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
  172. sizeof(
  173. CipShortString) );
  174. CipShortString *short_string =
  175. (CipShortString *) (target_stringI->array_of_string_i_structs[i].
  176. string);
  177. CipUsint length = GetUsintFromMessage(
  178. &message_router_request->data);
  179. SetCipShortStringByData(short_string, length,
  180. message_router_request->data);
  181. message_router_request->data += length;
  182. }
  183. break;
  184. case kCipString: {
  185. target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
  186. sizeof(
  187. CipString) );
  188. CipString *const string =
  189. (CipString *const ) target_stringI->array_of_string_i_structs[i].
  190. string;
  191. CipUint length = GetUintFromMessage(&message_router_request->data);
  192. SetCipStringByData(string, length, message_router_request->data);
  193. message_router_request->data += length;
  194. }
  195. break;
  196. case kCipString2: {
  197. target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
  198. sizeof(
  199. CipString2) );
  200. CipString2 *const string =
  201. (CipString2 *const ) target_stringI->array_of_string_i_structs[i].
  202. string;
  203. CipUint length = GetUintFromMessage(&message_router_request->data);
  204. SetCipString2ByData(string, length, message_router_request->data);
  205. message_router_request->data += length * 2 * sizeof(CipOctet);
  206. }
  207. break;
  208. case kCipStringN: {
  209. CipUint size = GetUintFromMessage(&message_router_request->data);
  210. CipUint length = GetUintFromMessage(&message_router_request->data);
  211. target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
  212. sizeof(
  213. CipStringN) );
  214. CipStringN *const string =
  215. (CipStringN *const ) target_stringI->array_of_string_i_structs[i].
  216. string;
  217. SetCipStringNByData(string, length, size,
  218. message_router_request->data);
  219. message_router_request->data += length * size;
  220. }
  221. break;
  222. default:
  223. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  224. }
  225. } //end for
  226. }
  227. bool CipStringICompare(const CipStringI *const stringI_1,
  228. const CipStringI *const stringI_2) {
  229. /*loop through struct 1 strings*/
  230. for (size_t i = 0; i < stringI_1->number_of_strings; ++i) {
  231. // String 1
  232. void *string_1 = stringI_1->array_of_string_i_structs[i].string;
  233. void *string_1_data = NULL;
  234. CipUint len_1 = 0; //size of string-struct in bytes
  235. switch (stringI_1->array_of_string_i_structs[i].char_string_struct) {
  236. case kCipShortString: {
  237. len_1 = ((CipShortString *)string_1)->length;
  238. string_1_data = ((CipShortString *)string_1)->string;
  239. }
  240. break;
  241. case kCipString: {
  242. len_1 = ((CipString *)string_1)->length;
  243. string_1_data = ((CipString *)string_1)->string;
  244. }
  245. break;
  246. case kCipString2: {
  247. len_1 = ((CipString2 *)string_1)->length * 2;
  248. string_1_data = ((CipString2 *)string_1)->string;
  249. }
  250. break;
  251. case kCipStringN: {
  252. CipUint length = ((CipStringN *)string_1)->length;
  253. CipUint size = ((CipStringN *)string_1)->size; //bytes per symbol
  254. len_1 = length * size;
  255. string_1_data = ((CipStringN *)string_1)->string;
  256. }
  257. break;
  258. default:
  259. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  260. }
  261. /*loop through struct 2 strings*/
  262. for (size_t j = 0; j < stringI_2->number_of_strings; ++j) {
  263. // String 2
  264. void *string_2 = stringI_2->array_of_string_i_structs[j].string;
  265. void *string_2_data = NULL;
  266. CipUint len_2 = 0; //size of string-struct in bytes
  267. switch (stringI_2->array_of_string_i_structs[j].char_string_struct) {
  268. case kCipShortString: {
  269. len_2 = ((CipShortString *)string_2)->length;
  270. string_2_data = ((CipShortString *)string_2)->string;
  271. }
  272. break;
  273. case kCipString: {
  274. len_2 = ((CipString *)string_2)->length;
  275. string_2_data = ((CipString *)string_2)->string;
  276. }
  277. break;
  278. case kCipString2: {
  279. len_2 = ((CipString2 *)string_2)->length * 2;
  280. string_2_data = ((CipString2 *)string_2)->string;
  281. }
  282. break;
  283. case kCipStringN: {
  284. CipUint length = ((CipStringN *)string_2)->length;
  285. CipUint size = ((CipStringN *)string_2)->size; //bytes per symbol
  286. len_2 = length * size;
  287. string_2_data = ((CipStringN *)string_2)->string;
  288. }
  289. break;
  290. default:
  291. OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
  292. }
  293. /*compare strings*/ //TODO: compare works only for same data types
  294. if (len_1 == len_2 && string_1_data != NULL && string_2_data != NULL) {
  295. if (0 == memcmp(string_1_data, string_2_data, len_1) ) {
  296. return true;
  297. }
  298. }
  299. } //end for 1
  300. } //end for 2
  301. return false;
  302. }