]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: config: allow IPv6 bracketed literals
authormildis <me@mildis.org>
Mon, 26 Oct 2015 17:50:08 +0000 (18:50 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 1 Nov 2015 20:30:41 +0000 (21:30 +0100)
src/standard.c

index b5f4bf40462f4adacbfcff9dd34ff18ea1ed1778..969daf6b3ffb41e61f258dec5602bf926a723f4b 100644 (file)
@@ -620,6 +620,33 @@ const char *invalid_domainchar(const char *name) {
 struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, int resolve)
 {
        struct hostent *he;
+       /* max IPv6 length, including brackets and terminating NULL */
+       char tmpip[48];
+
+       /* check IPv6 with square brackets */
+       if (str[0] == '[') {
+               size_t iplength = strlen(str);
+
+               if (iplength < 4) {
+                       /* minimal size is 4 when using brackets "[::]" */
+                       goto fail;
+               }
+               else if (iplength >= sizeof(tmpip)) {
+                       /* IPv6 literal can not be larger than tmpip */
+                       goto fail;
+               }
+               else {
+                       if (str[iplength - 1] != ']') {
+                               /* if address started with bracket, it should end with bracket */
+                               goto fail;
+                       }
+                       else {
+                               memcpy(tmpip, str + 1, iplength - 2);
+                               tmpip[iplength - 2] = '\0';
+                               str = tmpip;
+                       }
+               }
+       }
 
        /* Any IPv6 address */
        if (str[0] == ':' && str[1] == ':' && !str[2]) {
@@ -747,10 +774,12 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i
  *                  the first byte of the address.
  *    - "fd@"    => an integer must follow, and is a file descriptor number.
  *
- * Also note that in order to avoid any ambiguity with IPv6 addresses, the ':'
- * is mandatory after the IP address even when no port is specified. NULL is
- * returned if the address cannot be parsed. The <low> and <high> ports are
- * always initialized if non-null, even for non-IP families.
+ * IPv6 addresses can be declared with or without square brackets. When using
+ * square brackets for IPv6 addresses, the port separator (colon) is optional.
+ * If not using square brackets, and in order to avoid any ambiguity with
+ * IPv6 addresses, the last colon ':' is mandatory even when no port is specified.
+ * NULL is returned if the address cannot be parsed. The <low> and <high> ports
+ * are always initialized if non-null, even for non-IP families.
  *
  * If <pfx> is non-null, it is used as a string prefix before any path-based
  * address (typically the path to a unix socket).
@@ -855,12 +884,29 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char
        }
        else { /* IPv4 and IPv6 */
                int use_fqdn = 0;
+               char *end = str2 + strlen(str2);
+               char *chr;
 
-               port1 = strrchr(str2, ':');
-               if (port1)
-                       *port1++ = '\0';
-               else
+               /* search for : or ] whatever comes first */
+               for (chr = end-1; chr > str2; chr--) {
+                       if (*chr == ']' || *chr == ':')
+                               break;
+               }
+
+               if (*chr == ':') {
+                       /* Found a colon before a closing-bracket, must be a port separator.
+                        * This guarantee backward compatibility.
+                        */
+                       *chr++ = '\0';
+                       port1 = chr;
+               }
+               else {
+                       /* Either no colon and no closing-bracket
+                        * or directly ending with a closing-bracket.
+                        * However, no port.
+                        */
                        port1 = "";
+               }
 
                if (str2ip2(str2, &ss, 0) == NULL) {
                        use_fqdn = 1;