Support for IPv6 has been broken with revision 1522: Because IPv6-addresses
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Thu, 25 Sep 2008 20:10:17 +0000 (20:10 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Thu, 25 Sep 2008 20:10:17 +0000 (20:10 +0000)
contain colons, simply checking for a colon and using everything after it does
destroy correctly formatted IPv6-addresses.

This patch checks for dots '.' in the address. If the address contains at least
one dot, it is considered to be a hostname or an IPv4-address and a simple
search for a colon is done.

If no dot is found, the code will check for an opening square bracket '[' at
the beginning of the address. If one if found, the format
  [address]:port
is assumed.

If neither applies, the default port will be used.
-- Florian Forster

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1523 a5681a0c-68f1-0310-ab6d-d61299d08faa

doc/rrdcached.pod
src/rrd_daemon.c

index bdb8949..3505728 100644 (file)
@@ -35,14 +35,19 @@ interpreted as the path to a UNIX domain socket. Otherwise the address or node
 name are resolved using L<getaddrinfo>.
 
 For network sockets, a port may be specified by using the form
-I<address>:I<port>.  The default port is 42217.
+C<B<[>I<address>B<]:>I<port>>. If the address is an IPv4 address or a fully
+qualified domain name (i.E<nbsp>e. the address contains at least one dot
+(C<.>)), the square brackets can be omitted, resulting in the (simpler)
+C<I<address>B<:>I<port>> pattern.. The default port is B<42217/udp>.
 
-These formats are accepted:
+The following formats are accepted. Please note that the address of the UNIX
+domain socket B<must> start with a slash in the second case!
 
    unix:</path/to/unix.sock>
-   </path/to/unix.sock>
+   /<path/to/unix.sock>
    <hostname-or-ip>
-   <hostname-or-ip>:<port>
+   [<hostname-or-ip>]:<port>
+   <hostname-or-ipv4>:<port>
 
 If the B<-l> option is not specified the default address,
 C<unix:/tmp/rrdcached.sock>, will be used.
index 6f01f89..a94e079 100644 (file)
@@ -1563,15 +1563,21 @@ static int open_listen_socket_unix (const char *path) /* {{{ */
   return (0);
 } /* }}} int open_listen_socket_unix */
 
-static int open_listen_socket (const char *addr) /* {{{ */
+static int open_listen_socket (const char *addr_orig) /* {{{ */
 {
   struct addrinfo ai_hints;
   struct addrinfo *ai_res;
   struct addrinfo *ai_ptr;
+  char addr_copy[NI_MAXHOST];
+  char *addr;
   char *port;
   int status;
 
-  assert (addr != NULL);
+  assert (addr_orig != NULL);
+
+  strncpy (addr_copy, addr_orig, sizeof (addr_copy));
+  addr_copy[sizeof (addr_copy) - 1] = 0;
+  addr = addr_copy;
 
   if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
     return (open_listen_socket_unix (addr + strlen ("unix:")));
@@ -1586,10 +1592,42 @@ static int open_listen_socket (const char *addr) /* {{{ */
   ai_hints.ai_family = AF_UNSPEC;
   ai_hints.ai_socktype = SOCK_STREAM;
 
-  port = rindex(addr, ':');
-  if (port != NULL)
-    *port++ = '\0';
+  port = NULL;
+ if (*addr == '[') /* IPv6+port format */
+  {
+    /* `addr' is something like "[2001:780:104:2:211:24ff:feab:26f8]:12345" */
+    addr++;
 
+    port = strchr (addr, ']');
+    if (port == NULL)
+    {
+      RRDD_LOG (LOG_ERR, "open_listen_socket: Malformed address: %s",
+          addr_orig);
+      return (-1);
+    }
+    *port = 0;
+    port++;
+
+    if (*port == ':')
+      port++;
+    else if (*port == 0)
+      port = NULL;
+    else
+    {
+      RRDD_LOG (LOG_ERR, "open_listen_socket: Garbage after address: %s",
+          port);
+      return (-1);
+    }
+  } /* if (*addr = ']') */
+  else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */
+  {
+    port = rindex(addr, ':');
+    if (port != NULL)
+    {
+      *port = 0;
+      port++;
+    }
+  }
   ai_res = NULL;
   status = getaddrinfo (addr,
                         port == NULL ? RRDCACHED_DEFAULT_PORT : port,