ソースを参照

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

- protect against NULL IP address BTW
- update documentation
Stéphane Raimbault 11 年 前
コミット
c1665d400c
5 ファイル変更48 行追加28 行削除
  1. 7 1
      NEWS
  2. 7 6
      doc/modbus_new_tcp.txt
  3. 9 5
      doc/modbus_tcp_listen.txt
  4. 24 15
      src/modbus-tcp.c
  5. 1 1
      tests/unit-test-client.c

+ 7 - 1
NEWS

@@ -1,10 +1,16 @@
-libmodbus 3.1.2 (2013-XX-XX)
+libmodbus 3.1.2 (2014-XX-XX)
 ============================
 ============================
 
 
+If you still want to listen any addresses in your TCP IPv4 server, you must now
+set the IP address to NULL in modbus_new_tcp before listening. Now,
+modbus_tcp_listen only listen the IP address set in the Modbus context (see
+documentation).
+
 This release introduces API changes on modbus_get_byte_timeout,
 This release introduces API changes on modbus_get_byte_timeout,
 modbus_get_response_timeout, modbus_set_byte_timeout,
 modbus_get_response_timeout, modbus_set_byte_timeout,
 modbus_set_response_timeout to ease writing of language bindings.
 modbus_set_response_timeout to ease writing of language bindings.
 
 
