瀏覽代碼

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,
 modbus_get_response_timeout, modbus_set_byte_timeout,
 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)
 - 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)

+ 7 - 6
doc/modbus_new_tcp.txt

@@ -14,21 +14,22 @@ SYNOPSIS
 
 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
-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
-_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
 administrator privileges.
 
 
 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
 defined below.
 
@@ -60,7 +61,7 @@ if (modbus_connect(ctx) == -1) {
 
 SEE ALSO
 --------
-linkmb:modbus_new_rtu[3]
+linkmb:modbus_tcp_listen[3]
 linkmb:modbus_free[3]
 
 

+ 9 - 5
doc/modbus_tcp_listen.txt

@@ -14,13 +14,16 @@ SYNOPSIS
 
 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
 ------------
-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.
 
 
@@ -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 */
 server_socket = modbus_tcp_listen(ctx, 10);
@@ -58,8 +62,8 @@ modbus_free(ctx);
 
 SEE ALSO
 --------
+linkmb:modbus_new_tcp[3]
 linkmb:modbus_tcp_accept[3]
-linkmb:modbus_tcp_pi_accept[3]
 linkmb:modbus_tcp_pi_listen[3]
 
 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;
     /* If the modbus port is < to 1024, we need the setuid root. */
     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) {
         close(new_s);
         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_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->t_id = 0;
 

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

@@ -98,7 +98,7 @@ int main(int argc, char *argv[])
                               MODBUS_ERROR_RECOVERY_PROTOCOL);
 
     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);