modbus-tcp.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. /*
  2. * Copyright © 2001-2013 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * SPDX-License-Identifier: LGPL-2.1+
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #ifndef _MSC_VER
  11. #include <unistd.h>
  12. #endif
  13. #include <signal.h>
  14. #include <sys/types.h>
  15. #if defined(_WIN32)
  16. # define OS_WIN32
  17. /* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
  18. * minwg32 headers check WINVER before allowing the use of these */
  19. # ifndef WINVER
  20. # define WINVER 0x0501
  21. # endif
  22. /* Already set in modbus-tcp.h but it seems order matters in VS2005 */
  23. # include <winsock2.h>
  24. # include <ws2tcpip.h>
  25. # define SHUT_RDWR 2
  26. # define close closesocket
  27. #else
  28. # include <sys/socket.h>
  29. # include <sys/ioctl.h>
  30. #if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5)
  31. # define OS_BSD
  32. # include <netinet/in_systm.h>
  33. #endif
  34. # include <netinet/in.h>
  35. # include <netinet/ip.h>
  36. # include <netinet/tcp.h>
  37. # include <arpa/inet.h>
  38. # include <netdb.h>
  39. #endif
  40. #if !defined(MSG_NOSIGNAL)
  41. #define MSG_NOSIGNAL 0
  42. #endif
  43. #if defined(_AIX) && !defined(MSG_DONTWAIT)
  44. #define MSG_DONTWAIT MSG_NONBLOCK
  45. #endif
  46. #include "modbus-private.h"
  47. #include "modbus-tcp.h"
  48. #include "modbus-tcp-private.h"
  49. #ifdef OS_WIN32
  50. static int _modbus_tcp_init_win32(void)
  51. {
  52. /* Initialise Windows Socket API */
  53. WSADATA wsaData;
  54. if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
  55. fprintf(stderr, "WSAStartup() returned error code %d\n",
  56. (unsigned int)GetLastError());
  57. errno = EIO;
  58. return -1;
  59. }
  60. return 0;
  61. }
  62. #endif
  63. static int _modbus_set_slave(modbus_t *ctx, int slave)
  64. {
  65. /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
  66. if (slave >= 0 && slave <= 247) {
  67. ctx->slave = slave;
  68. } else if (slave == MODBUS_TCP_SLAVE) {
  69. /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to
  70. * restore the default value. */
  71. ctx->slave = slave;
  72. } else {
  73. errno = EINVAL;
  74. return -1;
  75. }
  76. return 0;
  77. }
  78. /* Builds a TCP request header */
  79. static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,
  80. int addr, int nb,
  81. uint8_t *req)
  82. {
  83. modbus_tcp_t *ctx_tcp = ctx->backend_data;
  84. /* Increase transaction ID */
  85. if (ctx_tcp->t_id < UINT16_MAX)
  86. ctx_tcp->t_id++;
  87. else
  88. ctx_tcp->t_id = 0;
  89. req[0] = ctx_tcp->t_id >> 8;
  90. req[1] = ctx_tcp->t_id & 0x00ff;
  91. /* Protocol Modbus */
  92. req[2] = 0;
  93. req[3] = 0;
  94. /* Length will be defined later by set_req_length_tcp at offsets 4
  95. and 5 */
  96. req[6] = ctx->slave;
  97. req[7] = function;
  98. req[8] = addr >> 8;
  99. req[9] = addr & 0x00ff;
  100. req[10] = nb >> 8;
  101. req[11] = nb & 0x00ff;
  102. return _MODBUS_TCP_PRESET_REQ_LENGTH;
  103. }
  104. /* Builds a TCP response header */
  105. static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
  106. {
  107. /* Extract from MODBUS Messaging on TCP/IP Implementation
  108. Guide V1.0b (page 23/46):
  109. The transaction identifier is used to associate the future
  110. response with the request. */
  111. rsp[0] = sft->t_id >> 8;
  112. rsp[1] = sft->t_id & 0x00ff;
  113. /* Protocol Modbus */
  114. rsp[2] = 0;
  115. rsp[3] = 0;
  116. /* Length will be set later by send_msg (4 and 5) */
  117. /* The slave ID is copied from the indication */
  118. rsp[6] = sft->slave;
  119. rsp[7] = sft->function;
  120. return _MODBUS_TCP_PRESET_RSP_LENGTH;
  121. }
  122. static int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
  123. {
  124. return (req[0] << 8) + req[1];
  125. }
  126. static int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
  127. {
  128. /* Substract the header length to the message length */
  129. int mbap_length = req_length - 6;
  130. req[4] = mbap_length >> 8;
  131. req[5] = mbap_length & 0x00FF;
  132. return req_length;
  133. }
  134. static ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length)
  135. {
  136. /* MSG_NOSIGNAL
  137. Requests not to send SIGPIPE on errors on stream oriented
  138. sockets when the other end breaks the connection. The EPIPE
  139. error is still returned. */
  140. return send(ctx->s, (const char *)req, req_length, MSG_NOSIGNAL);
  141. }
  142. static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req) {
  143. return _modbus_receive_msg(ctx, req, MSG_INDICATION);
  144. }
  145. static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) {
  146. return recv(ctx->s, (char *)rsp, rsp_length, 0);
  147. }
  148. static int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
  149. {
  150. return msg_length;
  151. }
  152. static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
  153. const uint8_t *rsp, int rsp_length)
  154. {
  155. /* Check transaction ID */
  156. if (req[0] != rsp[0] || req[1] != rsp[1]) {
  157. if (ctx->debug) {
  158. fprintf(stderr, "Invalid transaction ID received 0x%X (not 0x%X)\n",
  159. (rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]);
  160. }
  161. errno = EMBBADDATA;
  162. return -1;
  163. }
  164. /* Check protocol ID */
  165. if (rsp[2] != 0x0 && rsp[3] != 0x0) {
  166. if (ctx->debug) {
  167. fprintf(stderr, "Invalid protocol ID received 0x%X (not 0x0)\n",
  168. (rsp[2] << 8) + rsp[3]);
  169. }
  170. errno = EMBBADDATA;
  171. return -1;
  172. }
  173. return 0;
  174. }
  175. static int _modbus_tcp_set_ipv4_options(int s)
  176. {
  177. int rc;
  178. int option;
  179. /* Set the TCP no delay flag */
  180. /* SOL_TCP = IPPROTO_TCP */
  181. option = 1;
  182. rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
  183. (const void *)&option, sizeof(int));
  184. if (rc == -1) {
  185. return -1;
  186. }
  187. /* If the OS does not offer SOCK_NONBLOCK, fall back to setting FIONBIO to
  188. * make sockets non-blocking */
  189. /* Do not care about the return value, this is optional */
  190. #if !defined(SOCK_NONBLOCK) && defined(FIONBIO)
  191. #ifdef OS_WIN32
  192. {
  193. /* Setting FIONBIO expects an unsigned long according to MSDN */
  194. u_long loption = 1;
  195. ioctlsocket(s, FIONBIO, &loption);
  196. }
  197. #else
  198. option = 1;
  199. ioctl(s, FIONBIO, &option);
  200. #endif
  201. #endif
  202. #ifndef OS_WIN32
  203. /**
  204. * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's
  205. * necessary to workaround that problem.
  206. **/
  207. /* Set the IP low delay option */
  208. option = IPTOS_LOWDELAY;
  209. rc = setsockopt(s, IPPROTO_IP, IP_TOS,
  210. (const void *)&option, sizeof(int));
  211. if (rc == -1) {
  212. return -1;
  213. }
  214. #endif
  215. return 0;
  216. }
  217. static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,
  218. const struct timeval *ro_tv)
  219. {
  220. int rc = connect(sockfd, addr, addrlen);
  221. #ifdef OS_WIN32
  222. int wsaError = 0;
  223. if (rc == -1) {
  224. wsaError = WSAGetLastError();
  225. }
  226. if (wsaError == WSAEWOULDBLOCK || wsaError == WSAEINPROGRESS) {
  227. #else
  228. if (rc == -1 && errno == EINPROGRESS) {
  229. #endif
  230. fd_set wset;
  231. int optval;
  232. socklen_t optlen = sizeof(optval);
  233. struct timeval tv = *ro_tv;
  234. /* Wait to be available in writing */
  235. FD_ZERO(&wset);
  236. FD_SET(sockfd, &wset);
  237. rc = select(sockfd + 1, NULL, &wset, NULL, &tv);
  238. if (rc <= 0) {
  239. /* Timeout or fail */
  240. return -1;
  241. }
  242. /* The connection is established if SO_ERROR and optval are set to 0 */
  243. rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen);
  244. if (rc == 0 && optval == 0) {
  245. return 0;
  246. } else {
  247. errno = ECONNREFUSED;
  248. return -1;
  249. }
  250. }
  251. return rc;
  252. }
  253. /* Establishes a modbus TCP connection with a Modbus server. */
  254. static int _modbus_tcp_connect(modbus_t *ctx)
  255. {
  256. int rc;
  257. /* Specialized version of sockaddr for Internet socket address (same size) */
  258. struct sockaddr_in addr;
  259. modbus_tcp_t *ctx_tcp = ctx->backend_data;
  260. int flags = SOCK_STREAM;
  261. #ifdef OS_WIN32
  262. if (_modbus_tcp_init_win32() == -1) {
  263. return -1;
  264. }
  265. #endif
  266. #ifdef SOCK_CLOEXEC
  267. flags |= SOCK_CLOEXEC;
  268. #endif
  269. #ifdef SOCK_NONBLOCK
  270. flags |= SOCK_NONBLOCK;
  271. #endif
  272. ctx->s = socket(PF_INET, flags, 0);
  273. if (ctx->s == -1) {
  274. return -1;
  275. }
  276. rc = _modbus_tcp_set_ipv4_options(ctx->s);
  277. if (rc == -1) {
  278. close(ctx->s);
  279. ctx->s = -1;
  280. return -1;
  281. }
  282. if (ctx->debug) {
  283. printf("Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port);
  284. }
  285. addr.sin_family = AF_INET;
  286. addr.sin_port = htons(ctx_tcp->port);
  287. addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
  288. rc = _connect(ctx->s, (struct sockaddr *)&addr, sizeof(addr), &ctx->response_timeout);
  289. if (rc == -1) {
  290. close(ctx->s);
  291. ctx->s = -1;
  292. return -1;
  293. }
  294. return 0;
  295. }
  296. /* Establishes a modbus TCP PI connection with a Modbus server. */
  297. static int _modbus_tcp_pi_connect(modbus_t *ctx)
  298. {
  299. int rc;
  300. struct addrinfo *ai_list;
  301. struct addrinfo *ai_ptr;
  302. struct addrinfo ai_hints;
  303. modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;
  304. #ifdef OS_WIN32
  305. if (_modbus_tcp_init_win32() == -1) {
  306. return -1;
  307. }
  308. #endif
  309. memset(&ai_hints, 0, sizeof(ai_hints));
  310. #ifdef AI_ADDRCONFIG
  311. ai_hints.ai_flags |= AI_ADDRCONFIG;
  312. #endif
  313. ai_hints.ai_family = AF_UNSPEC;
  314. ai_hints.ai_socktype = SOCK_STREAM;
  315. ai_hints.ai_addr = NULL;
  316. ai_hints.ai_canonname = NULL;
  317. ai_hints.ai_next = NULL;
  318. ai_list = NULL;
  319. rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,
  320. &ai_hints, &ai_list);
  321. if (rc != 0) {
  322. if (ctx->debug) {
  323. fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));
  324. }
  325. errno = ECONNREFUSED;
  326. return -1;
  327. }
  328. for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
  329. int flags = ai_ptr->ai_socktype;
  330. int s;
  331. #ifdef SOCK_CLOEXEC
  332. flags |= SOCK_CLOEXEC;
  333. #endif
  334. #ifdef SOCK_NONBLOCK
  335. flags |= SOCK_NONBLOCK;
  336. #endif
  337. s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);
  338. if (s < 0)
  339. continue;
  340. if (ai_ptr->ai_family == AF_INET)
  341. _modbus_tcp_set_ipv4_options(s);
  342. if (ctx->debug) {
  343. printf("Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service);
  344. }
  345. rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout);
  346. if (rc == -1) {
  347. close(s);
  348. continue;
  349. }
  350. ctx->s = s;
  351. break;
  352. }
  353. freeaddrinfo(ai_list);
  354. if (ctx->s < 0) {
  355. return -1;
  356. }
  357. return 0;
  358. }
  359. /* Closes the network connection and socket in TCP mode */
  360. static void _modbus_tcp_close(modbus_t *ctx)
  361. {
  362. if (ctx->s != -1) {
  363. shutdown(ctx->s, SHUT_RDWR);
  364. close(ctx->s);
  365. ctx->s = -1;
  366. }
  367. }
  368. static int _modbus_tcp_flush(modbus_t *ctx)
  369. {
  370. int rc;
  371. int rc_sum = 0;
  372. do {
  373. /* Extract the garbage from the socket */
  374. char devnull[MODBUS_TCP_MAX_ADU_LENGTH];
  375. #ifndef OS_WIN32
  376. rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
  377. #else
  378. /* On Win32, it's a bit more complicated to not wait */
  379. fd_set rset;
  380. struct timeval tv;
  381. tv.tv_sec = 0;
  382. tv.tv_usec = 0;
  383. FD_ZERO(&rset);
  384. FD_SET(ctx->s, &rset);
  385. rc = select(ctx->s+1, &rset, NULL, NULL, &tv);
  386. if (rc == -1) {
  387. return -1;
  388. }
  389. if (rc == 1) {
  390. /* There is data to flush */
  391. rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, 0);
  392. }
  393. #endif
  394. if (rc > 0) {
  395. rc_sum += rc;
  396. }
  397. } while (rc == MODBUS_TCP_MAX_ADU_LENGTH);
  398. return rc_sum;
  399. }
  400. /* Listens for any request from one or many modbus masters in TCP */
  401. int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
  402. {
  403. int new_s;
  404. int enable;
  405. struct sockaddr_in addr;
  406. modbus_tcp_t *ctx_tcp;
  407. if (ctx == NULL) {
  408. errno = EINVAL;
  409. return -1;
  410. }
  411. ctx_tcp = ctx->backend_data;
  412. #ifdef OS_WIN32
  413. if (_modbus_tcp_init_win32() == -1) {
  414. return -1;
  415. }
  416. #endif
  417. new_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  418. if (new_s == -1) {
  419. return -1;
  420. }
  421. enable = 1;
  422. if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR,
  423. (char *)&enable, sizeof(enable)) == -1) {
  424. close(new_s);
  425. return -1;
  426. }
  427. memset(&addr, 0, sizeof(addr));
  428. addr.sin_family = AF_INET;
  429. /* If the modbus port is < to 1024, we need the setuid root. */
  430. addr.sin_port = htons(ctx_tcp->port);
  431. if (ctx_tcp->ip[0] == '0') {
  432. /* Listen any addresses */
  433. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  434. } else {
  435. /* Listen only specified IP address */
  436. addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
  437. }
  438. if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  439. close(new_s);
  440. return -1;
  441. }
  442. if (listen(new_s, nb_connection) == -1) {
  443. close(new_s);
  444. return -1;
  445. }
  446. return new_s;
  447. }
  448. int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
  449. {
  450. int rc;
  451. struct addrinfo *ai_list;
  452. struct addrinfo *ai_ptr;
  453. struct addrinfo ai_hints;
  454. const char *node;
  455. const char *service;
  456. int new_s;
  457. modbus_tcp_pi_t *ctx_tcp_pi;
  458. if (ctx == NULL) {
  459. errno = EINVAL;
  460. return -1;
  461. }
  462. ctx_tcp_pi = ctx->backend_data;
  463. #ifdef OS_WIN32
  464. if (_modbus_tcp_init_win32() == -1) {
  465. return -1;
  466. }
  467. #endif
  468. if (ctx_tcp_pi->node[0] == 0) {
  469. node = NULL; /* == any */
  470. } else {
  471. node = ctx_tcp_pi->node;
  472. }
  473. if (ctx_tcp_pi->service[0] == 0) {
  474. service = "502";
  475. } else {
  476. service = ctx_tcp_pi->service;
  477. }
  478. memset(&ai_hints, 0, sizeof (ai_hints));
  479. /* If node is not NULL, than the AI_PASSIVE flag is ignored. */
  480. ai_hints.ai_flags |= AI_PASSIVE;
  481. #ifdef AI_ADDRCONFIG
  482. ai_hints.ai_flags |= AI_ADDRCONFIG;
  483. #endif
  484. ai_hints.ai_family = AF_UNSPEC;
  485. ai_hints.ai_socktype = SOCK_STREAM;
  486. ai_hints.ai_addr = NULL;
  487. ai_hints.ai_canonname = NULL;
  488. ai_hints.ai_next = NULL;
  489. ai_list = NULL;
  490. rc = getaddrinfo(node, service, &ai_hints, &ai_list);
  491. if (rc != 0) {
  492. if (ctx->debug) {
  493. fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));
  494. }
  495. errno = ECONNREFUSED;
  496. return -1;
  497. }
  498. new_s = -1;
  499. for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
  500. int s;
  501. s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
  502. ai_ptr->ai_protocol);
  503. if (s < 0) {
  504. if (ctx->debug) {
  505. perror("socket");
  506. }
  507. continue;
  508. } else {
  509. int enable = 1;
  510. rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  511. (void *)&enable, sizeof (enable));
  512. if (rc != 0) {
  513. close(s);
  514. if (ctx->debug) {
  515. perror("setsockopt");
  516. }
  517. continue;
  518. }
  519. }
  520. rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
  521. if (rc != 0) {
  522. close(s);
  523. if (ctx->debug) {
  524. perror("bind");
  525. }
  526. continue;
  527. }
  528. rc = listen(s, nb_connection);
  529. if (rc != 0) {
  530. close(s);
  531. if (ctx->debug) {
  532. perror("listen");
  533. }
  534. continue;
  535. }
  536. new_s = s;
  537. break;
  538. }
  539. freeaddrinfo(ai_list);
  540. if (new_s < 0) {
  541. return -1;
  542. }
  543. return new_s;
  544. }
  545. int modbus_tcp_accept(modbus_t *ctx, int *s)
  546. {
  547. struct sockaddr_in addr;
  548. socklen_t addrlen;
  549. if (ctx == NULL) {
  550. errno = EINVAL;
  551. return -1;
  552. }
  553. addrlen = sizeof(addr);
  554. #ifdef HAVE_ACCEPT4
  555. /* Inherit socket flags and use accept4 call */
  556. ctx->s = accept4(*s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
  557. #else
  558. ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);
  559. #endif
  560. if (ctx->s == -1) {
  561. close(*s);
  562. *s = -1;
  563. return -1;
  564. }
  565. if (ctx->debug) {
  566. printf("The client connection from %s is accepted\n",
  567. inet_ntoa(addr.sin_addr));
  568. }
  569. return ctx->s;
  570. }
  571. int modbus_tcp_pi_accept(modbus_t *ctx, int *s)
  572. {
  573. struct sockaddr_storage addr;
  574. socklen_t addrlen;
  575. if (ctx == NULL) {
  576. errno = EINVAL;
  577. return -1;
  578. }
  579. addrlen = sizeof(addr);
  580. #ifdef HAVE_ACCEPT4
  581. /* Inherit socket flags and use accept4 call */
  582. ctx->s = accept4(*s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
  583. #else
  584. ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);
  585. #endif
  586. if (ctx->s == -1) {
  587. close(*s);
  588. *s = -1;
  589. }
  590. if (ctx->debug) {
  591. printf("The client connection is accepted.\n");
  592. }
  593. return ctx->s;
  594. }
  595. static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)
  596. {
  597. int s_rc;
  598. while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {
  599. if (errno == EINTR) {
  600. if (ctx->debug) {
  601. fprintf(stderr, "A non blocked signal was caught\n");
  602. }
  603. /* Necessary after an error */
  604. FD_ZERO(rset);
  605. FD_SET(ctx->s, rset);
  606. } else {
  607. return -1;
  608. }
  609. }
  610. if (s_rc == 0) {
  611. errno = ETIMEDOUT;
  612. return -1;
  613. }
  614. return s_rc;
  615. }
  616. static void _modbus_tcp_free(modbus_t *ctx) {
  617. free(ctx->backend_data);
  618. free(ctx);
  619. }
  620. const modbus_backend_t _modbus_tcp_backend = {
  621. _MODBUS_BACKEND_TYPE_TCP,
  622. _MODBUS_TCP_HEADER_LENGTH,
  623. _MODBUS_TCP_CHECKSUM_LENGTH,
  624. MODBUS_TCP_MAX_ADU_LENGTH,
  625. _modbus_set_slave,
  626. _modbus_tcp_build_request_basis,
  627. _modbus_tcp_build_response_basis,
  628. _modbus_tcp_prepare_response_tid,
  629. _modbus_tcp_send_msg_pre,
  630. _modbus_tcp_send,
  631. _modbus_tcp_receive,
  632. _modbus_tcp_recv,
  633. _modbus_tcp_check_integrity,
  634. _modbus_tcp_pre_check_confirmation,
  635. _modbus_tcp_connect,
  636. _modbus_tcp_close,
  637. _modbus_tcp_flush,
  638. _modbus_tcp_select,
  639. _modbus_tcp_free
  640. };
  641. const modbus_backend_t _modbus_tcp_pi_backend = {
  642. _MODBUS_BACKEND_TYPE_TCP,
  643. _MODBUS_TCP_HEADER_LENGTH,
  644. _MODBUS_TCP_CHECKSUM_LENGTH,
  645. MODBUS_TCP_MAX_ADU_LENGTH,
  646. _modbus_set_slave,
  647. _modbus_tcp_build_request_basis,
  648. _modbus_tcp_build_response_basis,
  649. _modbus_tcp_prepare_response_tid,
  650. _modbus_tcp_send_msg_pre,
  651. _modbus_tcp_send,
  652. _modbus_tcp_receive,
  653. _modbus_tcp_recv,
  654. _modbus_tcp_check_integrity,
  655. _modbus_tcp_pre_check_confirmation,
  656. _modbus_tcp_pi_connect,
  657. _modbus_tcp_close,
  658. _modbus_tcp_flush,
  659. _modbus_tcp_select,
  660. _modbus_tcp_free
  661. };
  662. modbus_t* modbus_new_tcp(const char *ip, int port)
  663. {
  664. modbus_t *ctx;
  665. modbus_tcp_t *ctx_tcp;
  666. size_t dest_size;
  667. size_t ret_size;
  668. #if defined(OS_BSD)
  669. /* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore
  670. handler for SIGPIPE. */
  671. struct sigaction sa;
  672. sa.sa_handler = SIG_IGN;
  673. if (sigaction(SIGPIPE, &sa, NULL) < 0) {
  674. /* The debug flag can't be set here... */
  675. fprintf(stderr, "Coud not install SIGPIPE handler.\n");
  676. return NULL;
  677. }
  678. #endif
  679. ctx = (modbus_t *)malloc(sizeof(modbus_t));
  680. _modbus_init_common(ctx);
  681. /* Could be changed after to reach a remote serial Modbus device */
  682. ctx->slave = MODBUS_TCP_SLAVE;
  683. ctx->backend = &_modbus_tcp_backend;
  684. ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t));
  685. ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
  686. if (ip != NULL) {
  687. dest_size = sizeof(char) * 16;
  688. ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
  689. if (ret_size == 0) {
  690. fprintf(stderr, "The IP string is empty\n");
  691. modbus_free(ctx);
  692. errno = EINVAL;
  693. return NULL;
  694. }
  695. if (ret_size >= dest_size) {
  696. fprintf(stderr, "The IP string has been truncated\n");
  697. modbus_free(ctx);
  698. errno = EINVAL;
  699. return NULL;
  700. }
  701. } else {
  702. ctx_tcp->ip[0] = '0';
  703. }
  704. ctx_tcp->port = port;
  705. ctx_tcp->t_id = 0;
  706. return ctx;
  707. }
  708. modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
  709. {
  710. modbus_t *ctx;
  711. modbus_tcp_pi_t *ctx_tcp_pi;
  712. size_t dest_size;
  713. size_t ret_size;
  714. ctx = (modbus_t *)malloc(sizeof(modbus_t));
  715. _modbus_init_common(ctx);
  716. /* Could be changed after to reach a remote serial Modbus device */
  717. ctx->slave = MODBUS_TCP_SLAVE;
  718. ctx->backend = &_modbus_tcp_pi_backend;
  719. ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));
  720. ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
  721. if (node == NULL) {
  722. /* The node argument can be empty to indicate any hosts */
  723. ctx_tcp_pi->node[0] = 0;
  724. } else {
  725. dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
  726. ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
  727. if (ret_size == 0) {
  728. fprintf(stderr, "The node string is empty\n");
  729. modbus_free(ctx);
  730. errno = EINVAL;
  731. return NULL;
  732. }
  733. if (ret_size >= dest_size) {
  734. fprintf(stderr, "The node string has been truncated\n");
  735. modbus_free(ctx);
  736. errno = EINVAL;
  737. return NULL;
  738. }
  739. }
  740. if (service != NULL) {
  741. dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
  742. ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
  743. } else {
  744. /* Empty service is not allowed, error catched below. */
  745. ret_size = 0;
  746. }
  747. if (ret_size == 0) {
  748. fprintf(stderr, "The service string is empty\n");
  749. modbus_free(ctx);
  750. errno = EINVAL;
  751. return NULL;
  752. }
  753. if (ret_size >= dest_size) {
  754. fprintf(stderr, "The service string has been truncated\n");
  755. modbus_free(ctx);
  756. errno = EINVAL;
  757. return NULL;
  758. }
  759. ctx_tcp_pi->t_id = 0;
  760. return ctx;
  761. }