Hi,

if you are interested. The patch will bind squid to all A/AAAA
DNS records when a hostname is specified in the http_port directive.
Also does the patch allows to use IPv6 address/port syntax as suggested
in RFC2732 in the http_port directive.

Please see attachment for the patch.

Regards,
Oliver
diff -urNad /home/racon/squid/squid_2.5.3ipv6.20030616-4/src/cache_cf.c 
squid_2.5.3ipv6.20030616-4/src/cache_cf.c
--- /home/racon/squid/squid_2.5.3ipv6.20030616-4/src/cache_cf.c 2003-06-22 
22:50:35.000000000 -0300
+++ squid_2.5.3ipv6.20030616-4/src/cache_cf.c   2003-06-22 23:04:57.000000000 -0300
@@ -2203,43 +2203,151 @@
     return PEER_SIBLING;
 }
 
+static int
+get_address_list(const char* host, const unsigned int port,
+                 sockaddr_in_list** head, int af)
+{
+    int i = 0;
+    struct IN_ADDR addr;
+    int c = 0;
+    struct hostent* hp;
+    
+    /* do the query */
+    if((hp = gethostbyname2(host, af)) != NULL)
+    {
+        /* iterate through results */
+        while(hp->h_addr_list[i] != NULL)
+        {
+            c++;
+#ifdef INET6
+            /* if h_addrtype is AF_INET convert into AF_INET6 */
+            if(hp->h_addrtype == AF_INET)
+            {
+                addr.s6_addr32[0] = 0;
+                addr.s6_addr32[1] = 0;
+                addr.s6_addr32[2] = htonl(0xffff);
+                addr.s6_addr32[3] = 
+                    *((uint32_t*)(hp->h_addr_list[i]));
+            }
+            else
+#endif          
+            addr = *((struct IN_ADDR*)hp->h_addr_list[i]);
+            
+            sockaddr_in_list* sa_li;
+            sa_li = xcalloc(1, sizeof(sockaddr_in_list));
+            xmemcpy(&ADDR_FROM_SA(sa_li->s), 
+                    &addr, sizeof(struct IN_ADDR));
+            PORT_FROM_SA(sa_li->s) = htons(port);
+            
+            /* do not need to check for duplicates here since 
+             * DNS does not delivers duplicates and squid handles sockets
+             * which cannot be opened gracefully. */
+            while (*head)
+                head = &(*head)->next;
+            
+            *head = sa_li;
+            i++;
+        }
+    }
+    return c;
+}
+ 
 static void
 parse_sockaddr_in_list(sockaddr_in_list ** head)
 {
     char *token;
     char *t;
     char *host;
-    const struct hostent *hp;
     unsigned short port;
-    sockaddr_in_list *s;
     while ((token = strtok(NULL, w_space))) {
        host = NULL;
        port = 0;
-       if ((t = strchr(token, ':'))) {
+        /* If token starts with an opening bracket, the part in brackets is
+         * an IPv6 address, which must be followed by a colon and a port
+         * number. If token does not start with bracket, the part before
+         * the colon will be used as either address of hostname. */
+       if (token[0] == '[') {
+            /* [IPv6 addr]:port */
+            if ((t = strchr(token, ']')) && *(t + 1) == ':') {
+                /* copy IPv6 address to host */
+                *t = '\0';
+                host = xstrdup(&token[1]);
+                /* t + 1 and t + 2 should be safe since if ']' is not in
+                 * the string (t + 1) is not evaluated, if it is the last
+                 * character in the string *(t + 1) == '\0' in the worse
+                 * case which does not evaluate (t + 2). If (t + 1) != '\0'
+                 * *(t + 2) would be '\0' in the worse case which is an
+                 * empty string. */
+                port = (unsigned short) atoi(t + 2);
+               if (0 == port) {
+                    xfree(host);
+                   self_destruct();
+                }
+            }
+            else
+                self_destruct();
+        }
+        else if ((t = strchr(token, ':'))) {
            /* host:port */
-           host = token;
            *t = '\0';
+           host = xstrdup(token);
            port = (unsigned short) atoi(t + 1);
            if (0 == port)
+            {
+                xfree(host);
                self_destruct();
+            }
        } else if ((port = atoi(token)) > 0) {
            /* port */
        } else {
            self_destruct();
        }
-       s = xcalloc(1, sizeof(*s));
-       PORT_FROM_SA(s->s) = htons(port);
-       if (NULL == host)
-           ADDR_FROM_SA(s->s) = INADDR_ANY_ASSIGN;
-       else if (1 == SAFE_INET_ADDR(host, &ADDR_FROM_SA(s->s)))
-           (void) 0;
-       else if ((hp = GETHOSTBYNAME(host)))    /* dont use ipcache */
-         ADDR_FROM_SA(s->s) = inaddrFromHostent(hp);
-       else
-           self_destruct();
-       while (*head)
-           head = &(*head)->next;
-       *head = s;
+        
+       if (NULL == host) {
+            /* only port was specified, so listen on any local address */
+            sockaddr_in_list* sa_li;
+           sa_li = xcalloc(1, sizeof(sockaddr_in_list));
+           PORT_FROM_SA(sa_li->s) = htons(port);
+           ADDR_FROM_SA(sa_li->s) = INADDR_ANY_ASSIGN;
+           /* append to list */
+            while (*head)
+               head = &(*head)->next;
+           *head = sa_li;
+        }
+       else {
+            /* host is either IPv4/IPv6 address or hostname */
+            struct IN_ADDR addr;
+            
+            /* try IP address */
+            if (1 == SAFE_INET_ADDR(host, &addr)) {
+                /* ok host was an IPv4 or IPv6 address set the port and
+                 * done*/
+                sockaddr_in_list* sa_li;
+                sa_li = xcalloc(1, sizeof(sockaddr_in_list));
+                
+                ADDR_FROM_SA(sa_li->s) = addr;
+                PORT_FROM_SA(sa_li->s) = htons(port);
+               
+                /* append to list */
+                while (*head)
+                   head = &(*head)->next;
+               *head = sa_li;
+            }
+            /* no IP address so it should be hostname */
+           /* make an list entry for each address that was found */
+            else 
+            {
+                int ret = 0;
+                ret += get_address_list(host, port, head, AF_INET6);
+                ret += get_address_list(host, port, head, AF_INET);
+                if(!ret)
+                {
+                    xfree(host);
+                   self_destruct();
+                }
+            }
+            xfree(host);
+        }
     }
 }
 
diff -urNad /home/racon/squid/squid_2.5.3ipv6.20030616-4/src/cf.data.pre 
squid_2.5.3ipv6.20030616-4/src/cf.data.pre
--- /home/racon/squid/squid_2.5.3ipv6.20030616-4/src/cf.data.pre        2003-06-22 
23:04:57.000000000 -0300
+++ squid_2.5.3ipv6.20030616-4/src/cf.data.pre  2003-06-22 23:04:57.000000000 -0300
@@ -62,15 +62,22 @@
        Usage:  port
                hostname:port
                1.2.3.4:port
+               [aaaa:bbbb:ccc:1::abcd]:port
+               [::ffff:1.2.3.4]:port
 
        The socket addresses where Squid will listen for HTTP client
-       requests.  You may specify multiple socket addresses.
-       There are three forms: port alone, hostname with port, and
-       IP address with port.  If you specify a hostname or IP
-       address, then Squid binds the socket to that specific
-       address.  This replaces the old 'tcp_incoming_address'
-       option.  Most likely, you do not need to bind to a specific
-       address, so you can use the port number alone.
+       requests. You may specify multiple socket addresses.
+       There are four forms: port alone, hostname with port, IPv4 
+       style address with port and IPv6 style address with port. The 
+       IPv6 style address must appear in brackets as suggested in RFC 2732. 
+       If you specify an IP address, then Squid binds the socket to that
+       specific address. You can also specify IPv6 mapped IPv4 addresses.
+       If you specify a hostname Squid tries to bind to all addresses 
+       associated with this hostname. Therefor Squid will query for AAAA
+       as well as for A records. 
+       This option replaces the old 'tcp_incoming_address' option. Most
+       likely, you do not need to bind to a specific address, so you can
+       use the port number alone.
 
        The default port number is 3128.
 

Reply via email to