Commit c1665d400c2a490e6110f92e8fd34c5cf87d55db

Authored by Stéphane Raimbault
1 parent c3358643

Filter of IP addresses in IPv4 server (closes #190)

- protect against NULL IP address BTW
- update documentation
1 -libmodbus 3.1.2 (2013-XX-XX) 1 +libmodbus 3.1.2 (2014-XX-XX)
2 ============================ 2 ============================
3 3
  4 +If you still want to listen any addresses in your TCP IPv4 server, you must now
  5 +set the IP address to NULL in modbus_new_tcp before listening. Now,
  6 +modbus_tcp_listen only listen the IP address set in the Modbus context (see
  7 +documentation).
  8 +
4 This release introduces API changes on modbus_get_byte_timeout, 9 This release introduces API changes on modbus_get_byte_timeout,
5 modbus_get_response_timeout, modbus_set_byte_timeout, 10 modbus_get_response_timeout, modbus_set_byte_timeout,
6 modbus_set_response_timeout to ease writing of language bindings. 11 modbus_set_response_timeout to ease writing of language bindings.
7 12
  13 +- Filter of IP addresses in IPv4 server (closes #190)
8 - Allow to listen any hosts in IPv6 (closes #32) 14 - Allow to listen any hosts in IPv6 (closes #32)
9 - Define and public export of MODBUS_MAX_PDU_LENGTH (closes #167) 15 - Define and public export of MODBUS_MAX_PDU_LENGTH (closes #167)
10 - Truncate data from response in report_slave_id to new max arg (closes #167) 16 - Truncate data from response in report_slave_id to new max arg (closes #167)
doc/modbus_new_tcp.txt
@@ -14,21 +14,22 @@ SYNOPSIS @@ -14,21 +14,22 @@ SYNOPSIS
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 -The _modbus_new_tcp()_ function shall allocate and initialize a modbus_t  
18 -structure to communicate with a Modbus TCP/IPv4 server. 17 +The *modbus_new_tcp()* function shall allocate and initialize a modbus_t
  18 +structure to communicate with a Modbus TCP IPv4 server.
19 19
20 The _ip_ argument specifies the IP address of the server to which the client 20 The _ip_ argument specifies the IP address of the server to which the client
21 -wants etablish a connection. 21 +wants etablish a connection. A NULL value can be used to listen any addresses in
  22 +server mode.
22 23
23 The _port_ argument is the TCP port to use. Set the port to 24 The _port_ argument is the TCP port to use. Set the port to
24 -_MODBUS_TCP_DEFAULT_PORT_ to use the default one (502). It’s convenient to use a 25 +*MODBUS_TCP_DEFAULT_PORT* to use the default one (502). It’s convenient to use a
25 port number greater than or equal to 1024 because it’s not necessary to have 26 port number greater than or equal to 1024 because it’s not necessary to have
26 administrator privileges. 27 administrator privileges.
27 28
28 29
29 RETURN VALUE 30 RETURN VALUE
30 ------------ 31 ------------
31 -The _modbus_new_tcp()_ function shall return a pointer to a *modbus_t* structure 32 +The *modbus_new_tcp()* function shall return a pointer to a *modbus_t* structure
32 if successful. Otherwise it shall return NULL and set errno to one of the values 33 if successful. Otherwise it shall return NULL and set errno to one of the values
33 defined below. 34 defined below.
34 35
@@ -60,7 +61,7 @@ if (modbus_connect(ctx) == -1) { @@ -60,7 +61,7 @@ if (modbus_connect(ctx) == -1) {
60 61
61 SEE ALSO 62 SEE ALSO
62 -------- 63 --------
63 -linkmb:modbus_new_rtu[3] 64 +linkmb:modbus_tcp_listen[3]
64 linkmb:modbus_free[3] 65 linkmb:modbus_free[3]
65 66
66 67
doc/modbus_tcp_listen.txt
@@ -14,13 +14,16 @@ SYNOPSIS @@ -14,13 +14,16 @@ SYNOPSIS
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 -The _modbus_tcp_listen()_ function shall create a socket and listen for  
18 -'nb_connection' incoming connections. 17 +The *modbus_tcp_listen()* function shall create a socket and listen to maximum
  18 +_nb_connection_ incoming connections on the specified IP address. The context
  19 +_ctx _must be allocated and initialized with linkmb:modbus_new_tcp[3] before to
  20 +set the IP address to listen, if IP address is o NULL, any addresses will be
  21 +listen.
19 22
20 23
21 RETURN VALUE 24 RETURN VALUE
22 ------------ 25 ------------
23 -The _modbus_tcp_listen()_ function shall return a new socket if 26 +The *modbus_tcp_listen()* function shall return a new socket if
24 successful. Otherwise it shall return -1 and set errno. 27 successful. Otherwise it shall return -1 and set errno.
25 28
26 29
@@ -36,7 +39,8 @@ For detailed examples, see source files in tests directory: @@ -36,7 +39,8 @@ For detailed examples, see source files in tests directory:
36 ------------------- 39 -------------------
37 ... 40 ...
38 41
39 -ctx = modbus_new_tcp("127.0.0.1", 502); 42 +/* To listen any addresses on port 502 */
  43 +ctx = modbus_new_tcp(NULL, 502);
40 44
41 /* Handle until 10 established connections */ 45 /* Handle until 10 established connections */
42 server_socket = modbus_tcp_listen(ctx, 10); 46 server_socket = modbus_tcp_listen(ctx, 10);
@@ -58,8 +62,8 @@ modbus_free(ctx); @@ -58,8 +62,8 @@ modbus_free(ctx);
58 62
59 SEE ALSO 63 SEE ALSO
60 -------- 64 --------
  65 +linkmb:modbus_new_tcp[3]
61 linkmb:modbus_tcp_accept[3] 66 linkmb:modbus_tcp_accept[3]
62 -linkmb:modbus_tcp_pi_accept[3]  
63 linkmb:modbus_tcp_pi_listen[3] 67 linkmb:modbus_tcp_pi_listen[3]
64 68
65 AUTHORS 69 AUTHORS
src/modbus-tcp.c
@@ -515,7 +515,13 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) @@ -515,7 +515,13 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
515 addr.sin_family = AF_INET; 515 addr.sin_family = AF_INET;
516 /* If the modbus port is < to 1024, we need the setuid root. */ 516 /* If the modbus port is < to 1024, we need the setuid root. */
517 addr.sin_port = htons(ctx_tcp->port); 517 addr.sin_port = htons(ctx_tcp->port);
518 - addr.sin_addr.s_addr = INADDR_ANY; 518 + if (ctx_tcp->ip[0] == '0') {
  519 + /* Listen any addresses */
  520 + addr.sin_addr.s_addr = INADDR_ANY;
  521 + } else {
  522 + /* Listen only specified IP address */
  523 + addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
  524 + }
519 if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 525 if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
520 close(new_s); 526 close(new_s);
521 return -1; 527 return -1;
@@ -807,22 +813,25 @@ modbus_t* modbus_new_tcp(const char *ip, int port) @@ -807,22 +813,25 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
807 ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t)); 813 ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
808 ctx_tcp = (modbus_tcp_t *)ctx->backend_data; 814 ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
809 815
810 - dest_size = sizeof(char) * 16;  
811 - ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);  
812 - if (ret_size == 0) {  
813 - fprintf(stderr, "The IP string is empty\n");  
814 - modbus_free(ctx);  
815 - errno = EINVAL;  
816 - return NULL;  
817 - } 816 + if (ip != NULL) {
  817 + dest_size = sizeof(char) * 16;
  818 + ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
  819 + if (ret_size == 0) {
  820 + fprintf(stderr, "The IP string is empty\n");
  821 + modbus_free(ctx);
  822 + errno = EINVAL;
  823 + return NULL;
  824 + }
818 825
819 - if (ret_size >= dest_size) {  
820 - fprintf(stderr, "The IP string has been truncated\n");  
821 - modbus_free(ctx);  
822 - errno = EINVAL;  
823 - return NULL; 826 + if (ret_size >= dest_size) {
  827 + fprintf(stderr, "The IP string has been truncated\n");
  828 + modbus_free(ctx);
  829 + errno = EINVAL;
  830 + return NULL;
  831 + }
  832 + } else {
  833 + ctx_tcp->ip[0] = '0';
824 } 834 }
825 -  
826 ctx_tcp->port = port; 835 ctx_tcp->port = port;
827 ctx_tcp->t_id = 0; 836 ctx_tcp->t_id = 0;
828 837
tests/unit-test-client.c
@@ -98,7 +98,7 @@ int main(int argc, char *argv[]) @@ -98,7 +98,7 @@ int main(int argc, char *argv[])
98 MODBUS_ERROR_RECOVERY_PROTOCOL); 98 MODBUS_ERROR_RECOVERY_PROTOCOL);
99 99
100 if (use_backend == RTU) { 100 if (use_backend == RTU) {
101 - modbus_set_slave(ctx, SERVER_ID); 101 + modbus_set_slave(ctx, SERVER_ID);
102 } 102 }
103 103
104 modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec); 104 modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);