modbus-tcp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. #include <unistd.h>
  22. #include <sys/types.h>
  23. #if defined(_WIN32)
  24. # define OS_WIN32
  25. # include <winsock2.h>
  26. # include <ws2tcpip.h>
  27. # define SHUT_RDWR 2
  28. #else
  29. # include <sys/socket.h>
  30. # include <sys/ioctl.h>
  31. #if defined(OpenBSD) || (defined(__FreeBSD__) && __FreeBSD__ < 5)
  32. # define OS_BSD
  33. # include <netinet/in_systm.h>
  34. #endif
  35. # include <netinet/in.h>
  36. # include <netinet/ip.h>
  37. # include <netinet/tcp.h>
  38. # include <arpa/inet.h>
  39. #endif
  40. #if !defined(MSG_NOSIGNAL)
  41. #define MSG_NOSIGNAL 0
  42. #endif
  43. #include "modbus-private.h"
  44. #include "modbus-tcp.h"
  45. #include "modbus-tcp-private.h"
  46. #ifdef OS_WIN32
  47. static int _modbus_tcp_init_win32(void)
  48. {
  49. // Initialise Win32 Socket API
  50. WORD wVersionRequested;
  51. WSADATA wsaData;
  52. wVersionRequested = MAKEWORD(2, 0);
  53. if (WSAStartup(wVersionRequested, &wsaData) != 0)
  54. {
  55. fprintf (stderr, "WSAStartup() returned error code %d\n",
  56. 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. if (slave >= 1 && slave <= 247) {
  66. ctx->slave = slave;
  67. } else if (slave == MODBUS_TCP_SLAVE) {
  68. /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to
  69. * restore the default value. */
  70. ctx->slave = slave;
  71. } else {
  72. errno = EINVAL;
  73. return -1;
  74. }
  75. return 0;
  76. }
  77. /* Builds a TCP request header */
  78. int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,
  79. int addr, int nb,
  80. uint8_t *req)
  81. {
  82. /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
  83. (page 23/46):
  84. The transaction identifier is used to associate the future response
  85. with the request. So, at a time, on a TCP connection, this identifier
  86. must be unique. */
  87. static uint16_t t_id = 0;
  88. /* Transaction ID */
  89. if (t_id < UINT16_MAX)
  90. t_id++;
  91. else
  92. t_id = 0;
  93. req[0] = t_id >> 8;
  94. req[1] = t_id & 0x00ff;
  95. /* Protocol Modbus */
  96. req[2] = 0;
  97. req[3] = 0;
  98. /* Length will be defined later by set_req_length_tcp at offsets 4
  99. and 5 */
  100. req[6] = ctx->slave;
  101. req[7] = function;
  102. req[8] = addr >> 8;
  103. req[9] = addr & 0x00ff;
  104. req[10] = nb >> 8;
  105. req[11] = nb & 0x00ff;
  106. return _MODBUS_TCP_PRESET_REQ_LENGTH;
  107. }
  108. /* Builds a TCP response header */
  109. int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
  110. {
  111. /* Extract from MODBUS Messaging on TCP/IP Implementation
  112. Guide V1.0b (page 23/46):
  113. The transaction identifier is used to associate the future
  114. response with the request. */
  115. rsp[0] = sft->t_id >> 8;
  116. rsp[1] = sft->t_id & 0x00ff;
  117. /* Protocol Modbus */
  118. rsp[2] = 0;
  119. rsp[3] = 0;
  120. /* Length will be set later by send_msg (4 and 5) */
  121. rsp[6] = 0xFF;
  122. rsp[7] = sft->function;
  123. return _MODBUS_TCP_PRESET_RSP_LENGTH;
  124. }
  125. int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
  126. {
  127. return (req[0] << 8) + req[1];
  128. }
  129. int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
  130. {
  131. /* Substract the header length to the message length */
  132. int mbap_length = req_length - 6;
  133. req[4] = mbap_length >> 8;
  134. req[5] = mbap_length & 0x00FF;
  135. return req_length;
  136. }
  137. ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length)
  138. {
  139. /* MSG_NOSIGNAL
  140. Requests not to send SIGPIPE on errors on stream oriented
  141. sockets when the other end breaks the connection. The EPIPE
  142. error is still returned. */
  143. return send(ctx->s, (const char*)req, req_length, MSG_NOSIGNAL);
  144. }
  145. 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. int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
  149. {
  150. return msg_length;
  151. }
  152. /* Establishes a modbus TCP connection with a Modbus server. */
  153. static int _modbus_tcp_connect(modbus_t *ctx)
  154. {
  155. int rc;
  156. int option;
  157. struct sockaddr_in addr;
  158. modbus_tcp_t *ctx_tcp = ctx->backend_data;
  159. #ifdef OS_WIN32
  160. if (_modbus_tcp_init_win32() == -1) {
  161. return -1;
  162. }
  163. #endif
  164. ctx->s = socket(PF_INET, SOCK_STREAM, 0);
  165. if (ctx->s == -1) {
  166. return -1;
  167. }
  168. /* Set the TCP no delay flag */
  169. /* SOL_TCP = IPPROTO_TCP */
  170. option = 1;
  171. rc = setsockopt(ctx->s, IPPROTO_TCP, TCP_NODELAY,
  172. (const void *)&option, sizeof(int));
  173. if (rc == -1) {
  174. close(ctx->s);
  175. return -1;
  176. }
  177. #ifndef OS_WIN32
  178. /**
  179. * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's
  180. * necessary to workaround that problem.
  181. **/
  182. /* Set the IP low delay option */
  183. option = IPTOS_LOWDELAY;
  184. rc = setsockopt(ctx->s, IPPROTO_IP, IP_TOS,
  185. (const void *)&option, sizeof(int));
  186. if (rc == -1) {
  187. close(ctx->s);
  188. return -1;
  189. }
  190. #endif
  191. if (ctx->debug) {
  192. printf("Connecting to %s\n", ctx_tcp->ip);
  193. }
  194. addr.sin_family = AF_INET;
  195. addr.sin_port = htons(ctx_tcp->port);
  196. addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
  197. rc = connect(ctx->s, (struct sockaddr *)&addr,
  198. sizeof(struct sockaddr_in));
  199. if (rc == -1) {
  200. close(ctx->s);
  201. return -1;
  202. }
  203. return 0;
  204. }
  205. /* Closes the network connection and socket in TCP mode */
  206. void _modbus_tcp_close(modbus_t *ctx)
  207. {
  208. shutdown(ctx->s, SHUT_RDWR);
  209. close(ctx->s);
  210. }
  211. int _modbus_tcp_flush(modbus_t *ctx)
  212. {
  213. int rc;
  214. do {
  215. /* Extract the garbage from the socket */
  216. char devnull[MODBUS_TCP_MAX_ADU_LENGTH];
  217. #ifndef OS_WIN32
  218. rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
  219. #else
  220. /* On Win32, it's a bit more complicated to not wait */
  221. fd_set rfds;
  222. struct timeval tv;
  223. tv.tv_sec = 0;
  224. tv.tv_usec = 0;
  225. FD_ZERO(&rfds);
  226. FD_SET(ctx->s, &rfds);
  227. rc = select(ctx->s+1, &rfds, NULL, NULL, &tv);
  228. if (rc == -1) {
  229. return -1;
  230. }
  231. rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, 0);
  232. #endif
  233. if (ctx->debug && rc != -1) {
  234. printf("\n%d bytes flushed\n", rc);
  235. }
  236. } while (rc > 0);
  237. return rc;
  238. }
  239. /* Listens for any request from one or many modbus masters in TCP */
  240. int _modbus_tcp_listen(modbus_t *ctx, int nb_connection)
  241. {
  242. int new_socket;
  243. int yes;
  244. struct sockaddr_in addr;
  245. modbus_tcp_t *ctx_tcp = ctx->backend_data;
  246. #ifdef OS_WIN32
  247. if (_modbus_tcp_init_win32() == -1) {
  248. return -1;
  249. }
  250. #endif
  251. new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  252. if (new_socket == -1) {
  253. return -1;
  254. }
  255. yes = 1;
  256. if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
  257. (char *) &yes, sizeof(yes)) == -1) {
  258. close(new_socket);
  259. return -1;
  260. }
  261. memset(&addr, 0, sizeof(addr));
  262. addr.sin_family = AF_INET;
  263. /* If the modbus port is < to 1024, we need the setuid root. */
  264. addr.sin_port = htons(ctx_tcp->port);
  265. addr.sin_addr.s_addr = INADDR_ANY;
  266. if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  267. close(new_socket);
  268. return -1;
  269. }
  270. if (listen(new_socket, nb_connection) == -1) {
  271. close(new_socket);
  272. return -1;
  273. }
  274. return new_socket;
  275. }
  276. /* On success, the function return a non-negative integer that is a descriptor
  277. for the accepted socket. On error, -1 is returned, and errno is set
  278. appropriately. */
  279. int _modbus_tcp_accept(modbus_t *ctx, int *socket)
  280. {
  281. struct sockaddr_in addr;
  282. socklen_t addrlen;
  283. addrlen = sizeof(struct sockaddr_in);
  284. ctx->s = accept(*socket, (struct sockaddr *)&addr, &addrlen);
  285. if (ctx->s == -1) {
  286. close(*socket);
  287. *socket = 0;
  288. return -1;
  289. }
  290. if (ctx->debug) {
  291. printf("The client %s is connected\n", inet_ntoa(addr.sin_addr));
  292. }
  293. return ctx->s;
  294. }
  295. int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length_computed, int msg_length)
  296. {
  297. int s_rc;
  298. while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) {
  299. if (errno == EINTR) {
  300. if (ctx->debug) {
  301. fprintf(stderr, "A non blocked signal was caught\n");
  302. }
  303. /* Necessary after an error */
  304. FD_ZERO(rfds);
  305. FD_SET(ctx->s, rfds);
  306. } else {
  307. _error_print(ctx, "select");
  308. if (ctx->error_recovery && (errno == EBADF)) {
  309. modbus_close(ctx);
  310. modbus_connect(ctx);
  311. errno = EBADF;
  312. return -1;
  313. } else {
  314. return -1;
  315. }
  316. }
  317. }
  318. if (s_rc == 0) {
  319. /* Timeout */
  320. if (msg_length == (ctx->backend->header_length + 2 +
  321. ctx->backend->checksum_length)) {
  322. /* Optimization allowed because exception response is
  323. the smallest trame in modbus protocol (3) so always
  324. raise a timeout error.
  325. Temporary error before exception analyze. */
  326. errno = EMBUNKEXC;
  327. } else {
  328. errno = ETIMEDOUT;
  329. _error_print(ctx, "select");
  330. }
  331. return -1;
  332. }
  333. return s_rc;
  334. }
  335. int _modbus_tcp_filter_request(modbus_t *ctx, int slave)
  336. {
  337. return 0;
  338. }
  339. const modbus_backend_t _modbus_tcp_backend = {
  340. _MODBUS_BACKEND_TYPE_TCP,
  341. _MODBUS_TCP_HEADER_LENGTH,
  342. _MODBUS_TCP_CHECKSUM_LENGTH,
  343. MODBUS_TCP_MAX_ADU_LENGTH,
  344. _modbus_set_slave,
  345. _modbus_tcp_build_request_basis,
  346. _modbus_tcp_build_response_basis,
  347. _modbus_tcp_prepare_response_tid,
  348. _modbus_tcp_send_msg_pre,
  349. _modbus_tcp_send,
  350. _modbus_tcp_recv,
  351. _modbus_tcp_check_integrity,
  352. _modbus_tcp_connect,
  353. _modbus_tcp_close,
  354. _modbus_tcp_flush,
  355. _modbus_tcp_listen,
  356. _modbus_tcp_accept,
  357. _modbus_tcp_select,
  358. _modbus_tcp_filter_request
  359. };
  360. /* Allocates and initializes the modbus_t structure for TCP.
  361. - ip : "192.168.0.5"
  362. - port : 1099
  363. Set the port to MODBUS_TCP_DEFAULT_PORT to use the default one
  364. (502). It's convenient to use a port number greater than or equal
  365. to 1024 because it's not necessary to be root to use this port
  366. number.
  367. */
  368. modbus_t* modbus_new_tcp(const char *ip, int port)
  369. {
  370. modbus_t *ctx;
  371. modbus_tcp_t *ctx_tcp;
  372. ctx = (modbus_t *) malloc(sizeof(modbus_t));
  373. _modbus_init_common(ctx);
  374. /* Could be changed after to reach a remote serial Modbus device */
  375. ctx->slave = MODBUS_TCP_SLAVE;
  376. ctx->backend = &(_modbus_tcp_backend);
  377. ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
  378. ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
  379. strncpy(ctx_tcp->ip, ip, sizeof(char)*16);
  380. ctx_tcp->port = port;
  381. return ctx;
  382. }