+- Filter of IP addresses in IPv4 server (closes #190)
 - Allow to listen any hosts in IPv6 (closes #32)
 - Allow to listen any hosts in IPv6 (closes #32)
 - Define and public export of MODBUS_MAX_PDU_LENGTH (closes #167)
 - Define and public export of MODBUS_MAX_PDU_LENGTH (closes #167)
 - Truncate data from response in report_slave_id to new max arg (closes #167)
 - Truncate data from response in report_slave_id to new max arg (closes #167)

+ 7 - 6
doc/modbus_new_tcp.txt

@@ -14,21 +14,22 @@ SYNOPSIS
 
 
 DESCRIPTION
 DESCRIPTION
 -----------
 -----------
-The _modbus_new_tcp()_ function shall allocate and initialize a modbus_t
-structure to communicate with a Modbus TCP/IPv4 server.
+The *modbus_new_tcp()* function shall allocate and initialize a modbus_t
+structure to communicate with a Modbus TCP IPv4 server.
 
 
 The _ip_ argument specifies the IP address of the server to which the client
 The _ip_ argument specifies the IP address of the server to which the client
-wants etablish a connection.
+wants etablish a connection. A NULL value can be used to listen any addresses in
+server mode.
 
 
 The _port_ argument is the TCP port to use. Set the port to
 The _port_ argument is the TCP port to use. Set the port to
-_MODBUS_TCP_DEFAULT_PORT_ to use the default one (502). It’s convenient to use a
+*MODBUS_TCP_DEFAULT_PORT* to use the default one (502). It’s convenient to use a
 port number greater than or equal to 1024 because it’s not necessary to have
 port number greater than or equal to 1024 because it’s not necessary to have
 administrator privileges.
 administrator privileges.
 
 
 
 
 RETURN VALUE
 RETURN VALUE
 ------------
 ------------
-The _modbus_new_tcp()_ function shall return a pointer to a *modbus_t* structure
+The *modbus_new_tcp()* function shall return a pointer to a *modbus_t* structure
 if successful. Otherwise it shall return NULL and set errno to one of the values
 if successful. Otherwise it shall return NULL and set errno to one of the values
 defined below.
 defined below.
 
 
@@ -60,7 +61,7 @@ if (modbus_connect(ctx) == -1) {
 
 
 SEE ALSO
 SEE ALSO
 --------
 --------
-linkmb:modbus_new_rtu[3]
+linkmb:modbus_tcp_listen[3]
 linkmb:modbus_free[3]
 linkmb:modbus_free[3]
 
 
 
 

+ 9 - 5
doc/modbus_tcp_listen.txt

@@ -14,13 +14,16 @@ SYNOPSIS
 
 
 DESCRIPTION
 DESCRIPTION
 -----------
 -----------
-The _modbus_tcp_listen()_ function shall create a socket and listen for
-'nb_connection' incoming connections.
+The *modbus_tcp_listen()* function shall create a socket and listen to maximum
+_nb_connection_ incoming connections on the specified IP address.  The context
+_ctx _must be allocated and initialized with linkmb:modbus_new_tcp[3] before to
+set the IP address to listen, if IP address is o NULL, any addresses will be
+listen.
 
 
 
 
 RETURN VALUE
 RETURN VALUE
 ------------
 ------------
-The _modbus_tcp_listen()_ function shall return a new socket if
+The *modbus_tcp_listen()* function shall return a new socket if
 successful. Otherwise it shall return -1 and set errno.
 successful. Otherwise it shall return -1 and set errno.
 
 
 
 
@@ -36,7 +39,8 @@ For detailed examples, see source files in tests directory:
 -------------------
 -------------------
 ...
 ...
 
 
-ctx = modbus_new_tcp("127.0.0.1", 502);
+/* To listen any addresses on port 502 */
+ctx = modbus_new_tcp(NULL, 502);
 
 
 /* Handle until 10 established connections */
 /* Handle until 10 established connections */
 server_socket = modbus_tcp_listen(ctx, 10);
 server_socket = modbus_tcp_listen(ctx, 10);
@@ -58,8 +62,8 @@ modbus_free(ctx);
 
 
 SEE ALSO
 SEE ALSO
 --------
 --------
+linkmb:modbus_new_tcp[3]
 linkmb:modbus_tcp_accept[3]
 linkmb:modbus_tcp_accept[3]
-linkmb:modbus_tcp_pi_accept[3]
 linkmb:modbus_tcp_pi_listen[3]
 linkmb:modbus_tcp_pi_listen[3]
 
 
 AUTHORS
 AUTHORS

+ 24 - 15
src/modbus-tcp.c

@@ -515,7 +515,13 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
     addr.sin_family = AF_INET;
     addr.sin_family = AF_INET;
     /* If the modbus port is < to 1024, we need the setuid root. */
     /* If the modbus port is < to 1024, we need the setuid root. */
     addr.sin_port = htons(ctx_tcp->port);
     addr.sin_port = htons(ctx_tcp->port);
-    addr.sin_addr.s_addr = INADDR_ANY;
+    if (ctx_tcp->ip[0] == '0') {
+        /* Listen any addresses */
+        addr.sin_addr.s_addr = INADDR_ANY;
+    } else {
+        /* Listen only specified IP address */
+        addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
+    }
     if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
     if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
         close(new_s);
         close(new_s);
         return -1;
         return -1;
@@ -807,22 +813,25 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
     ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
     ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
     ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
     ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
 
 
-    dest_size = sizeof(char) * 16;
-    ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
-    if (ret_size == 0) {
-        fprintf(stderr, "The IP string is empty\n");
-        modbus_free(ctx);
-        errno = EINVAL;
-        return NULL;
-    }
+    if (ip != NULL) {
+        dest_size = sizeof(char) * 16;
+        ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
+        if (ret_size == 0) {
+            fprintf(stderr, "The IP string is empty\n");
+            modbus_free(ctx);
+            errno = EINVAL;
+            return NULL;
+        }
 
 
-    if (ret_size >= dest_size) {
-        fprintf(stderr, "The IP string has been truncated\n");
-        modbus_free(ctx);
-        errno = EINVAL;
-        return NULL;
+        if (ret_size >= dest_size) {
+            fprintf(stderr, "The IP string has been truncated\n");
+            modbus_free(ctx);
+            errno = EINVAL;
+            return NULL;
+        }
+    } else {
+        ctx_tcp->ip[0] = '0';
     }
     }
-
     ctx_tcp->port = port;
     ctx_tcp->port = port;
     ctx_tcp->t_id = 0;
     ctx_tcp->t_id = 0;
 
 

+ 1 - 1
tests/unit-test-client.c

@@ -98,7 +98,7 @@ int main(int argc, char *argv[])
                               MODBUS_ERROR_RECOVERY_PROTOCOL);
                               MODBUS_ERROR_RECOVERY_PROTOCOL);
 
 
     if (use_backend == RTU) {
     if (use_backend == RTU) {
-          modbus_set_slave(ctx, SERVER_ID);
+        modbus_set_slave(ctx, SERVER_ID);
     }
     }
 
 
     modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
     modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);