From f2d480b190c1f4199e86ff3095a4fb6ac641a4bb Mon Sep 17 00:00:00 2001 From: oetiker Date: Thu, 25 Sep 2008 20:10:17 +0000 Subject: [PATCH] Support for IPv6 has been broken with revision 1522: Because IPv6-addresses 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 | 13 +++++++++---- src/rrd_daemon.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/doc/rrdcached.pod b/doc/rrdcached.pod index bdb8949..3505728 100644 --- a/doc/rrdcached.pod +++ b/doc/rrdcached.pod @@ -35,14 +35,19 @@ interpreted as the path to a UNIX domain socket. Otherwise the address or node name are resolved using L. For network sockets, a port may be specified by using the form -I
:I. The default port is 42217. +CI
B<]:>I>. If the address is an IPv4 address or a fully +qualified domain name (i.Ee. the address contains at least one dot +(C<.>)), the square brackets can be omitted, resulting in the (simpler) +CB<:>I> 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 start with a slash in the second case! unix: - + / - : + []: + : If the B<-l> option is not specified the default address, C, will be used. diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c index 6f01f89..a94e079 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -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, -- 2.11.0