Blob Blame History Raw
commit 4baa578f2b7552ed44482b32fb18dc4bbb53f538
Author: githublvv <ymaillvv@yahoo.com>
Date:   Fri Jan 9 18:15:36 2015 -0500

    Fix for 310: 	memcached unable to bind to an ipv6 address
    
    URL: https://code.google.com/p/memcached/issues/detail?id=310

diff --git a/memcached.c b/memcached.c
index 154b15a..1181966 100644
--- a/memcached.c
+++ b/memcached.c
@@ -4614,15 +4614,40 @@ static int server_sockets(int port, enum network_transport transport,
              p != NULL;
              p = strtok_r(NULL, ";,", &b)) {
             int the_port = port;
+
+            char *h = NULL;
+            if (*p == '[') {
+                // expecting it to be an IPv6 address enclosed in []
+                // i.e. RFC3986 style recommended by RFC5952
+                char *e = strchr(p, ']');
+                if (e == NULL) {
+                    fprintf(stderr, "Invalid IPV6 address: \"%s\"", p);
+                    return 1;
+                }
+                h = ++p; // skip the opening '['
+                *e = '\0';
+                p = ++e; // skip the closing ']'
+            }
+
             char *s = strchr(p, ':');
             if (s != NULL) {
-                *s = '\0';
-                ++s;
-                if (!safe_strtol(s, &the_port)) {
-                    fprintf(stderr, "Invalid port number: \"%s\"", s);
-                    return 1;
+                // If no more semicolons - attempt to treat as port number.
+                // Otherwise the only valid option is an unenclosed IPv6 without port, until
+                // of course there was an RFC3986 IPv6 address previously specified -
+                // in such a case there is no good option, will just send it to fail as port number.
+                if (strchr(s + 1, ':') == NULL || h != NULL) {
+                    *s = '\0';
+                    ++s;
+                    if (!safe_strtol(s, &the_port)) {
+                        fprintf(stderr, "Invalid port number: \"%s\"", s);
+                        return 1;
+                    }
                 }
             }
+
+            if (h != NULL)
+                p = h;
+
             if (strcmp(p, "*") == 0) {
                 p = NULL;
             }