--------------------- PatchSet 6418 Date: 2005/02/10 01:14:40 Author: hno Branch: ipv6 Tag: ipv6-2001-11-22 Log: From: Oliver Baltzer Date: Mon, 23 Jun 2003 00:02:59 -0300 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 Members: src/cache_cf.c:1.4.2.8->1.4.2.9 src/cf.data.pre:1.4.6.4->1.4.6.5 Index: squid/src/cache_cf.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cache_cf.c,v retrieving revision 1.4.2.8 retrieving revision 1.4.2.9 diff -u -r1.4.2.8 -r1.4.2.9 --- squid/src/cache_cf.c 30 Oct 2001 09:01:26 -0000 1.4.2.8 +++ squid/src/cache_cf.c 10 Feb 2005 01:14:40 -0000 1.4.2.9 @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.c,v 1.4.2.8 2001/10/30 09:01:26 rvenning Exp $ + * $Id: cache_cf.c,v 1.4.2.9 2005/02/10 01:14:40 hno Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -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); + } } } Index: squid/src/cf.data.pre =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v retrieving revision 1.4.6.4 retrieving revision 1.4.6.5 diff -u -r1.4.6.4 -r1.4.6.5 --- squid/src/cf.data.pre 25 Oct 2001 18:24:54 -0000 1.4.6.4 +++ squid/src/cf.data.pre 10 Feb 2005 01:14:43 -0000 1.4.6.5 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.4.6.4 2001/10/25 18:24:54 hno Exp $ +# $Id: cf.data.pre,v 1.4.6.5 2005/02/10 01:14:43 hno Exp $ # # # SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -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.