Commit 8f1cc7b3c8de8ef64b2ea35676d3e6ac039dbc3d

Authored by Stéphane Raimbault
1 parent 652b5b05

Allow to listen any hosts in IPv6 (closes #32)

- allow an empty string or NULL for node argument
- protect against NULL in service argument
- new test for NULL service
- update documentation
doc/modbus_new_tcp_pi.txt
@@ -14,11 +14,12 @@ SYNOPSIS @@ -14,11 +14,12 @@ SYNOPSIS
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 -The _modbus_new_tcp_pi()_ function shall allocate and initialize a modbus_t  
18 -structure to communicate with a Modbus TCP IPv4 or Ipv6 server. 17 +The *modbus_new_tcp_pi()* function shall allocate and initialize a modbus_t
  18 +structure to communicate with a Modbus TCP IPv4 or IPv6 server.
19 19
20 The _node_ argument specifies the host name or IP address of the host to connect 20 The _node_ argument specifies the host name or IP address of the host to connect
21 -to, eg. '192.168.0.5' , '::1' or 'server.com'. 21 +to, eg. "192.168.0.5" , "::1" or "server.com". A NULL value can be used to
  22 +listen any addresses in server mode.
22 23
23 The _service_ argument is the service name/port number to connect to. To use the 24 The _service_ argument is the service name/port number to connect to. To use the
24 default Modbus port use the string "502". On many Unix systems, it’s 25 default Modbus port use the string "502". On many Unix systems, it’s
@@ -28,7 +29,7 @@ necessary to have administrator privileges. @@ -28,7 +29,7 @@ necessary to have administrator privileges.
28 29
29 RETURN VALUE 30 RETURN VALUE
30 ------------ 31 ------------
31 -The _modbus_new_tcp_pi()_ function shall return a pointer to a *modbus_t* structure 32 +The *modbus_new_tcp_pi()* 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
@@ -62,7 +63,7 @@ if (modbus_connect(ctx) == -1) { @@ -62,7 +63,7 @@ if (modbus_connect(ctx) == -1) {
62 SEE ALSO 63 SEE ALSO
63 -------- 64 --------
64 linkmb:modbus_new_tcp[3] 65 linkmb:modbus_new_tcp[3]
65 -linkmb:modbus_new_rtu[3] 66 +linkmb:modbus_tcp_pi_listen[3]
66 linkmb:modbus_free[3] 67 linkmb:modbus_free[3]
67 68
68 69
doc/modbus_tcp_pi_listen.txt
@@ -14,13 +14,16 @@ SYNOPSIS @@ -14,13 +14,16 @@ SYNOPSIS
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 -The _modbus_tcp_pi_listen()_ function shall create a socket and listen for  
18 -'nb_connection' incoming connections. 17 +The *modbus_tcp_pi_listen()* function shall create a socket and listen to
  18 +maximum _nb_connection_ incoming connections on the specified nodes. The
  19 +context *ctx* must be allocated and initialized with linkmb:modbus_new_tcp_pi[3]
  20 +before to set the node to listen, if node is set to 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
@@ -54,8 +57,8 @@ modbus_free(ctx); @@ -54,8 +57,8 @@ modbus_free(ctx);
54 57
55 SEE ALSO 58 SEE ALSO
56 -------- 59 --------
  60 +linkmb:modbus_new_tcp_pi[3]
57 linkmb:modbus_tcp_pi_accept[3] 61 linkmb:modbus_tcp_pi_accept[3]
58 -linkmb:modbus_tcp_accept[3]  
59 linkmb:modbus_tcp_listen[3] 62 linkmb:modbus_tcp_listen[3]
60 63
61 AUTHORS 64 AUTHORS
src/modbus-tcp.c
@@ -553,17 +553,20 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) @@ -553,17 +553,20 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
553 } 553 }
554 #endif 554 #endif
555 555
556 - if (ctx_tcp_pi->node[0] == 0) 556 + if (ctx_tcp_pi->node[0] == 0) {
557 node = NULL; /* == any */ 557 node = NULL; /* == any */
558 - else 558 + } else {
559 node = ctx_tcp_pi->node; 559 node = ctx_tcp_pi->node;
  560 + }
560 561
561 - if (ctx_tcp_pi->service[0] == 0) 562 + if (ctx_tcp_pi->service[0] == 0) {
562 service = "502"; 563 service = "502";
563 - else 564 + } else {
564 service = ctx_tcp_pi->service; 565 service = ctx_tcp_pi->service;
  566 + }
565 567
566 memset(&ai_hints, 0, sizeof (ai_hints)); 568 memset(&ai_hints, 0, sizeof (ai_hints));
  569 + /* If node is not NULL, than the AI_PASSIVE flag is ignored. */
567 ai_hints.ai_flags |= AI_PASSIVE; 570 ai_hints.ai_flags |= AI_PASSIVE;
568 #ifdef AI_ADDRCONFIG 571 #ifdef AI_ADDRCONFIG
569 ai_hints.ai_flags |= AI_ADDRCONFIG; 572 ai_hints.ai_flags |= AI_ADDRCONFIG;
@@ -845,24 +848,35 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) @@ -845,24 +848,35 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
845 ctx->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t)); 848 ctx->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t));
846 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data; 849 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
847 850
848 - dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;  
849 - ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);  
850 - if (ret_size == 0) {  
851 - fprintf(stderr, "The node string is empty\n");  
852 - modbus_free(ctx);  
853 - errno = EINVAL;  
854 - return NULL; 851 + if (node == NULL) {
  852 + /* The node argument can be empty to indicate any hosts */
  853 + ctx_tcp_pi->node[0] = '0';
  854 + } else {
  855 + dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
  856 + ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
  857 + if (ret_size == 0) {
  858 + fprintf(stderr, "The node string is empty\n");
  859 + modbus_free(ctx);
  860 + errno = EINVAL;
  861 + return NULL;
  862 + }
  863 +
  864 + if (ret_size >= dest_size) {
  865 + fprintf(stderr, "The node string has been truncated\n");
  866 + modbus_free(ctx);
  867 + errno = EINVAL;
  868 + return NULL;
  869 + }
855 } 870 }
856 871
857 - if (ret_size >= dest_size) {  
858 - fprintf(stderr, "The node string has been truncated\n");  
859 - modbus_free(ctx);  
860 - errno = EINVAL;  
861 - return NULL; 872 + if (service != NULL) {
  873 + dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
  874 + ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
  875 + } else {
  876 + /* Empty service is not allowed, error catched below. */
  877 + ret_size = 0;
862 } 878 }
863 879
864 - dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;  
865 - ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);  
866 if (ret_size == 0) { 880 if (ret_size == 0) {
867 fprintf(stderr, "The service string is empty\n"); 881 fprintf(stderr, "The service string is empty\n");
868 modbus_free(ctx); 882 modbus_free(ctx);
tests/unit-test-client.c
@@ -600,6 +600,9 @@ int main(int argc, char *argv[]) @@ -600,6 +600,9 @@ int main(int argc, char *argv[])
600 ctx = modbus_new_rtu(NULL, 0, 'A', 0, 0); 600 ctx = modbus_new_rtu(NULL, 0, 'A', 0, 0);
601 ASSERT_TRUE(ctx == NULL && errno == EINVAL, ""); 601 ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
602 602
  603 + ctx = modbus_new_tcp_pi(NULL, NULL);
  604 + ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
  605 +
603 printf("\nALL TESTS PASS WITH SUCCESS.\n"); 606 printf("\nALL TESTS PASS WITH SUCCESS.\n");
604 607
605 close: 608 close: