modbus-tcp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. /*
  2. * Copyright © 2001-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #ifndef _MSC_VER
  22. #include <unistd.h>
  23. #endif
  24. #include <signal.h>
  25. #include <sys/types.h>
  26. #if defined(_WIN32)
  27. # define OS_WIN32
  28. /* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
  29. * minwg32 headers check WINVER before allowing the use of these */
  30. # ifndef WINVER
  31. # define WINVER 0x0501
  32. # endif
  33. # include <ws2tcpip.h>
  34. # define SHUT_RDWR 2
  35. # define close closesocket
  36. #else
  37. # include <sys/socket.h>
  38. # include <sys/ioctl.h>
  39. #if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5)
  40. # define OS_BSD
  41. # include <netinet/in_systm.h>
  42. #endif
  43. # include <netinet/in.h>
  44. # include <netinet/ip.h>
  45. # include <netinet/tcp.h>
  46. # include <arpa/inet.h>
  47. # include <poll.h>
  48. # include <netdb.h>
  49. #endif
  50. #if !defined(MSG_NOSIGNAL)
  51. #define MSG_NOSIGNAL 0
  52. #endif
  53. #include "modbus-private.h"
  54. #include "modbus-tcp.h"
  55. #include "modbus-tcp-private.h"
  56. #ifdef OS_WIN32
  57. static int _modbus_tcp_init_win32(void)
  58. {
  59. /* Initialise Windows Socket API */
  60. WSADATA wsaData;
  61. if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
  62. fprintf(stderr, "WSAStartup() returned error code %d\n",
  63. (unsigned int)GetLastError());
  64. errno = EIO;
  65. return -1;
  66. }
  67. return 0;
  68. }
  69. #endif
  70. static int _modbus_set_slave(modbus_t *ctx, int slave)
  71. {
  72. /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
  73. if (slave >= 0 && slave <= 247) {
  74. ctx->slave = slave;
  75. } else if (slave == MODBUS_TCP_SLAVE) {
  76. /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to
  77. * restore the default value. */
  78. ctx->slave = slave;
  79. } else {
  80. errno = EINVAL;
  81. return -1;
  82. }
  83. return 0;
  84. }
  85. /* Builds a TCP request header */
  86. int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,
  87. int addr, int nb,
  88. uint8_t *req)
  89. {
  90. /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
  91. (page 23/46):
  92. The transaction identifier is used to associate the future response
  93. with the request. So, at a time, on a TCP connection, this identifier
  94. must be unique. */
  95. static uint16_t t_id = 0;
  96. /* Transaction ID */
  97. if (t_id < UINT16_MAX)
  98. t_id++;
  99. else
  100. t_id = 0;
  101. req[0] = t_id >> 8;
  102. req[1] = t_id & 0x00ff;
  103. /* Protocol Modbus */
  104. req[2] = 0;
  105. req[3] = 0;
  106. /* Length will be defined later by set_req_length_tcp at offsets 4
  107. and 5 */
  108. req[6] = ctx->slave;
  109. req[7] = function;
  110. req[8] = addr >> 8;
  111. req[9] = addr & 0x00ff;
  112. req[10] = nb >> 8;
  113. req[11] = nb & 0x00ff;
  114. return _MODBUS_TCP_PRESET_REQ_LENGTH;
  115. }
  116. /* Builds a TCP response header */
  117. int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
  118. {
  119. /* Extract from MODBUS Messaging on TCP/IP Implementation
  120. Guide V1.0b (page 23/46):
  121. The transaction identifier is used to associate the future
  122. response with the request. */
  123. rsp[0] = sft->t_id >> 8;
  124. rsp[1] = sft->t_id & 0x00ff;
  125. /* Protocol Modbus */
  126. rsp[2] = 0;
  127. rsp[3] = 0;
  128. /* Length will be set later by send_msg (4 and 5) */
  129. /* The slave ID is copied from the indication */
  130. rsp[6] = sft->slave;
  131. rsp[7] = sft->function;
  132. return _MODBUS_TCP_PRESET_RSP_LENGTH;
  133. }
  134. int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
  135. {
  136. return (req[0] << 8) + req[1];
  137. }
  138. int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
  139. {
  140. /* Substract the header length to the message length */
  141. int mbap_length = req_length - 6;
  142. req[4] = mbap_length >> 8;
  143. req[5] = mbap_length & 0x00FF;
  144. return req_length;
  145. }
  146. ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length)
  147. {
  148. /* MSG_NOSIGNAL
  149. Requests not to send SIGPIPE on errors on stream oriented
  150. sockets when the other end breaks the connection. The EPIPE
  151. error is still returned. */
  152. return send(ctx->s, (const char*)req, req_length, MSG_NOSIGNAL);
  153. }
  154. ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) {
  155. return recv(ctx->s, (char *)rsp, rsp_length, 0);
  156. }
  157. int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
  158. {
  159. return msg_length;
  160. }
  161. static int _modbus_tcp_set_ipv4_options(int s)
  162. {
  163. int rc;
  164. int option;
  165. /* Set the TCP no delay flag */
  166. /* SOL_TCP = IPPROTO_TCP */
  167. option = 1;
  168. rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
  169. (const void *)&option, sizeof(int));
  170. if (rc == -1) {
  171. return -1;
  172. }
  173. #ifndef OS_WIN32
  174. /**
  175. * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's
  176. * necessary to workaround that problem.
  177. **/
  178. /* Set the IP low delay option */
  179. option = IPTOS_LOWDELAY;
  180. rc = setsockopt(s, IPPROTO_IP, IP_TOS,
  181. (const void *)&option, sizeof(int));
  182. if (rc == -1) {
  183. return -1;
  184. }
  185. #endif
  186. return 0;
  187. }
  188. /* Establishes a modbus TCP connection with a Modbus server. */
  189. static int _modbus_tcp_connect(modbus_t *ctx)
  190. {
  191. int rc;
  192. struct sockaddr_in addr;
  193. modbus_tcp_t *ctx_tcp = ctx->backend_data;
  194. #ifdef OS_WIN32
  195. if (_modbus_tcp_init_win32() == -1) {
  196. return -1;
  197. }
  198. #endif
  199. ctx->s = socket(PF_INET, SOCK_STREAM, 0);
  200. if (ctx->s == -1) {
  201. return -1;
  202. }
  203. rc = _modbus_tcp_set_ipv4_options(ctx->s);
  204. if (rc == -1) {
  205. close(ctx->s);
  206. return -1;
  207. }
  208. if (ctx->debug) {
  209. printf("Connecting to %s\n", ctx_tcp->ip);
  210. }
  211. addr.sin_family = AF_INET;
  212. addr.sin_port = htons(ctx_tcp->port);
  213. addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
  214. rc = connect(ctx->s, (struct sockaddr *)&addr,
  215. sizeof(struct sockaddr_in));
  216. if (rc == -1) {
  217. close(ctx->s);
  218. return -1;
  219. }
  220. return 0;
  221. }
  222. /* Establishes a modbus TCP PI connection with a Modbus server. */
  223. static int _modbus_tcp_pi_connect(modbus_t *ctx)
  224. {
  225. int rc;
  226. struct addrinfo *ai_list;
  227. struct addrinfo *ai_ptr;
  228. struct addrinfo ai_hints;
  229. modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;
  230. memset(&ai_hints, 0, sizeof(ai_hints));
  231. #ifdef AI_ADDRCONFIG
  232. ai_hints.ai_flags |= AI_ADDRCONFIG;
  233. #endif
  234. ai_hints.ai_family = AF_UNSPEC;
  235. ai_hints.ai_socktype = SOCK_STREAM;
  236. ai_hints.ai_addr = NULL;
  237. ai_hints.ai_canonname = NULL;
  238. ai_hints.ai_next = NULL;
  239. ai_list = NULL;
  240. rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,
  241. &ai_hints, &ai_list);
  242. if (rc != 0)
  243. return rc;
  244. for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
  245. int s;
  246. s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
  247. if (s < 0)
  248. continue;
  249. if (ai_ptr->ai_family == AF_INET)
  250. _modbus_tcp_set_ipv4_options(s);
  251. rc = connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
  252. if (rc != 0) {
  253. close(s);
  254. continue;
  255. }
  256. ctx->s = s;
  257. break;
  258. }
  259. freeaddrinfo(ai_list);
  260. if (ctx->s < 0) {
  261. return -1;
  262. }
  263. return 0;
  264. }
  265. /* Closes the network connection and socket in TCP mode */
  266. void _modbus_tcp_close(modbus_t *ctx)
  267. {
  268. shutdown(ctx->s, SHUT_RDWR);
  269. close(ctx->s);
  270. }
  271. int _modbus_tcp_flush(modbus_t *ctx)
  272. {
  273. int rc;
  274. do {
  275. /* Extract the garbage from the socket */
  276. char devnull[MODBUS_TCP_MAX_ADU_LENGTH];
  277. #ifndef OS_WIN32
  278. rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
  279. #else
  280. /* On Win32, it's a bit more complicated to not wait */
  281. fd_set rfds;
  282. struct timeval tv;
  283. tv.tv_sec = 0;
  284. tv.tv_usec = 0;
  285. FD_ZERO(&rfds);
  286. FD_SET(ctx->s, &rfds);
  287. rc = select(ctx->s+1, &rfds, NULL, NULL, &tv);
  288. if (rc == -1) {
  289. return -1;
  290. }
  291. if (rc == 1) {
  292. /* There is data to flush */
  293. rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, 0);
  294. }
  295. #endif
  296. if (ctx->debug && rc != -1) {
  297. printf("\n%d bytes flushed\n", rc);
  298. }
  299. } while (rc == MODBUS_TCP_MAX_ADU_LENGTH);
  300. return rc;
  301. }
  302. /* Listens for any request from one or many modbus masters in TCP */
  303. int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
  304. {
  305. int new_socket;
  306. int yes;
  307. struct sockaddr_in addr;
  308. modbus_tcp_t *ctx_tcp = ctx->backend_data;
  309. #ifdef OS_WIN32
  310. if (_modbus_tcp_init_win32() == -1) {
  311. return -1;
  312. }
  313. #endif
  314. new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  315. if (new_socket == -1) {
  316. return -1;
  317. }
  318. yes = 1;
  319. if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
  320. (char *) &yes, sizeof(yes)) == -1) {
  321. close(new_socket);
  322. return -1;
  323. }
  324. memset(&addr, 0, sizeof(addr));
  325. addr.sin_family = AF_INET;
  326. /* If the modbus port is < to 1024, we need the setuid root. */
  327. addr.sin_port = htons(ctx_tcp->port);
  328. addr.sin_addr.s_addr = INADDR_ANY;
  329. if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  330. close(new_socket);
  331. return -1;
  332. }
  333. if (listen(new_socket, nb_connection) == -1) {
  334. close(new_socket);
  335. return -1;
  336. }
  337. return new_socket;
  338. }
  339. int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
  340. {
  341. int rc;
  342. struct addrinfo *ai_list;
  343. struct addrinfo *ai_ptr;
  344. struct addrinfo ai_hints;
  345. const char *node;
  346. const char *service;
  347. int new_socket;
  348. modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;
  349. if (ctx_tcp_pi->node[0] == 0)
  350. node = NULL; /* == any */
  351. else
  352. node = ctx_tcp_pi->node;
  353. if (ctx_tcp_pi->service[0] == 0)
  354. service = "502";
  355. else
  356. service = ctx_tcp_pi->service;
  357. memset(&ai_hints, 0, sizeof (ai_hints));
  358. ai_hints.ai_flags |= AI_PASSIVE;
  359. #ifdef AI_ADDRCONFIG
  360. ai_hints.ai_flags |= AI_ADDRCONFIG;
  361. #endif
  362. ai_hints.ai_family = AF_UNSPEC;
  363. ai_hints.ai_socktype = SOCK_STREAM;
  364. ai_hints.ai_addr = NULL;
  365. ai_hints.ai_canonname = NULL;
  366. ai_hints.ai_next = NULL;
  367. ai_list = NULL;
  368. rc = getaddrinfo(node, service, &ai_hints, &ai_list);
  369. if (rc != 0)
  370. return -1;
  371. new_socket = -1;
  372. for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
  373. int s;
  374. s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
  375. ai_ptr->ai_protocol);
  376. if (s < 0) {
  377. if (ctx->debug) {
  378. perror("socket");
  379. }
  380. continue;
  381. } else {
  382. int yes = 1;
  383. rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  384. (void *) &yes, sizeof (yes));
  385. if (rc != 0) {
  386. close(s);
  387. if (ctx->debug) {
  388. perror("setsockopt");
  389. }
  390. continue;
  391. }
  392. }
  393. rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
  394. if (rc != 0) {
  395. close(s);
  396. if (ctx->debug) {
  397. perror("bind");
  398. }
  399. continue;
  400. }
  401. rc = listen(s, nb_connection);
  402. if (rc != 0) {
  403. close(s);
  404. if (ctx->debug) {
  405. perror("listen");
  406. }
  407. continue;
  408. }
  409. new_socket = s;
  410. break;
  411. }
  412. freeaddrinfo(ai_list);
  413. if (new_socket < 0) {
  414. return -1;
  415. }
  416. return new_socket;
  417. }
  418. /* On success, the function return a non-negative integer that is a descriptor
  419. for the accepted socket. On error, -1 is returned, and errno is set
  420. appropriately. */
  421. int modbus_tcp_accept(modbus_t *ctx, int *socket)
  422. {
  423. struct sockaddr_in addr;
  424. socklen_t addrlen;
  425. addrlen = sizeof(addr);
  426. ctx->s = accept(*socket, (struct sockaddr *)&addr, &addrlen);
  427. if (ctx->s == -1) {
  428. close(*socket);
  429. *socket = 0;
  430. return -1;
  431. }
  432. if (ctx->debug) {
  433. printf("The client connection from %s is accepted\n",
  434. inet_ntoa(addr.sin_addr));
  435. }
  436. return ctx->s;
  437. }
  438. int modbus_tcp_pi_accept(modbus_t *ctx, int *socket)
  439. {
  440. struct sockaddr_storage addr;
  441. socklen_t addrlen;
  442. addrlen = sizeof(addr);
  443. ctx->s = accept(*socket, (void *)&addr, &addrlen);
  444. if (ctx->s == -1) {
  445. close(*socket);
  446. *socket = 0;
  447. }
  448. if (ctx->debug) {
  449. printf("The client connection is accepted.");
  450. }
  451. return ctx->s;
  452. }
  453. int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int length_to_read)
  454. {
  455. int s_rc;
  456. while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) {
  457. if (errno == EINTR) {
  458. if (ctx->debug) {
  459. fprintf(stderr, "A non blocked signal was caught\n");
  460. }
  461. /* Necessary after an error */
  462. FD_ZERO(rfds);
  463. FD_SET(ctx->s, rfds);
  464. } else {
  465. _error_print(ctx, "select");
  466. if (ctx->error_recovery && (errno == EBADF)) {
  467. modbus_close(ctx);
  468. modbus_connect(ctx);
  469. errno = EBADF;
  470. return -1;
  471. } else {
  472. return -1;
  473. }
  474. }
  475. }
  476. if (s_rc == 0) {
  477. errno = ETIMEDOUT;
  478. _error_print(ctx, "select");
  479. return -1;
  480. }
  481. return s_rc;
  482. }
  483. int _modbus_tcp_filter_request(modbus_t *ctx, int slave)
  484. {
  485. return 0;
  486. }
  487. const modbus_backend_t _modbus_tcp_backend = {
  488. _MODBUS_BACKEND_TYPE_TCP,
  489. _MODBUS_TCP_HEADER_LENGTH,
  490. _MODBUS_TCP_CHECKSUM_LENGTH,
  491. MODBUS_TCP_MAX_ADU_LENGTH,
  492. _modbus_set_slave,
  493. _modbus_tcp_build_request_basis,
  494. _modbus_tcp_build_response_basis,
  495. _modbus_tcp_prepare_response_tid,
  496. _modbus_tcp_send_msg_pre,
  497. _modbus_tcp_send,
  498. _modbus_tcp_recv,
  499. _modbus_tcp_check_integrity,
  500. _modbus_tcp_connect,
  501. _modbus_tcp_close,
  502. _modbus_tcp_flush,
  503. _modbus_tcp_select,
  504. _modbus_tcp_filter_request
  505. };
  506. const modbus_backend_t _modbus_tcp_pi_backend = {
  507. _MODBUS_BACKEND_TYPE_TCP,
  508. _MODBUS_TCP_HEADER_LENGTH,
  509. _MODBUS_TCP_CHECKSUM_LENGTH,
  510. MODBUS_TCP_MAX_ADU_LENGTH,
  511. _modbus_set_slave,
  512. _modbus_tcp_build_request_basis,
  513. _modbus_tcp_build_response_basis,
  514. _modbus_tcp_prepare_response_tid,
  515. _modbus_tcp_send_msg_pre,
  516. _modbus_tcp_send,
  517. _modbus_tcp_recv,
  518. _modbus_tcp_check_integrity,
  519. _modbus_tcp_pi_connect,
  520. _modbus_tcp_close,
  521. _modbus_tcp_flush,
  522. _modbus_tcp_select,
  523. _modbus_tcp_filter_request
  524. };
  525. modbus_t* modbus_new_tcp(const char *ip, int port)
  526. {
  527. modbus_t *ctx;
  528. modbus_tcp_t *ctx_tcp;
  529. size_t dest_size;
  530. size_t ret_size;
  531. #if defined(OS_BSD)
  532. /* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore
  533. handler for SIGPIPE. */
  534. struct sigaction sa;
  535. sa.sa_handler = SIG_IGN;
  536. if (sigaction(SIGPIPE, &sa, NULL) < 0) {
  537. /* The debug flag can't be set here... */
  538. fprintf(stderr, "Coud not install SIGPIPE handler.\n");
  539. return NULL;
  540. }
  541. #endif
  542. ctx = (modbus_t *) malloc(sizeof(modbus_t));
  543. _modbus_init_common(ctx);
  544. /* Could be changed after to reach a remote serial Modbus device */
  545. ctx->slave = MODBUS_TCP_SLAVE;
  546. ctx->backend = &(_modbus_tcp_backend);
  547. ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
  548. ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
  549. dest_size = sizeof(char) * 16;
  550. ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
  551. if (ret_size == 0) {
  552. fprintf(stderr, "The IP string is empty\n");
  553. modbus_free(ctx);
  554. errno = EINVAL;
  555. return NULL;
  556. }
  557. if (ret_size >= dest_size) {
  558. fprintf(stderr, "The IP string has been truncated\n");
  559. modbus_free(ctx);
  560. errno = EINVAL;
  561. return NULL;
  562. }
  563. ctx_tcp->port = port;
  564. return ctx;
  565. }
  566. modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
  567. {
  568. modbus_t *ctx;
  569. modbus_tcp_pi_t *ctx_tcp_pi;
  570. size_t dest_size;
  571. size_t ret_size;
  572. ctx = (modbus_t *) malloc(sizeof(modbus_t));
  573. _modbus_init_common(ctx);
  574. /* Could be changed after to reach a remote serial Modbus device */
  575. ctx->slave = MODBUS_TCP_SLAVE;
  576. ctx->backend = &(_modbus_tcp_pi_backend);
  577. ctx->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t));
  578. ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
  579. dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
  580. ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
  581. if (ret_size == 0) {
  582. fprintf(stderr, "The node string is empty\n");
  583. modbus_free(ctx);
  584. errno = EINVAL;
  585. return NULL;
  586. }
  587. if (ret_size >= dest_size) {
  588. fprintf(stderr, "The node string has been truncated\n");
  589. modbus_free(ctx);
  590. errno = EINVAL;
  591. return NULL;
  592. }
  593. dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
  594. ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
  595. if (ret_size == 0) {
  596. fprintf(stderr, "The service string is empty\n");
  597. modbus_free(ctx);
  598. errno = EINVAL;
  599. return NULL;
  600. }
  601. if (ret_size >= dest_size) {
  602. fprintf(stderr, "The service string has been truncated\n");
  603. modbus_free(ctx);
  604. errno = EINVAL;
  605. return NULL;
  606. }
  607. return ctx;
  608. }