Index: include/rfc1035.h =================================================================== RCS file: /cvsroot/squid/squid/include/rfc1035.h,v retrieving revision 1.10 diff -u -I\$Id -r1.10 rfc1035.h --- include/rfc1035.h 28 Apr 2006 10:17:18 -0000 1.10 +++ include/rfc1035.h 5 Jul 2008 09:37:35 -0000 @@ -38,6 +38,9 @@ #if HAVE_SYS_TYPES_H #include #endif +#if HAVE_SYS_SOCKET_H +#include +#endif #if HAVE_NETINET_IN_H #include #endif @@ -71,6 +74,7 @@ unsigned int tc:1; unsigned int rd:1; unsigned int ra:1; + unsigned int z:3; unsigned int rcode:4; unsigned short qdcount; unsigned short ancount; @@ -85,7 +89,12 @@ size_t sz, unsigned short qid, rfc1035_query * query); -extern ssize_t rfc1035BuildPTRQuery(const struct in_addr, +extern ssize_t rfc1035BuildAAAAQuery(const char *hostname, + char *buf, + size_t sz, + unsigned short qid, + rfc1035_query * query); +extern ssize_t rfc1035BuildPTRQuery(const struct sockaddr *, char *buf, size_t sz, unsigned short qid, @@ -100,6 +109,7 @@ extern const char *rfc1035_error_message; #define RFC1035_TYPE_A 1 +#define RFC1035_TYPE_AAAA 28 #define RFC1035_TYPE_CNAME 5 #define RFC1035_TYPE_PTR 12 #define RFC1035_CLASS_IN 1 Index: include/util.h =================================================================== RCS file: /cvsroot/squid/squid/include/util.h,v retrieving revision 1.69 diff -u -I\$Id -r1.69 util.h --- include/util.h 10 Dec 2006 13:36:23 -0000 1.69 +++ include/util.h 5 Jul 2008 09:37:35 -0000 @@ -104,7 +104,7 @@ extern void xmalloc_find_leaks(void); #endif -typedef struct in_addr SIA; +typedef struct sockaddr SIA; extern int safe_inet_addr(const char *, SIA *); extern time_t parse_iso3307_time(const char *buf); extern char *base64_decode(const char *coded); Index: lib/rfc1035.c =================================================================== RCS file: /cvsroot/squid/squid/lib/rfc1035.c,v retrieving revision 1.29 diff -u -I\$Id -r1.29 rfc1035.c --- lib/rfc1035.c 17 May 2005 16:56:36 -0000 1.29 +++ lib/rfc1035.c 5 Jul 2008 09:37:35 -0000 @@ -644,7 +644,7 @@ h.qr = 0; h.rd = 1; h.opcode = 0; /* QUERY */ - h.qdcount = (unsigned int) 1; + h.qdcount = 1; offset += rfc1035HeaderPack(buf + offset, sz - offset, &h); offset += rfc1035QuestionPack(buf + offset, sz - offset, @@ -660,6 +660,32 @@ return offset; } +ssize_t +rfc1035BuildAAAAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query) +{ + static rfc1035_message h; + size_t offset = 0; + memset(&h, '\0', sizeof(h)); + h.id = qid; + h.qr = 0; + h.rd = 1; + h.opcode = 0; /* QUERY */ + h.qdcount = 1; + offset += rfc1035HeaderPack(buf + offset, sz - offset, &h); + offset += rfc1035QuestionPack(buf + offset, + sz - offset, + hostname, + RFC1035_TYPE_AAAA, + RFC1035_CLASS_IN); + if (query) { + query->qtype = RFC1035_TYPE_AAAA; + query->qclass = RFC1035_CLASS_IN; + xstrncpy(query->name, hostname, sizeof(query->name)); + } + assert(offset <= sz); + return offset; +} + /* * rfc1035BuildPTRQuery() * @@ -671,19 +697,45 @@ * Returns the size of the query */ ssize_t -rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query) +rfc1035BuildPTRQuery(const struct sockaddr *addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query) { static rfc1035_message h; size_t offset = 0; - static char rev[32]; + static char rev[100]; unsigned int i; memset(&h, '\0', sizeof(h)); - i = (unsigned int) ntohl(addr.s_addr); + memset(rev, '\0', sizeof(rev)); + if (addr->sa_family == AF_INET) { + i = (unsigned int) ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); snprintf(rev, 32, "%u.%u.%u.%u.in-addr.arpa.", i & 255, (i >> 8) & 255, (i >> 16) & 255, (i >> 24) & 255); + } + if (addr->sa_family == AF_INET6) { + char temp[16]; + int sx, ex; + u_int8_t ci; +#if BYTE_ORDER == BIG_ENDIAN + sx = 0; +#elif BYTE_ORDER == LITTLE_ENDIAN + sx = 15; +#endif + for (i = 0; i < 16; i++) { + ci = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr[sx]; + memset(temp, '\0', sizeof(temp)); + sprintf(temp, "%x.%x", ci & 0xf, ci & 0xf0); + strcat(rev, temp); +#if BYTE_ORDER == BIG_ENDIAN + sx++; +#elif BYTE_ORDER == LITTLE_ENDIAN + sx--; +#endif + + } + strcat(rev, ".ip6.arpa"); + } h.id = qid; h.qr = 0; h.rd = 1; Index: lib/safe_inet_addr.c =================================================================== RCS file: /cvsroot/squid/squid/lib/safe_inet_addr.c,v retrieving revision 1.12 diff -u -I\$Id -r1.12 safe_inet_addr.c --- lib/safe_inet_addr.c 7 Feb 2001 18:56:51 -0000 1.12 +++ lib/safe_inet_addr.c 5 Jul 2008 09:37:35 -0000 @@ -24,6 +24,9 @@ #if HAVE_NETINET_IN_H #include #endif +#if HAVE_NETDB_H +#include +#endif #if HAVE_ARPA_INET_H #include #endif @@ -31,36 +34,18 @@ #include "snprintf.h" int -safe_inet_addr(const char *buf, struct in_addr *addr) +safe_inet_addr(const char *buf, struct sockaddr *addr) { - static char addrbuf[32]; - int a1 = 0, a2 = 0, a3 = 0, a4 = 0; - struct in_addr A; - char x; -#if defined(_SQUID_HPUX_) - /* - * MIYOSHI Tsutomu says scanning 'buf' - * causes a bus error on hppa1.1-hp-hpux9.07, so we - * have a broad hack for all HP systems. - */ - static char buftmp[32]; - snprintf(buftmp, 32, "%s", buf); - if (sscanf(buftmp, "%d.%d.%d.%d%c", &a1, &a2, &a3, &a4, &x) != 4) -#else - if (sscanf(buf, "%d.%d.%d.%d%c", &a1, &a2, &a3, &a4, &x) != 4) -#endif - return 0; - if (a1 < 0 || a1 > 255) - return 0; - if (a2 < 0 || a2 > 255) - return 0; - if (a3 < 0 || a3 > 255) - return 0; - if (a4 < 0 || a4 > 255) - return 0; - snprintf(addrbuf, 32, "%d.%d.%d.%d", a1, a2, a3, a4); - A.s_addr = inet_addr(addrbuf); - if (addr) - addr->s_addr = A.s_addr; + struct addrinfo hints, *res; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE; + hints.ai_family = PF_UNSPEC; + error = getaddrinfo(buf, NULL, &hints, &res); + if (error) return 0; + xmemcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); return 1; + } Index: src/HttpRequest.c =================================================================== RCS file: /cvsroot/squid/squid/src/HttpRequest.c,v retrieving revision 1.41 diff -u -I\$Id -r1.41 HttpRequest.c --- src/HttpRequest.c 17 Jul 2006 02:31:59 -0000 1.41 +++ src/HttpRequest.c 5 Jul 2008 09:37:35 -0000 @@ -45,8 +45,8 @@ stringReset(&req->urlpath, urlpath); req->max_forwards = -1; req->lastmod = -1; - req->client_addr = no_addr; - req->my_addr = no_addr; + memset(&req->client_addr, 0, sizeof(req->client_addr)); + memset(&req->my_addr, 0, sizeof(req->client_addr)); httpHeaderInit(&req->header, hoRequest); return req; } @@ -135,8 +135,8 @@ { assert(req && p); /* Client info */ - packerPrintf(p, "Client: %s ", inet_ntoa(req->client_addr)); - packerPrintf(p, "http_port: %s:%d", inet_ntoa(req->my_addr), req->my_port); + packerPrintf(p, "Client: %s ", sockaddr_ntoa(&req->client_addr)); + packerPrintf(p, "http_port: %s:%d", sockaddr_ntoa(&req->my_addr), req->my_port); if (req->auth_user_request && authenticateUserRequestUsername(req->auth_user_request)) packerPrintf(p, "user: %s", authenticateUserRequestUsername(req->auth_user_request)); packerPrintf(p, "\n"); Index: src/access_log.c =================================================================== RCS file: /cvsroot/squid/squid/src/access_log.c,v retrieving revision 1.95.2.1 diff -u -I\$Id -r1.95.2.1 access_log.c --- src/access_log.c 3 Feb 2007 21:59:24 -0000 1.95.2.1 +++ src/access_log.c 5 Jul 2008 09:37:35 -0000 @@ -445,6 +445,7 @@ long int outint = 0; int doint = 0; int dofree = 0; + char caddr[80]; switch (fmt->type) { case LFT_NONE: out = ""; @@ -453,13 +454,18 @@ out = fmt->data.string; break; case LFT_CLIENT_IP_ADDRESS: - out = inet_ntoa(al->cache.caddr); + getnameinfo(&al->cache.caddr, SOCKLEN(&al->cache.caddr), caddr, 80, + (char *)NULL, 0, NI_NUMERICHOST); + out = caddr; break; case LFT_CLIENT_FQDN: - out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); - if (!out) - out = inet_ntoa(al->cache.caddr); + out = fqdncache_gethostbyaddr((struct sockaddr *)&al->cache.caddr, FQDN_LOOKUP_IF_MISS); + if (!out) { + getnameinfo(&al->cache.caddr, SOCKLEN(&al->cache.caddr), caddr, 80, + (char *)NULL, 0, NI_NUMERICHOST); + out = caddr; + } break; case LFT_CLIENT_PORT: @@ -478,8 +484,12 @@ /* case LFT_SERVER_PORT: */ case LFT_LOCAL_IP: - if (al->request) - out = inet_ntoa(al->request->my_addr); + if (al->request) { + getnameinfo(&al->request->my_addr, + SOCKLEN(&al->request->my_addr), + caddr, 80, (char *)NULL, 0, NI_NUMERICHOST); + out = caddr; + } break; case LFT_LOCAL_PORT: @@ -1008,10 +1018,14 @@ { const char *client = NULL; const char *user = NULL; + char caddr[80]; if (Config.onoff.log_fqdn) - client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); - if (client == NULL) - client = inet_ntoa(al->cache.caddr); + client = fqdncache_gethostbyaddr((struct sockaddr *)&al->cache.caddr, FQDN_LOOKUP_IF_MISS); + if (client == NULL) { + getnameinfo(&al->cache.caddr, SOCKLEN(&al->cache.caddr), caddr, 80, + (char *)NULL, 0, NI_NUMERICHOST); + client = caddr; + } user = accessLogFormatName(al->cache.authuser); if (!user) user = accessLogFormatName(al->cache.rfc931); @@ -1068,10 +1082,14 @@ { const char *client = NULL; char *user1 = NULL, *user2 = NULL; + char caddr[80]; if (Config.onoff.log_fqdn) - client = fqdncache_gethostbyaddr(al->cache.caddr, 0); - if (client == NULL) - client = inet_ntoa(al->cache.caddr); + client = fqdncache_gethostbyaddr(&al->cache.caddr, FQDN_LOOKUP_IF_MISS); + if (client == NULL) { + getnameinfo(&al->cache.caddr, SOCKLEN(&al->cache.caddr), caddr, 80, + (char *)NULL, 0, NI_NUMERICHOST); + client = caddr; + } user1 = accessLogFormatName(al->cache.authuser); user2 = accessLogFormatName(al->cache.rfc931); logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %" PRINTF_OFF_T " %s:%s", Index: src/acl.c =================================================================== RCS file: /cvsroot/squid/squid/src/acl.c,v retrieving revision 1.318 diff -u -I\$Id -r1.318 acl.c --- src/acl.c 6 Jan 2007 17:22:45 -0000 1.318 +++ src/acl.c 5 Jul 2008 09:37:35 -0000 @@ -53,18 +53,18 @@ static int aclMatchAcl(struct _acl *, aclCheck_t *); static int aclMatchTime(acl_time_data * data, time_t when); static int aclMatchUser(void *proxyauth_acl, char *user); -static int aclMatchIp(void *dataptr, struct in_addr c); +static int aclMatchIp(void *dataptr, struct sockaddr *c); static int aclMatchDomainList(void *dataptr, const char *); static int aclMatchIntegerRange(intrange * data, int i); static int aclMatchWordList(wordlist *, const char *); static void aclParseUserMaxIP(void *data); static void aclDestroyUserMaxIP(void *data); static wordlist *aclDumpUserMaxIP(void *data); -static int aclMatchUserMaxIP(void *, auth_user_request_t *, struct in_addr); +static int aclMatchUserMaxIP(void *, auth_user_request_t *, struct sockaddr *); static void aclParseHeader(void *data); static void aclDestroyHeader(void *data); static squid_acl aclStrToType(const char *s); -static int decode_addr(const char *, struct in_addr *); +static int decode_addr(const char *, struct sockaddr *); static void aclCheck(aclCheck_t * checklist); static void aclCheckCallback(aclCheck_t * checklist, allow_t answer); #if USE_IDENT @@ -431,35 +431,31 @@ * This function should NOT be called if 'asc' is a hostname! */ static int -decode_addr(const char *asc, struct in_addr *addr) +decode_addr(const char *asc, struct sockaddr *addr) { - int a1 = 0, a2 = 0, a3 = 0, a4 = 0; + struct addrinfo hints, *res; + int error; - switch (sscanf(asc, "%d.%d.%d.%d", &a1, &a2, &a3, &a4)) { - case 4: /* a dotted quad */ - if (!safe_inet_addr(asc, addr)) { - debug(28, 0) ("decode_addr: unsafe IP address: '%s'\n", asc); - self_destruct(); - } - break; - case 1: /* a significant bits value for a mask */ - if (a1 >= 0 && a1 < 33) { - addr->s_addr = a1 ? htonl(0xfffffffful << (32 - a1)) : 0; - break; - } - default: + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE; + + error = getaddrinfo(asc, NULL, &hints, &res); + if (error) { debug(28, 0) ("decode_addr: Invalid IP address '%s'\n", asc); return 0; /* This is not valid address */ } + xmemcpy(addr, res->ai_addr, SOCKLEN(res->ai_addr)); + freeaddrinfo(res); return 1; } -#define SCAN_ACL1 "%[0123456789.]-%[0123456789.]/%[0123456789.]" -#define SCAN_ACL2 "%[0123456789.]-%[0123456789.]%c" -#define SCAN_ACL3 "%[0123456789.]/%[0123456789.]" -#define SCAN_ACL4 "%[0123456789.]%c" +#define SCAN_ACL1 "%[0123456789abcdef:.]-%[0123456789abcdef:.]/%[0123456789]" +#define SCAN_ACL2 "%[0123456789abcdef:.]-%[0123456789abcdef:.]%c" +#define SCAN_ACL3 "%[0123456789abcdef:.]/%[0123456789]" +#define SCAN_ACL4 "%[0123456789abcdef:.]%c" static acl_ip_data * aclParseIpData(const char *t) @@ -468,19 +464,14 @@ LOCAL_ARRAY(char, addr2, 256); LOCAL_ARRAY(char, mask, 256); acl_ip_data *q = memAllocate(MEM_ACL_IP_DATA); - acl_ip_data *r; - acl_ip_data **Q; - struct hostent *hp; - char **x; char c; debug(28, 5) ("aclParseIpData: %s\n", t); if (!strcasecmp(t, "all")) { - q->addr1.s_addr = 0; - q->addr2.s_addr = 0; - q->mask.s_addr = 0; + q->addr1.ss_family = 0; + q->addr2.ss_family = 0; + q->masklen = 0; return q; } - q->mask.s_addr = no_addr.s_addr; /* 255.255.255.255 */ if (sscanf(t, SCAN_ACL1, addr1, addr2, mask) == 3) { (void) 0; } else if (sscanf(t, SCAN_ACL2, addr1, addr2, &c) == 2) { @@ -489,29 +480,21 @@ addr2[0] = '\0'; } else if (sscanf(t, SCAN_ACL4, addr1, &c) == 1) { addr2[0] = '\0'; - mask[0] = '\0'; + strcpy(mask, "-1"); } else if (sscanf(t, "%[^/]/%s", addr1, mask) == 2) { addr2[0] = '\0'; } else if (sscanf(t, "%s", addr1) == 1) { - /* - * Note, must use plain gethostbyname() here because at startup - * ipcache hasn't been initialized - */ - if ((hp = gethostbyname(addr1)) == NULL) { + struct addrinfo hints, *res; + memset(&hints, '\0', sizeof(hints)); + hints.ai_family = PF_UNSPEC; + if (getaddrinfo(t, NULL, &hints, &res)) { debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); safe_free(q); return NULL; } - Q = &q; - for (x = hp->h_addr_list; x != NULL && *x != NULL; x++) { - if ((r = *Q) == NULL) - r = *Q = memAllocate(MEM_ACL_IP_DATA); - xmemcpy(&r->addr1.s_addr, *x, sizeof(r->addr1.s_addr)); - r->addr2.s_addr = 0; - r->mask.s_addr = no_addr.s_addr; /* 255.255.255.255 */ - Q = &r->next; - debug(28, 3) ("%s --> %s\n", addr1, inet_ntoa(r->addr1)); - } + xmemcpy(&q->addr1, res->ai_addr, res->ai_addrlen); + q->masklen = (res->ai_family == AF_INET6) ? 128 : 32; + freeaddrinfo(res); return q; } else { debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); @@ -519,7 +502,7 @@ return NULL; } /* Decode addr1 */ - if (!decode_addr(addr1, &q->addr1)) { + if (!decode_addr(addr1, (struct sockaddr *)&q->addr1)) { debug(28, 0) ("%s line %d: %s\n", cfg_filename, config_lineno, config_input_line); debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown first address '%s'\n", addr1); @@ -527,7 +510,7 @@ return NULL; } /* Decode addr2 */ - if (*addr2 && !decode_addr(addr2, &q->addr2)) { + if (*addr2 && !decode_addr(addr2, (struct sockaddr *)&q->addr2)) { debug(28, 0) ("%s line %d: %s\n", cfg_filename, config_lineno, config_input_line); debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown second address '%s'\n", addr2); @@ -535,19 +518,30 @@ return NULL; } /* Decode mask */ - if (*mask && !decode_addr(mask, &q->mask)) { - debug(28, 0) ("%s line %d: %s\n", + if (*mask) { + q->masklen = atoi(mask); + switch (q->addr1.ss_family) { + case AF_INET: + if (q->masklen == -1) + q->masklen = 32; + if (q->masklen > 32) + q->masklen = -1; + break; + case AF_INET6: + if (q->masklen == -1) + q->masklen = 128; + if (q->masklen > 128) + q->masklen = -1; + break; + } + if (*mask && (q->masklen == -1)) { + debug(28, 0) ("%s line %d: %s\n", cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown netmask '%s'\n", mask); - safe_free(q); - return NULL; + debug(28, 0) ("aclParseIpData: Ignoring invalid IP acl entry: unknown masklen'%s'\n", mask); + safe_free(q); + return NULL; + } } - if ((q->addr1.s_addr & q->mask.s_addr) != q->addr1.s_addr || - (q->addr2.s_addr & q->mask.s_addr) != q->addr2.s_addr) - debug(28, 0) ("aclParseIpData: WARNING: Netmask masks away part of the specified IP in '%s'\n", t); - q->addr1.s_addr &= q->mask.s_addr; - q->addr2.s_addr &= q->mask.s_addr; - /* 1.2.3.4/255.255.255.0 --> 1.2.3.0 */ return q; } @@ -1295,7 +1289,7 @@ /**************/ static int -aclMatchIp(void *dataptr, struct in_addr c) +aclMatchIp(void *dataptr, struct sockaddr *c) { splayNode **Top = dataptr; acl_ip_data x; @@ -1308,13 +1302,12 @@ * XXX Could eliminate these repetitive assignments with a * static structure. */ - x.addr1 = c; - x.addr2 = any_addr; - x.mask = no_addr; + xmemcpy(&x.addr1, c, SOCKLEN(c)); + x.masklen = 0; x.next = NULL; *Top = splay_splay(&x, *Top, aclIpAddrNetworkCompare); debug(28, 3) ("aclMatchIp: '%s' %s\n", - inet_ntoa(c), splayLastResult ? "NOT found" : "found"); + sockaddr_ntoa(c), splayLastResult ? "NOT found" : "found"); return !splayLastResult; } @@ -1549,7 +1542,7 @@ */ int aclMatchUserMaxIP(void *data, auth_user_request_t * auth_user_request, - struct in_addr src_addr) + struct sockaddr *src_addr) { /* * the logic for flush the ip list when the limit is hit vs keep @@ -1714,7 +1707,7 @@ } /* get authed here */ /* Note: this fills in checklist->auth_user_request when applicable (auth incomplete) */ - switch (authenticateTryToAuthenticateAndSetAuthUser(&checklist->auth_user_request, headertype, checklist->request, checklist->conn, checklist->src_addr)) { + switch (authenticateTryToAuthenticateAndSetAuthUser(&checklist->auth_user_request, headertype, checklist->request, checklist->conn, &checklist->src_addr)) { case AUTH_ACL_CANNOT_AUTHENTICATE: debug(28, 4) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n"); return 0; @@ -1785,16 +1778,16 @@ debug(28, 3) ("aclMatchAcl: checking '%s'\n", ae->cfgline); switch (ae->type) { case ACL_SRC_IP: - return aclMatchIp(&ae->data, checklist->src_addr); + return aclMatchIp(&ae->data, (struct sockaddr *)&checklist->src_addr); /* NOTREACHED */ case ACL_MY_IP: - return aclMatchIp(&ae->data, checklist->my_addr); + return aclMatchIp(&ae->data, (struct sockaddr *)&checklist->my_addr); /* NOTREACHED */ case ACL_DST_IP: ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); if (ia) { for (k = 0; k < (int) ia->count; k++) { - if (aclMatchIp(&ae->data, ia->in_addrs[k])) + if (aclMatchIp(&ae->data, (struct sockaddr *)&ia->in_addrs[k])) return 1; } return 0; @@ -1812,24 +1805,24 @@ return 1; if ((ia = ipcacheCheckNumeric(r->host)) == NULL) return 0; - fqdn = fqdncache_gethostbyaddr(ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); + fqdn = fqdncache_gethostbyaddr((struct sockaddr *)&ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); if (fqdn) return aclMatchDomainList(&ae->data, fqdn); if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - ae->name, inet_ntoa(ia->in_addrs[0])); + ae->name, sockaddr_ntoa(&ia->in_addrs[0])); checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } return aclMatchDomainList(&ae->data, "none"); /* NOTREACHED */ case ACL_SRC_DOMAIN: - fqdn = fqdncache_gethostbyaddr(checklist->src_addr, FQDN_LOOKUP_IF_MISS); + fqdn = fqdncache_gethostbyaddr((struct sockaddr *)&checklist->src_addr, FQDN_LOOKUP_IF_MISS); if (fqdn) { return aclMatchDomainList(&ae->data, fqdn); } else if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - ae->name, inet_ntoa(checklist->src_addr)); + ae->name, ""); /*XXX inet_ntoa(checklist->src_addr)); */ checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } @@ -1840,24 +1833,24 @@ return 1; if ((ia = ipcacheCheckNumeric(r->host)) == NULL) return 0; - fqdn = fqdncache_gethostbyaddr(ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); + fqdn = fqdncache_gethostbyaddr((struct sockaddr *)&ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); if (fqdn) return aclMatchRegex(ae->data, fqdn); if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - ae->name, inet_ntoa(ia->in_addrs[0])); + ae->name, sockaddr_ntoa(&ia->in_addrs[0])); checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } return aclMatchRegex(ae->data, "none"); /* NOTREACHED */ case ACL_SRC_DOM_REGEX: - fqdn = fqdncache_gethostbyaddr(checklist->src_addr, FQDN_LOOKUP_IF_MISS); + fqdn = fqdncache_gethostbyaddr((struct sockaddr *)&checklist->src_addr, FQDN_LOOKUP_IF_MISS); if (fqdn) { return aclMatchRegex(ae->data, fqdn); } else if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", - ae->name, inet_ntoa(checklist->src_addr)); + ae->name, sockaddr_ntoa(&checklist->src_addr)); checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } @@ -1887,7 +1880,7 @@ return k; /* NOTREACHED */ case ACL_MAXCONN: - k = clientdbEstablished(checklist->src_addr, 0); + k = clientdbEstablished((struct sockaddr *)&checklist->src_addr, 0); return ((k > ((intlist *) ae->data)->i) ? 1 : 0); /* NOTREACHED */ case ACL_URL_PORT: @@ -1950,7 +1943,7 @@ if ((ti = aclAuthenticated(checklist)) != 1) return ti; ti = aclMatchUserMaxIP(ae->data, r->auth_user_request, - checklist->src_addr); + (struct sockaddr *)&checklist->src_addr); return ti; /* NOTREACHED */ #if SQUID_SNMP @@ -1959,13 +1952,13 @@ /* NOTREACHED */ #endif case ACL_SRC_ASN: - return asnMatchIp(ae->data, checklist->src_addr); + return asnMatchIp(ae->data, &checklist->src_addr); /* NOTREACHED */ case ACL_DST_ASN: ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); if (ia) { for (k = 0; k < (int) ia->count; k++) { - if (asnMatchIp(ae->data, ia->in_addrs[k])) + if (asnMatchIp(ae->data, &ia->in_addrs[k])) return 1; } return 0; @@ -1974,7 +1967,7 @@ ae->name, r->host); checklist->state[ACL_DST_ASN] = ACL_LOOKUP_NEEDED; } else { - return asnMatchIp(ae->data, no_addr); + return asnMatchIp(ae->data, &no_addr); } return 0; /* NOTREACHED */ @@ -2166,7 +2159,7 @@ return; } else if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NEEDED) { checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_PENDING; - fqdncache_nbgethostbyaddr(checklist->src_addr, + fqdncache_nbgethostbyaddr((struct sockaddr *)&checklist->src_addr, aclLookupSrcFQDNDone, checklist); return; } else if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_NEEDED) { @@ -2177,7 +2170,7 @@ } checklist->dst_addr = ia->in_addrs[0]; checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_PENDING; - fqdncache_nbgethostbyaddr(checklist->dst_addr, + fqdncache_nbgethostbyaddr((struct sockaddr *)&checklist->dst_addr, aclLookupDstFQDNDone, checklist); return; } else if (checklist->state[ACL_PROXY_AUTH] == ACL_LOOKUP_NEEDED) { @@ -2199,7 +2192,7 @@ else if (checklist->state[ACL_IDENT] == ACL_LOOKUP_NEEDED) { debug(28, 3) ("aclCheck: Doing ident lookup\n"); if (cbdataValid(checklist->conn)) { - identStart(&checklist->conn->me, &checklist->conn->peer, + identStart((struct sockaddr *)&checklist->conn->me, (struct sockaddr *)&checklist->conn->peer, aclLookupIdentDone, checklist); checklist->state[ACL_IDENT] = ACL_LOOKUP_PENDING; return; @@ -2382,11 +2375,11 @@ checklist->request = requestLink(request); #if FOLLOW_X_FORWARDED_FOR if (Config.onoff.acl_uses_indirect_client) { - checklist->src_addr = request->indirect_client_addr; + xmemcpy(&checklist->src_addr, &request->indirect_client_addr, sizeof(struct sockaddr_storage)); } else #endif /* FOLLOW_X_FORWARDED_FOR */ - checklist->src_addr = request->client_addr; - checklist->my_addr = request->my_addr; + xmemcpy(&checklist->src_addr, &request->client_addr, sizeof(struct sockaddr_storage)); + xmemcpy(&checklist->my_addr, &request->my_addr, sizeof(struct sockaddr_storage)); checklist->my_port = request->my_port; } for (i = 0; i < ACL_ENUM_MAX; i++) @@ -2665,19 +2658,7 @@ static void aclIpDataToStr(const acl_ip_data * ip, char *buf, int len) { - char b1[20]; - char b2[20]; - char b3[20]; - snprintf(b1, 20, "%s", inet_ntoa(ip->addr1)); - if (ip->addr2.s_addr != any_addr.s_addr) - snprintf(b2, 20, "-%s", inet_ntoa(ip->addr2)); - else - b2[0] = '\0'; - if (ip->mask.s_addr != no_addr.s_addr) - snprintf(b3, 20, "/%s", inet_ntoa(ip->mask)); - else - b3[0] = '\0'; - snprintf(buf, len, "%s%s%s", b1, b2, b3); + sprintf(buf, len, "%s/%d", sockaddr_ntoa(&ip->addr1), ip->masklen); } /* @@ -2690,27 +2671,77 @@ static int aclIpNetworkCompare2(const acl_ip_data * p, const acl_ip_data * q) { - struct in_addr A = p->addr1; - const struct in_addr B = q->addr1; - const struct in_addr C = q->addr2; - int rc = 0; - A.s_addr &= q->mask.s_addr; /* apply netmask */ - if (C.s_addr == 0) { /* single address check */ - if (ntohl(A.s_addr) > ntohl(B.s_addr)) - rc = 1; - else if (ntohl(A.s_addr) < ntohl(B.s_addr)) - rc = -1; - else - rc = 0; - } else { /* range address check */ - if (ntohl(A.s_addr) > ntohl(C.s_addr)) - rc = 1; - else if (ntohl(A.s_addr) < ntohl(B.s_addr)) - rc = -1; + if (q->addr1.ss_family < p->addr1.ss_family) + return -1; + else + if (q->addr1.ss_family > p->addr1.ss_family) + return 1; + else + if (q->addr1.ss_family == AF_INET) { + u_int32_t maskedup_B; + u_int32_t A = ntohl(((struct sockaddr_in *)&p->addr1)->sin_addr.s_addr); + u_int32_t B = ntohl(((struct sockaddr_in *)&q->addr1)->sin_addr.s_addr); + + if (q->masklen == 0) + return 0; + + maskedup_B = ((B >> (32 - q->masklen)) + 1) << (32 - q->masklen); + maskedup_B--; + + if (A < B) + return -1; + else if (A > maskedup_B) + return 1; else - rc = 0; + return 0; } - return rc; + else + if (q->addr1.ss_family == AF_INET6) { + + int masklen, invmasklen, i, rc; + struct in6_addr A, B; + + if (q->masklen == 0) + return 0; + + xmemcpy(&A, &((struct sockaddr_in6 *)&p->addr1)->sin6_addr, sizeof(struct in6_addr)); + xmemcpy(&B, &((struct sockaddr_in6 *)&q->addr1)->sin6_addr, sizeof(struct in6_addr)); + + invmasklen = 128 - q->masklen; + masklen = q->masklen; + + rc = 0; + for (i = 0; i < 16; i=i+4) { + if (masklen >= 32) { + if (IN6_NTOHL_N(&A, i) < IN6_NTOHL_N(&B, i)) + return -1; + else + if (IN6_NTOHL_N(&A, i) > IN6_NTOHL_N(&B, i)) + return 1; + else + masklen = masklen - 32; + } + else if (masklen > 0) { + invmasklen = 32 - masklen; + debug(28, 3) ("aclIpNetworkCompare2: %s vs %s,\n", + sockaddr_ntoa(&p->addr1), sockaddr_ntoa(&q->addr1)); + debug(28, 3) ("aclIpNetworkCompare2: %x/%d (%x) vs %x\n", + IN6_NTOHL_N(&A, i), masklen, + IN6_NTOHL_N(&A, i) & (0xffffffff << invmasklen), + IN6_NTOHL_N(&B, i)); + if (IN6_NTOHL_N(&A, i) < IN6_NTOHL_N(&B, i)) + return -1; + else + if ((IN6_NTOHL_N(&A, i) & (0xffffffff << invmasklen)) > IN6_NTOHL_N(&B, i)) + return 1; + else + return 0; + } + } + } + else + return 0; + return 0; } /* @@ -2734,16 +2765,14 @@ ret = aclIpNetworkCompare2(n1, n2); } if (ret == 0) { - char buf_n1[60]; - char buf_n2[60]; - char buf_a[60]; - aclIpDataToStr(n1, buf_n1, 60); - aclIpDataToStr(n2, buf_n2, 60); - aclIpDataToStr((acl_ip_data *) a, buf_a, 60); + char buf_n1[100]; + char buf_n2[100]; + getnameinfo(&n1->addr1, SOCKLEN(&n1->addr1), &buf_n1, 100, NULL, 0, NI_NUMERICHOST); + getnameinfo(&n2->addr1, SOCKLEN(&n2->addr1), &buf_n2, 100, NULL, 0, NI_NUMERICHOST); debug(28, 0) ("WARNING: '%s' is a subnetwork of " "'%s'\n", buf_n1, buf_n2); debug(28, 0) ("WARNING: because of this '%s' is ignored " - "to keep splay tree searching predictable\n", buf_a); + "to keep splay tree searching predictable\n", buf_n1); debug(28, 0) ("WARNING: You should probably remove '%s' " "from the ACL named '%s'\n", buf_n1, AclMatchedName); } @@ -2794,11 +2823,12 @@ MemBuf mb; wordlist **W = state; memBufDefInit(&mb); - memBufPrintf(&mb, "%s", inet_ntoa(ip->addr1)); + memBufPrintf(&mb, "%s", sockaddr_ntoa(&ip->addr1)); +/* if (ip->addr2.s_addr != any_addr.s_addr) - memBufPrintf(&mb, "-%s", inet_ntoa(ip->addr2)); - if (ip->mask.s_addr != no_addr.s_addr) - memBufPrintf(&mb, "/%s", inet_ntoa(ip->mask)); + memBufPrintf(&mb, "-%s", sockaddr_ntoa(&ip->addr2)); +*/ + memBufPrintf(&mb, "/%d", ip->masklen); wordlistAdd(W, mb.buf); memBufClean(&mb); } @@ -3205,7 +3235,7 @@ /* Do lookup */ *Top = splay_splay(&arpReq.arp_ha.sa_data, *Top, aclArpCompare); debug(28, 3) ("aclMatchArp: '%s' %s\n", - inet_ntoa(c), splayLastResult ? "NOT found" : "found"); + sockaddr_ntoa(c), splayLastResult ? "NOT found" : "found"); return (0 == splayLastResult); } /* lookup list of interface names */ Index: src/asn.c =================================================================== RCS file: /cvsroot/squid/squid/src/asn.c,v retrieving revision 1.84 diff -u -I\$Id -r1.84 asn.c --- src/asn.c 5 Jun 2006 22:47:01 -0000 1.84 +++ src/asn.c 5 Jul 2008 09:37:35 -0000 @@ -103,7 +103,7 @@ /* PUBLIC */ int -asnMatchIp(void *data, struct in_addr addr) +asnMatchIp(void *data, struct sockaddr *saddr) { unsigned long lh; struct squid_radix_node *rn; @@ -111,6 +111,10 @@ m_int m_addr; intlist *a = NULL; intlist *b = NULL; + struct in_addr addr = ((struct sockaddr_in *)saddr)->sin_addr; + + if (saddr->sa_family == AF_INET6) + return 1; lh = ntohl(addr.s_addr); debug(53, 3) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr)); Index: src/authenticate.c =================================================================== RCS file: /cvsroot/squid/squid/src/authenticate.c,v retrieving revision 1.51 diff -u -I\$Id -r1.51 authenticate.c --- src/authenticate.c 1 Jan 2007 22:44:58 -0000 1.51 +++ src/authenticate.c 5 Jul 2008 09:37:35 -0000 @@ -43,7 +43,7 @@ CBDATA_TYPE(auth_user_ip_t); static void authenticateDecodeAuth(const char *proxy_auth, auth_user_request_t * auth_user_request); -static auth_acl_t authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr); +static auth_acl_t authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct sockaddr *src_addr); /* * @@ -259,11 +259,10 @@ } static void -authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr) +authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct sockaddr *ipaddr) { auth_user_ip_t *ipdata, *next; auth_user_t *auth_user; - char *ip1; int found = 0; CBDATA_INIT_TYPE(auth_user_ip_t); if (!auth_user_request->auth_user) @@ -278,7 +277,7 @@ while ((ipdata = next) != NULL) { next = (auth_user_ip_t *) ipdata->node.next; /* walk the ip list */ - if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { + if (!memcmp(&ipdata->ipaddr, ipaddr, SOCKLEN(ipaddr))) { /* This ip has already been seen. */ found = 1; /* update IP ttl */ @@ -295,17 +294,15 @@ /* This ip is not in the seen list */ ipdata = cbdataAlloc(auth_user_ip_t); ipdata->ip_expiretime = squid_curtime; - ipdata->ipaddr = ipaddr; + xmemcpy(&ipdata->ipaddr, ipaddr, SOCKLEN(ipaddr)); dlinkAddTail(ipdata, &ipdata->node, &auth_user->ip_list); auth_user->ipcount++; - ip1 = xstrdup(inet_ntoa(ipaddr)); - debug(29, 2) ("authenticateAuthUserRequestSetIp: user '%s' has been seen at a new IP address (%s)\n", authenticateUserUsername(auth_user), ip1); - safe_free(ip1); + debug(29, 2) ("authenticateAuthUserRequestSetIp: user '%s' has been seen at a new IP address (%s)\n", authenticateUserUsername(auth_user), sockaddr_ntoa(ipaddr)); } void -authenticateAuthUserRequestRemoveIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr) +authenticateAuthUserRequestRemoveIp(auth_user_request_t * auth_user_request, struct sockaddr *ipaddr) { auth_user_ip_t *ipdata; auth_user_t *auth_user; @@ -315,7 +312,7 @@ ipdata = (auth_user_ip_t *) auth_user->ip_list.head; while (ipdata) { /* walk the ip list */ - if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { + if (!memcmp(&ipdata->ipaddr, ipaddr, SOCKLEN(ipaddr))) { authenticateAuthUserRemoveIpEntry(auth_user, ipdata); return; } @@ -434,7 +431,7 @@ * the authenticateStart routine for rv==AUTH_ACL_HELPER */ auth_acl_t -authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr) +authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct sockaddr *src_addr) { const char *proxy_auth; assert(headertype != 0); @@ -500,8 +497,8 @@ if (proxy_auth && !request->auth_user_request && conn && conn->auth_user_request) { int id = authenticateAuthSchemeId(proxy_auth) + 1; if (!conn->auth_user_request->auth_user || conn->auth_user_request->auth_user->auth_module != id) { - debug(29, 1) ("authenticateAuthenticate: Unexpected change of authentication scheme from '%s' to '%s' (client %s)\n", - authscheme_list[conn->auth_user_request->auth_user->auth_module - 1].typestr, proxy_auth, inet_ntoa(src_addr)); + debug(29, 1) ("authenticateAuthenticate: Unexpected change of authentication scheme from '%s' to '%s'", /* (client %s)\n",*/ + authscheme_list[conn->auth_user_request->auth_user->auth_module - 1].typestr, proxy_auth/*, inet_ntoa(src_addr)*/); /* XXX husni */ authenticateAuthUserRequestUnlock(conn->auth_user_request); conn->auth_user_request = NULL; conn->auth_type = AUTH_UNKNOWN; @@ -602,7 +599,7 @@ } auth_acl_t -authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr) +authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct sockaddr *src_addr) { /* If we have already been called, return the cached value */ auth_user_request_t *t = authTryGetUser(auth_user_request, conn, request); Index: src/cache_cf.c =================================================================== RCS file: /cvsroot/squid/squid/src/cache_cf.c,v retrieving revision 1.463.2.1 diff -u -I\$Id -r1.463.2.1 cache_cf.c --- src/cache_cf.c 26 Feb 2007 22:45:24 -0000 1.463.2.1 +++ src/cache_cf.c 5 Jul 2008 09:37:35 -0000 @@ -76,6 +76,7 @@ }; +static void cbdataFree_http_port(void *data); static void update_maxobjsize(void); static void configDoConfigure(void); static void parse_refreshpattern(refresh_t **); @@ -103,11 +104,11 @@ static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var); static void free_denyinfo(acl_deny_info_list ** var); #if USE_WCCPv2 -static void parse_sockaddr_in_list(sockaddr_in_list **); -static void dump_sockaddr_in_list(StoreEntry *, const char *, const sockaddr_in_list *); -static void free_sockaddr_in_list(sockaddr_in_list **); +static void parse_sockaddr_storage_list(sockaddr_storage_list **); +static void dump_sockaddr_storage_list(StoreEntry *, const char *, const sockaddr_storage_list *); +static void free_sockaddr_storage_list(sockaddr_storage_list **); #if UNUSED_CODE -static int check_null_sockaddr_in_list(const sockaddr_in_list *); +static int check_null_sockaddr_storage_list(const sockaddr_storage_list *); #endif #endif static void parse_http_port_list(http_port_list **); @@ -757,31 +758,44 @@ } static void -dump_address(StoreEntry * entry, const char *name, struct in_addr addr) +dump_address(StoreEntry * entry, const char *name, struct sockaddr *addr) { - storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr)); + storeAppendPrintf(entry, "%s %s\n", name, sockaddr_ntoa(addr)); } static void -parse_address(struct in_addr *addr) +parse_address(struct sockaddr *addr) { const struct hostent *hp; + struct addrinfo hints, *res, *res0; + int error; char *token = strtok(NULL, w_space); if (token == NULL) self_destruct(); if (safe_inet_addr(token, addr) == 1) (void) 0; - else if ((hp = gethostbyname(token))) /* dont use ipcache */ - *addr = inaddrFromHostent(hp); - else - self_destruct(); + else { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(token, NULL, &hints, &res); + if (error) + self_destruct(); + for (res = res0; res; res = res->ai_next) { + if ((res->ai_family == AF_INET) || (res->ai_family == AF_INET6)) { + xmemcpy(addr, res->ai_addr, SOCKLEN(res->ai_addr)); + break; + } + } + freeaddrinfo(res0); + } } static void -free_address(struct in_addr *addr) +free_address(struct sockaddr *addr) { - memset(addr, '\0', sizeof(struct in_addr)); + memset(addr, '\0', SOCKLEN(addr)); } CBDATA_TYPE(acl_address); @@ -791,10 +805,8 @@ { acl_address *l; for (l = head; l; l = l->next) { - if (l->addr.s_addr != INADDR_ANY) - storeAppendPrintf(entry, "%s %s", name, inet_ntoa(l->addr)); - else - storeAppendPrintf(entry, "%s autoselect", name); + storeAppendPrintf(entry, "%s %s", name, sockaddr_ntoa(&l->addr)); +/* storeAppendPrintf(entry, "%s autoselect", name); */ dump_acl_list(entry, l->acl_list); storeAppendPrintf(entry, "\n"); } @@ -2613,19 +2625,20 @@ #if USE_WCCPv2 static void -parse_sockaddr_in_list(sockaddr_in_list ** head) +parse_sockaddr_storage_list(sockaddr_storage_list ** head) { char *token; char *t; char *host; char *tmp; - const struct hostent *hp; + struct addrinfo hints, *res, *res0; unsigned short port = 0; - sockaddr_in_list *s; + sockaddr_storage_list *s; + int error; while ((token = strtok(NULL, w_space))) { host = NULL; port = 0; - if ((t = strchr(token, ':'))) { + if ((t = strrchr(token, ':'))) { /* host:port */ host = token; *t = '\0'; @@ -2639,15 +2652,27 @@ port = 0; } s = xcalloc(1, sizeof(*s)); - s->s.sin_port = htons(port); - if (NULL == host) - s->s.sin_addr = any_addr; - else if (1 == safe_inet_addr(host, &s->s.sin_addr)) + if (safe_inet_addr(token, &s->s) == 1) (void) 0; - else if ((hp = gethostbyname(host))) /* dont use ipcache */ - s->s.sin_addr = inaddrFromHostent(hp); + else { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(token, NULL, &hints, &res); + if (error) + self_destruct(); + for (res = res0; res; res = res->ai_next) { + if ((res->ai_family == AF_INET) || (res->ai_family == AF_INET6)) { + xmemcpy(&s->s, res->ai_addr, SOCKLEN(res->ai_addr)); + break; + } + } + freeaddrinfo(res0); + } + if (s->s.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&s->s)->sin6_port = htons(port); else - self_destruct(); + ((struct sockaddr_in *)&s->s)->sin_port = htons(port); while (*head) head = &(*head)->next; *head = s; @@ -2655,21 +2680,23 @@ } static void -dump_sockaddr_in_list(StoreEntry * e, const char *n, const sockaddr_in_list * s) +dump_sockaddr_storage_list(StoreEntry * e, const char *n, const sockaddr_storage_list * s) { while (s) { storeAppendPrintf(e, "%s %s:%d\n", n, - inet_ntoa(s->s.sin_addr), - ntohs(s->s.sin_port)); + sockaddr_ntoa(&s->s), + s->s.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&s->s)->sin6_port) : + ntohs(((struct sockaddr_in *)&s->s)->sin_port)); s = s->next; } } static void -free_sockaddr_in_list(sockaddr_in_list ** head) +free_sockaddr_storage_list(sockaddr_storage_list ** head) { - sockaddr_in_list *s; + sockaddr_storage_list *s; while ((s = *head) != NULL) { *head = s->next; xfree(s); @@ -2678,7 +2705,7 @@ #if UNUSED_CODE static int -check_null_sockaddr_in_list(const sockaddr_in_list * s) +check_null_sockaddr_storage_list(const sockaddr_storage_list * s) { return NULL == s; } @@ -2688,32 +2715,64 @@ static void parse_http_port_specification(http_port_list * s, char *token) { + CBDATA_TYPE(http_port_list); char *host = NULL; - const struct hostent *hp; + char *portstr = NULL; + struct addrinfo hints, *res, *res0; + http_port_list *sn1, *sn2; + int error; unsigned short port = 0; char *t; - if ((t = strchr(token, ':'))) { + CBDATA_INIT_TYPE_FREECB(http_port_list, cbdataFree_http_port); + if ((t = strrchr(token, ':'))) { /* host:port */ + port = xatos(t + 1); + portstr = t + 1; host = token; *t = '\0'; - port = xatos(t + 1); + t--; + if (*t == ']') { + *t = '\0'; + host = token+1; + } } else { /* port */ port = xatos(token); + portstr = token; } if (port == 0) self_destruct(); - s->s.sin_port = htons(port); - if (NULL == host) - s->s.sin_addr = any_addr; - else if (1 == safe_inet_addr(host, &s->s.sin_addr)) - (void) 0; - else if ((hp = gethostbyname(host))) { - /* dont use ipcache */ - s->s.sin_addr = inaddrFromHostent(hp); - s->defaultsite = xstrdup(host); - } else - self_destruct(); + + memset(&hints, 0, sizeof(hints)); + if (!host) { + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + } + error = getaddrinfo(host, portstr, &hints, &res0); + if (error) + self_destruct(); + sn1 = s; + sn2 = s; + for (res = res0; res; res = res->ai_next) { + if ((res->ai_family == AF_INET) ||(res->ai_family == AF_INET6)) { + if (!sn2) { + sn2 = cbdataAlloc(http_port_list); + sn1->next = sn2; + sn1 = sn2; + } + xmemcpy(&sn2->s, res->ai_addr, SOCKLEN(res->ai_addr)); + if (res->ai_family == AF_INET6) + ((struct sockaddr_in6 *)&sn2->s)->sin6_port = htons(port); + else + ((struct sockaddr_in *)&sn2->s)->sin_port = htons(port); + if (host) + sn2->defaultsite = xstrdup(host); + sn2 = sn2->next; + } + } + freeaddrinfo(res0); + } static void @@ -2732,7 +2791,9 @@ s->vhost = 1; s->accel = 1; } else if (strcmp(token, "vport") == 0) { - s->vport = ntohs(s->s.sin_port); + s->vport = (s->s.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&s->s)->sin6_port) : + ntohs(((struct sockaddr_in *)&s->s)->sin_port); s->accel = 1; } else if (strncmp(token, "vport=", 6) == 0) { s->vport = xatos(token + 6); @@ -2811,8 +2872,10 @@ { storeAppendPrintf(e, "%s %s:%d", n, - inet_ntoa(s->s.sin_addr), - ntohs(s->s.sin_port)); + sockaddr_ntoa(&s->s), + s->s.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&s->s)->sin6_port) : + ntohs(((struct sockaddr_in *)&s->s)->sin_port) ); if (s->transparent) storeAppendPrintf(e, " transparent"); if (s->accel) @@ -2821,7 +2884,7 @@ storeAppendPrintf(e, " defaultsite=%s", s->defaultsite); if (s->vhost) storeAppendPrintf(e, " vhost"); - if (s->vport == ntohs(s->s.sin_port)) + if (s->vport == ntohs(((struct sockaddr_in *)&s->s)->sin_port)) storeAppendPrintf(e, " vport"); else if (s->vport) storeAppendPrintf(e, " vport=%d", s->vport); Index: src/cf.data.pre =================================================================== RCS file: /cvsroot/squid/squid/src/cf.data.pre,v retrieving revision 1.382.2.2 diff -u -I\$Id -r1.382.2.2 cf.data.pre --- src/cf.data.pre 24 Apr 2007 21:30:03 -0000 1.382.2.2 +++ src/cf.data.pre 5 Jul 2008 09:37:35 -0000 @@ -380,15 +380,26 @@ By default, Squid doesn't listen on any multicast groups. DOC_END +NAME: udp_incoming_address6 +TYPE: address* +LOC:Config.Addrs.udp6_incoming +DEFAULT: :: +DOC_NONE + +NAME: udp_outgoing_address6 +TYPE: address* +LOC:Config.Addrs.udp6_outgoing +DEFAULT: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +DOC_NONE NAME: udp_incoming_address -TYPE: address +TYPE: address* LOC:Config.Addrs.udp_incoming DEFAULT: 0.0.0.0 DOC_NONE NAME: udp_outgoing_address -TYPE: address +TYPE: address* LOC: Config.Addrs.udp_outgoing DEFAULT: 255.255.255.255 DOC_START @@ -412,6 +423,7 @@ have the same value since they both use port 3130. DOC_END + COMMENT_START OPTIONS WHICH AFFECT THE NEIGHBOR SELECTION ALGORITHM ----------------------------------------------------------------------------- @@ -1477,8 +1489,20 @@ DOC_END +NAME: client_masklen +TYPE: int +LOC: Config.Addrs.client_masklen +DEFAULT: 32 +DOC_NONE + +NAME: client6_masklen +TYPE: int +LOC: Config.Addrs.client6_masklen +DEFAULT: 128 +DOC_NONE + NAME: client_netmask -TYPE: address +TYPE: address* LOC: Config.Addrs.client_netmask DEFAULT: 255.255.255.255 DOC_START @@ -2828,10 +2852,10 @@ NOCOMMENT_START #Recommended minimum configuration: -acl all src 0.0.0.0/0.0.0.0 +acl all src 0.0.0.0/0 ::/0 acl manager proto cache_object -acl localhost src 127.0.0.1/255.255.255.255 -acl to_localhost dst 127.0.0.0/8 +acl localhost src 127.0.0.1/32 ::1/128 +acl to_localhost dst 127.0.0.0/8 ::/126 acl SSL_ports port 443 acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp @@ -3162,8 +3186,8 @@ Example where normal_service_net uses the TOS value 0x00 and normal_service_net uses 0x20 - acl normal_service_net src 10.0.0.0/255.255.255.0 - acl good_service_net src 10.0.1.0/255.255.255.0 + acl normal_service_net src 10.0.0.0/24 + acl good_service_net src 10.0.1.0/24 tcp_outgoing_tos 0x00 normal_service_net 0x00 tcp_outgoing_tos 0x20 good_service_net @@ -3201,8 +3225,8 @@ source address 10.1.0.2 and the rest will be forwarded with source address 10.1.0.3. - acl normal_service_net src 10.0.0.0/255.255.255.0 - acl good_service_net src 10.0.1.0/255.255.255.0 + acl normal_service_net src 10.0.0.0/24 + acl good_service_net src 10.0.1.0/24 tcp_outgoing_address 10.0.0.1 normal_service_net tcp_outgoing_address 10.0.0.2 good_service_net tcp_outgoing_address 10.0.0.3 @@ -3986,7 +4010,7 @@ requests, except those in your local domain use something like: acl local-servers dstdomain .foo.net - acl all src 0.0.0.0/0.0.0.0 + acl all src 0.0.0.0/0 ::/0 never_direct deny local-servers never_direct allow all @@ -4191,13 +4215,13 @@ DOC_END NAME: snmp_incoming_address -TYPE: address +TYPE: address* LOC: Config.Addrs.snmp_incoming DEFAULT: 0.0.0.0 IFDEF: SQUID_SNMP DOC_NONE NAME: snmp_outgoing_address -TYPE: address +TYPE: address* LOC: Config.Addrs.snmp_outgoing DEFAULT: 255.255.255.255 IFDEF: SQUID_SNMP @@ -4232,13 +4256,13 @@ DOC_END NAME: wccp_router -TYPE: address +TYPE: address* LOC: Config.Wccp.router DEFAULT: 0.0.0.0 IFDEF: USE_WCCP DOC_NONE NAME: wccp2_router -TYPE: sockaddr_in_list +TYPE: sockaddr_storage_list LOC: Config.Wccp2.router DEFAULT: none IFDEF: USE_WCCPv2 @@ -4408,13 +4432,13 @@ DOC_END NAME: wccp_address -TYPE: address +TYPE: address* LOC: Config.Wccp.address DEFAULT: 0.0.0.0 IFDEF: USE_WCCP DOC_NONE NAME: wccp2_address -TYPE: address +TYPE: address* LOC: Config.Wccp2.address DEFAULT: 0.0.0.0 IFDEF: USE_WCCPv2 @@ -4688,7 +4712,7 @@ NAME: mcast_miss_addr IFDEF: MULTICAST_MISS_STREAM -TYPE: address +TYPE: address* LOC: Config.mcast_miss.addr DEFAULT: 255.255.255.255 DOC_START Index: src/cf_gen.c =================================================================== RCS file: /cvsroot/squid/squid/src/cf_gen.c,v retrieving revision 1.50 diff -u -I\$Id -r1.50 cf_gen.c --- src/cf_gen.c 22 May 2006 18:55:23 -0000 1.50 +++ src/cf_gen.c 5 Jul 2008 09:37:35 -0000 @@ -85,6 +85,7 @@ Line *doc; Line *nocomment; int array_flag; + int ptr_flag; struct Entry *next; } Entry; @@ -215,6 +216,12 @@ curr->array_flag = 1; *(ptr + strlen(ptr) - 2) = '\0'; } + /* hack to support pointers to struct */ + curr->ptr_flag = 0; + if (0 == strcmp(ptr + strlen(ptr) - 1, "*")) { + curr->ptr_flag = 1; + *(ptr + strlen(ptr) - 1) = '\0'; + } curr->type = xstrdup(ptr); } else if (!strncmp(buff, "IFDEF:", 6)) { if ((ptr = strtok(buff + 6, WS)) == NULL) { @@ -521,9 +528,10 @@ continue; if (entry->ifdef) fprintf(fp, "#if %s\n", entry->ifdef); - fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", + fprintf(fp, "\tdump_%s(entry, \"%s\", %s%s);\n", entry->type, entry->name, + entry->ptr_flag ? "&" : "", entry->loc); if (entry->ifdef) fprintf(fp, "#endif\n"); Index: src/client_db.c =================================================================== RCS file: /cvsroot/squid/squid/src/client_db.c,v retrieving revision 1.56 diff -u -I\$Id -r1.56 client_db.c --- src/client_db.c 23 Oct 2005 15:20:54 -0000 1.56 +++ src/client_db.c 5 Jul 2008 09:37:35 -0000 @@ -36,7 +36,7 @@ #include "squid.h" static hash_table *client_table = NULL; -static ClientInfo *clientdbAdd(struct in_addr addr); +static ClientInfo *clientdbAdd(struct sockaddr *addr); static FREE clientdbFreeItem; static void clientdbStartGC(void); static void clientdbScheduledGC(void *); @@ -49,12 +49,14 @@ #define CLIENT_DB_HASH_SIZE 467 static ClientInfo * -clientdbAdd(struct in_addr addr) +clientdbAdd(struct sockaddr *addr) { ClientInfo *c; + char host[100]; + getnameinfo(addr, SOCKLEN(addr), host, 100, NULL, 0, NI_NUMERICHOST); c = memAllocate(MEM_CLIENT_INFO); - c->hash.key = xstrdup(inet_ntoa(addr)); - c->addr = addr; + c->hash.key = xstrdup(host); + xmemcpy(&c->addr, addr, SOCKLEN(addr)); hash_join(client_table, &c->hash); statCounter.client_http.clients++; if ((statCounter.client_http.clients > max_clients) && !cleanup_running && cleanup_scheduled < 2) { @@ -77,13 +79,13 @@ } void -clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, squid_off_t size) +clientdbUpdate(struct sockaddr *addr, log_type ltype, protocol_t p, squid_off_t size) { - char *key; ClientInfo *c; + char key[100]; if (!Config.onoff.client_db) return; - key = inet_ntoa(addr); + getnameinfo(addr, SOCKLEN(addr), key, 100, NULL, 0, NI_NUMERICHOST); c = (ClientInfo *) hash_lookup(client_table, key); if (c == NULL) c = clientdbAdd(addr); @@ -113,13 +115,13 @@ * -1. To get the current value, simply call with delta = 0. */ int -clientdbEstablished(struct in_addr addr, int delta) +clientdbEstablished(struct sockaddr *addr, int delta) { - char *key; + char key[100]; ClientInfo *c; if (!Config.onoff.client_db) return 0; - key = inet_ntoa(addr); + getnameinfo(addr, SOCKLEN(addr), key, 100, NULL, 0, NI_NUMERICHOST); c = (ClientInfo *) hash_lookup(client_table, key); if (c == NULL) c = clientdbAdd(addr); @@ -131,16 +133,16 @@ #define CUTOFF_SECONDS 3600 int -clientdbCutoffDenied(struct in_addr addr) +clientdbCutoffDenied(struct sockaddr *addr) { - char *key; + char key[100]; int NR; int ND; double p; ClientInfo *c; if (!Config.onoff.client_db) return 0; - key = inet_ntoa(addr); + getnameinfo(addr, SOCKLEN(addr), key, 100, NULL, 0, NI_NUMERICHOST); c = (ClientInfo *) hash_lookup(client_table, key); if (c == NULL) return 0; @@ -184,7 +186,7 @@ hash_first(client_table); while ((c = (ClientInfo *) hash_next(client_table))) { storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(&c->hash)); - storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(c->addr)); + storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(&c->addr)); storeAppendPrintf(sentry, "Currently established connections: %d\n", c->n_established); storeAppendPrintf(sentry, " ICP Requests %d\n", @@ -299,6 +301,7 @@ } #if SQUID_SNMP +/* XXX husni */ struct in_addr * client_entry(struct in_addr *current) { @@ -347,7 +350,7 @@ switch (Var->name[LEN_SQ_NET + 2]) { case MESH_CTBL_ADDR: Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->addr.s_addr, + (snint) 0 /* c->addr.s_addr */, SMI_IPADDRESS); break; case MESH_CTBL_HTBYTES: Index: src/client_side.c =================================================================== RCS file: /cvsroot/squid/squid/src/client_side.c,v retrieving revision 1.693.2.12 diff -u -I\$Id -r1.693.2.12 client_side.c --- src/client_side.c 20 Mar 2007 21:26:34 -0000 1.693.2.12 +++ src/client_side.c 5 Jul 2008 09:37:35 -0000 @@ -220,8 +220,8 @@ request_t *request = http->request; request->x_forwarded_for_iterator = httpHeaderGetList( &request->header, HDR_X_FORWARDED_FOR); - debug(33, 5) ("clientFollowXForwardedForStart: indirect_client_addr=%s XFF='%s'\n", - inet_ntoa(request->indirect_client_addr), + debug(33, 5) ("clientFollowXForwardedForStart: indirect_client_addr=%s XFF='%s'\n", + sockaddr_ntoa(&request->indirect_client_addr), strBuf(request->x_forwarded_for_iterator)); clientFollowXForwardedForNext(http); } @@ -232,7 +232,7 @@ clientHttpRequest *http = data; request_t *request = http->request; debug(33, 5) ("clientFollowXForwardedForNext: indirect_client_addr=%s XFF='%s'\n", - inet_ntoa(request->indirect_client_addr), + sockaddr_ntoa(&request->indirect_client_addr), strBuf(request->x_forwarded_for_iterator)); if (strLen(request->x_forwarded_for_iterator) != 0) { /* check the acl to see whether to believe the X-Forwarded-For header */ @@ -266,9 +266,10 @@ const char *p; const char *asciiaddr; int l; - struct in_addr addr; + struct addrinfo hints, *res; + debug(33, 5) ("clientFollowXForwardedForDone: indirect_client_addr=%s is trusted\n", - inet_ntoa(request->indirect_client_addr)); + sockaddr_ntoa(&request->indirect_client_addr)); p = strBuf(request->x_forwarded_for_iterator); l = strLen(request->x_forwarded_for_iterator); @@ -290,16 +291,18 @@ while (l > 0 && !(p[l - 1] == ',' || xisspace(p[l - 1]))) l--; asciiaddr = p + l; - if (inet_aton(asciiaddr, &addr) == 0) { + memset(&hints, 0, sizeof(hints)); + if (getaddrinfo(asciiaddr, NULL, &hints, &res)) { /* the address is not well formed; do not use it */ debug(33, 3) ("clientFollowXForwardedForDone: malformed address '%s'\n", asciiaddr); goto done; } + debug(33, 3) ("clientFollowXForwardedForDone: changing indirect_client_addr from %s to '%s'\n", - inet_ntoa(request->indirect_client_addr), + sockaddr_ntoa(&request->indirect_client_addr), asciiaddr); - request->indirect_client_addr = addr; + xmemcpy(&request->indirect_client_addr, res->ai_addr, SOCKLEN(res->ai_addr)); strCut(request->x_forwarded_for_iterator, l); if (!Config.onoff.acl_uses_indirect_client) { /* @@ -312,10 +315,10 @@ return; } else if (answer == ACCESS_DENIED) { debug(33, 5) ("clientFollowXForwardedForDone: indirect_client_addr=%s not trusted\n", - inet_ntoa(request->indirect_client_addr)); + sockaddr_ntoa(&request->indirect_client_addr)); } else { debug(33, 5) ("clientFollowXForwardedForDone: indirect_client_addr=%s nothing more to do\n", - inet_ntoa(request->indirect_client_addr)); + sockaddr_ntoa(&request->indirect_client_addr)); } done: /* clean up, and pass control to clientAccessCheck */ @@ -326,10 +329,10 @@ * instead of the direct client. */ ConnStateData *conn = http->conn; - conn->log_addr = request->indirect_client_addr; - conn->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; + xmemcpy(&conn->log_addr, &request->indirect_client_addr, + sizeof(struct sockaddr_storage)); debug(33, 3) ("clientFollowXForwardedForDone: setting log_addr=%s\n", - inet_ntoa(conn->log_addr)); + sockaddr_ntoa(&conn->log_addr)); } stringClean(&request->x_forwarded_for_iterator); http->acl_checklist = NULL; /* XXX do we need to aclChecklistFree() ? */ @@ -602,12 +605,14 @@ http->uri = xstrdup(urlCanonical(new_request)); new_request->http_ver = old_request->http_ver; httpHeaderAppend(&new_request->header, &old_request->header); - new_request->client_addr = old_request->client_addr; + xmemcpy(&new_request->client_addr, &old_request->client_addr, + sizeof(struct sockaddr_storage)); new_request->client_port = old_request->client_port; #if FOLLOW_X_FORWARDED_FOR new_request->indirect_client_addr = old_request->indirect_client_addr; #endif /* FOLLOW_X_FORWARDED_FOR */ - new_request->my_addr = old_request->my_addr; + xmemcpy(&new_request->my_addr, &old_request->my_addr, + sizeof(struct sockaddr_storage)); new_request->my_port = old_request->my_port; new_request->client_port = old_request->client_port; new_request->flags = old_request->flags; @@ -1282,7 +1287,8 @@ http->al.http.code = mem->reply->sline.status; http->al.http.content_type = strBuf(mem->reply->content_type); } - http->al.cache.caddr = conn->log_addr; + xmemcpy(&http->al.cache.caddr, &conn->log_addr, + sizeof(struct sockaddr_storage)); http->al.cache.size = http->out.size; http->al.cache.code = http->log_type; http->al.cache.msec = tvSubMsec(http->start, current_time); @@ -1324,7 +1330,7 @@ http->al.reply = http->reply; accessLogLog(&http->al, http->acl_checklist); clientUpdateCounters(http); - clientdbUpdate(conn->peer.sin_addr, http->log_type, PROTO_HTTP, http->out.size); + clientdbUpdate(&conn->peer, http->log_type, PROTO_HTTP, http->out.size); } } if (http->acl_checklist) @@ -1380,7 +1386,7 @@ clientHttpRequest *http; debug(33, 3) ("connStateFree: FD %d\n", fd); assert(connState != NULL); - clientdbEstablished(connState->peer.sin_addr, -1); /* decrement */ + clientdbEstablished(&connState->peer, -1); /* decrement */ n = connState->reqs.head; while (n != NULL) { http = n->data; @@ -1538,11 +1544,11 @@ } #if USE_USERAGENT_LOG if ((str = httpHeaderGetStr(req_hdr, HDR_USER_AGENT))) - logUserAgent(fqdnFromAddr(http->conn->log_addr), str); + logUserAgent(fqdnFromAddr(&http->conn->log_addr), str); #endif #if USE_REFERER_LOG if ((str = httpHeaderGetStr(req_hdr, HDR_REFERER))) - logReferer(fqdnFromAddr(http->conn->log_addr), str, + logReferer(fqdnFromAddr(&http->conn->log_addr), str, http->log_uri); #endif #if FORW_VIA_DB @@ -3076,7 +3082,7 @@ #if SIZEOF_SQUID_OFF_T <= 4 if (http->out.size > 0x7FFF0000) { debug(33, 1) ("WARNING: closing FD %d to prevent counter overflow\n", fd); - debug(33, 1) ("\tclient %s\n", inet_ntoa(http->conn->peer.sin_addr)); + debug(33, 1) ("\tclient %s\n", sockaddr_ntoa(&http->conn->peer)); debug(33, 1) ("\treceived %d bytes\n", (int) http->out.size); debug(33, 1) ("\tURI %s\n", http->log_uri); comm_close(fd); @@ -3085,7 +3091,7 @@ #if SIZEOF_SQUID_OFF_T <= 4 if (http->out.offset > 0x7FFF0000) { debug(33, 1) ("WARNING: closing FD %d to prevent counter overflow\n", fd); - debug(33, 1) ("\tclient %s\n", inet_ntoa(http->conn->peer.sin_addr)); + debug(33, 1) ("\tclient %s\n", sockaddr_ntoa(&http->conn->peer)); debug(33, 1) ("\treceived %d bytes (offset %d)\n", (int) http->out.size, (int) http->out.offset); debug(33, 1) ("\tURI %s\n", http->log_uri); @@ -3640,10 +3646,13 @@ http->flags.accel = 1; debug(33, 5) ("INTERNAL REWRITE: '%s'\n", http->uri); } else if (*url == '/' && conn->port->transparent) { + char *q = NULL; int port = 0; const char *host = mime_get_header(req_hdr, "Host"); char *portstr; - if (host && (portstr = strchr(host, ':')) != NULL) { + if (!(q = strchr(host, ']'))) + q = host; + if (host && (portstr = strchr(q, ':')) != NULL) { *portstr++ = '\0'; port = atoi(portstr); } @@ -3663,9 +3672,11 @@ if (!host && !conn->transparent && clientNatLookup(conn) == 0) conn->transparent = 1; if (!host && conn->transparent) { - port = ntohs(conn->me.sin_port); + port = (conn->me.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&conn->me)->sin6_port) : + ntohs(((struct sockaddr_in *)&conn->me)->sin_port); if (!host) - host = inet_ntoa(conn->me.sin_addr); + host = sockaddr_ntoa(&conn->me); } if (host) { size_t url_sz = 10 + strlen(host) + 6 + strlen(url) + 32 + Config.appendDomainLen; @@ -3697,9 +3708,13 @@ if (*url != '/') { /* Fully qualified URL. Nothing special to do */ } else if (vhost && (t = mime_get_header(req_hdr, "Host"))) { - char *portstr = strchr(t, ':'); + char *portstr, *q; int port = 0; size_t url_sz = strlen(url) + 32 + Config.appendDomainLen + strlen(t); + + if (!(q = strchr(t, ']'))) + q = t; + portstr = strchr(q, ':'); if (portstr) { *portstr++ = '\0'; port = atoi(portstr); @@ -3728,7 +3743,7 @@ http->uri = xcalloc(url_sz, 1); snprintf(http->uri, url_sz, "%s://%s:%d%s", http->conn->port->protocol, - inet_ntoa(http->conn->me.sin_addr), + sockaddr_ntoa(&http->conn->me), vport, url); debug(33, 5) ("VPORT REWRITE: '%s'\n", http->uri); } else if (internalCheck(url)) { @@ -3915,7 +3930,8 @@ if (parser_return_code < 0) { debug(33, 1) ("clientReadRequest: FD %d (%s:%d) Invalid Request\n", fd, fd_table[fd].ipaddr, fd_table[fd].remote_port); err = errorCon(ERR_INVALID_REQ, HTTP_BAD_REQUEST, NULL); - err->src_addr = conn->peer.sin_addr; + xmemcpy(&err->src_addr, &conn->peer, + sizeof(struct sockaddr_storage)); err->request_hdrs = xstrdup(conn->in.buf); http->log_type = LOG_TCP_DENIED; http->entry = clientCreateStoreEntry(http, method, null_request_flags); @@ -3926,7 +3942,8 @@ if ((request = urlParse(method, http->uri)) == NULL) { debug(33, 5) ("Invalid URL: %s\n", http->uri); err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST, NULL); - err->src_addr = conn->peer.sin_addr; + xmemcpy(&err->src_addr, &conn->peer, + sizeof(struct sockaddr_storage)); err->url = xstrdup(http->uri); http->al.http.code = err->http_status; http->log_type = LOG_TCP_DENIED; @@ -3977,14 +3994,22 @@ request->content_length = httpHeaderGetSize(&request->header, HDR_CONTENT_LENGTH); request->flags.internal = http->flags.internal; - request->client_addr = conn->peer.sin_addr; - request->client_port = conn->peer.sin_port; + xmemcpy(&request->client_addr, &conn->peer, + sizeof(struct sockaddr_storage)); + request->client_port = (conn->peer.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&conn->peer)->sin6_port) : + ntohs(((struct sockaddr_in *)&conn->peer)->sin_port); #if FOLLOW_X_FORWARDED_FOR request->indirect_client_addr = request->client_addr; #endif /* FOLLOW_X_FORWARDED_FOR */ - request->my_addr = conn->me.sin_addr; - request->my_port = ntohs(conn->me.sin_port); - request->client_port = ntohs(conn->peer.sin_port); + xmemcpy(&request->my_addr, &conn->me, + sizeof(struct sockaddr_storage)); + request->my_port = (conn->me.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&conn->me)->sin6_port) : + ntohs(((struct sockaddr_in *)&conn->me)->sin_port); + request->client_port = (conn->peer.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&conn->peer)->sin6_port) : + ntohs(((struct sockaddr_in *)&conn->peer)->sin_port); request->http_ver = http->http_ver; if (!urlCheckRequest(request) || httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) { @@ -4029,7 +4054,7 @@ if (!DLINK_ISEMPTY(conn->reqs) && DLINK_HEAD(conn->reqs) == http) clientCheckFollowXForwardedFor(http); else { - debug(33, 1) ("WARNING: pipelined CONNECT request seen from %s\n", inet_ntoa(http->conn->peer.sin_addr)); + debug(33, 1) ("WARNING: pipelined CONNECT request seen from %s\n", sockaddr_ntoa(&http->conn->peer)); debugObj(33, 1, "Previous request:\n", ((clientHttpRequest *) DLINK_HEAD(conn->reqs))->request, (ObjPackMethod) & httpRequestPackDebug); debugObj(33, 1, "This request:\n", request, (ObjPackMethod) & httpRequestPackDebug); @@ -4050,7 +4075,8 @@ debug(33, 1) ("Config 'request_header_max_size'= %ld bytes.\n", (long int) Config.maxRequestHeaderSize); err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE, NULL); - err->src_addr = conn->peer.sin_addr; + xmemcpy(&err->src_addr, &conn->peer, + sizeof(struct sockaddr_storage)); http = parseHttpRequestAbort(conn, "error:request-too-large"); /* add to the client request queue */ dlinkAddTail(http, &http->node, &conn->reqs); @@ -4262,7 +4288,8 @@ * Generate an error */ err = errorCon(ERR_LIFETIME_EXP, HTTP_REQUEST_TIMEOUT, NULL); - err->src_addr = conn->peer.sin_addr; + xmemcpy(&err->src_addr, &conn->peer, + sizeof(struct sockaddr_storage)); err->url = xstrdup("N/A"); /* * Normally we shouldn't call errorSend() in client_side.c, but @@ -4301,7 +4328,7 @@ clientHttpRequest *http = data; ConnStateData *conn = http->conn; debug(33, 1) ("WARNING: Closing client %s connection due to lifetime timeout\n", - inet_ntoa(conn->peer.sin_addr)); + sockaddr_ntoa(&conn->peer)); debug(33, 1) ("\t%s\n", http->uri); comm_close(fd); } @@ -4411,7 +4438,7 @@ clientNatLookup(ConnStateData * conn) { socklen_t sock_sz = sizeof(conn->me); - struct in_addr orig_addr = conn->me.sin_addr; + struct in_addr orig_addr = ((struct sockaddr_in *)&conn->me)->sin_addr; static time_t last_reported = 0; /* If the call fails the address structure will be unchanged */ if (getsockopt(conn->fd, SOL_IP, SO_ORIGINAL_DST, &conn->me, &sock_sz) != 0) { @@ -4421,8 +4448,8 @@ } return -1; } - debug(33, 5) ("clientNatLookup: addr = %s", inet_ntoa(conn->me.sin_addr)); - if (orig_addr.s_addr != conn->me.sin_addr.s_addr) + debug(33, 5) ("clientNatLookup: addr = %s", sockaddr_ntoa(&conn->me)); + if (orig_addr.s_addr != ((struct sockaddr_in *)&conn->me)->sin_addr.s_addr) return 0; else return -1; @@ -4493,16 +4520,16 @@ int fd = -1; fde *F; ConnStateData *connState = NULL; - struct sockaddr_in peer; - struct sockaddr_in me; + struct sockaddr_storage peer; + struct sockaddr_storage me; int max = INCOMING_HTTP_MAX; #if USE_IDENT static aclCheck_t identChecklist; #endif commSetSelect(sock, COMM_SELECT_READ, httpAccept, data, 0); while (max-- && !httpAcceptDefer(sock, NULL)) { - memset(&peer, '\0', sizeof(struct sockaddr_in)); - memset(&me, '\0', sizeof(struct sockaddr_in)); + memset(&peer, '\0', sizeof(struct sockaddr_storage)); + memset(&me, '\0', sizeof(struct sockaddr_storage)); if ((fd = comm_accept(sock, &peer, &me)) < 0) { if (!ignoreErrno(errno)) debug(50, 1) ("httpAccept: FD %d: accept failure: %s\n", @@ -4515,27 +4542,36 @@ connState = cbdataAlloc(ConnStateData); connState->port = s; cbdataLock(connState->port); - connState->peer = peer; - connState->log_addr = peer.sin_addr; + xmemcpy(&connState->peer, &peer, + sizeof(struct sockaddr_storage)); + xmemcpy(&connState->log_addr, &peer, + sizeof(struct sockaddr_storage)); +/* connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; - connState->me = me; +*/ + xmemcpy(&connState->me, &me, + sizeof(struct sockaddr_storage)); connState->fd = fd; connState->pinning.fd = -1; connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size); comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(&peer, FQDN_LOOKUP_IF_MISS); commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState); #if USE_IDENT - identChecklist.src_addr = peer.sin_addr; - identChecklist.my_addr = me.sin_addr; - identChecklist.my_port = ntohs(me.sin_port); + xmemcpy(&identChecklist.src_addr, &peer, + sizeof(struct sockaddr_storage)); + xmemcpy(&identChecklist.my_addr, &me, + sizeof(struct sockaddr_storage)); + identChecklist.my_port = (me.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&me)->sin6_port) : + ntohs(((struct sockaddr_in *)&me)->sin_port) ; if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) identStart(&me, &peer, clientIdentDone, connState); #endif commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0); commSetDefer(fd, clientReadDefer, connState); - clientdbEstablished(peer.sin_addr, 1); + clientdbEstablished(&peer, 1); incoming_sockets_accepted++; } } @@ -4653,8 +4689,8 @@ https_port_list *s = data; int fd = -1; ConnStateData *connState = NULL; - struct sockaddr_in peer; - struct sockaddr_in me; + struct sockaddr_storage peer; + struct sockaddr_storage me; int max = INCOMING_HTTP_MAX; #if USE_IDENT static aclCheck_t identChecklist; @@ -4662,8 +4698,8 @@ commSetSelect(sock, COMM_SELECT_READ, httpsAccept, s, 0); while (max-- && !httpAcceptDefer(sock, NULL)) { fde *F; - memset(&peer, '\0', sizeof(struct sockaddr_in)); - memset(&me, '\0', sizeof(struct sockaddr_in)); + memset(&peer, '\0', sizeof(struct sockaddr_storage)); + memset(&me, '\0', sizeof(struct sockaddr_storage)); if ((fd = comm_accept(sock, &peer, &me)) < 0) { if (!ignoreErrno(errno)) debug(50, 1) ("httpsAccept: FD %d: accept failure: %s\n", @@ -4675,25 +4711,34 @@ connState = cbdataAlloc(ConnStateData); connState->port = (http_port_list *) s; cbdataLock(connState->port); - connState->peer = peer; - connState->log_addr = peer.sin_addr; + xmemcpy(&connState->peer, &peer, + sizeof(struct sockaddr_storage)); + xmemcpy(&connState->log_addr, &peer, + sizeof(struct sockaddr_storage)); +/* connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; - connState->me = me; +*/ + xmemcpy(&connState->me, &me, + sizeof(struct sockaddr_storage)); connState->fd = fd; connState->pinning.fd = -1; connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size); comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(&peer, FQDN_LOOKUP_IF_MISS); commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState); #if USE_IDENT - identChecklist.src_addr = peer.sin_addr; - identChecklist.my_addr = me.sin_addr; + xmemcpy(&identChecklist.src_addr, &peer, + sizeof(struct sockaddr_storage)); + xmemcpy(&identChecklist.my_addr, &me, + sizeof(struct sockaddr_storage)); +/* identChecklist.my_port = ntohs(me.sin_port); +*/ if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) identStart(&me, &peer, clientIdentDone, connState); #endif - clientdbEstablished(peer.sin_addr, 1); + clientdbEstablished(&peer, 1); incoming_sockets_accepted++; httpsAcceptSSL(connState, s->sslContext); } @@ -4831,6 +4876,7 @@ { http_port_list *s; int fd; + char host[100], port[8]; for (s = Config.Sockaddr.http; s; s = s->next) { if (MAXHTTPPORTS == NHttpSockets) { debug(1, 1) ("WARNING: You have too many 'http_port' lines.\n"); @@ -4840,8 +4886,7 @@ enter_suid(); fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - s->s.sin_addr, - ntohs(s->s.sin_port), + &s->s, COMM_NONBLOCKING, "HTTP Socket"); leave_suid(); @@ -4854,12 +4899,14 @@ * peg the CPU with select() when we hit the FD limit. */ commSetDefer(fd, httpAcceptDefer, NULL); - debug(1, 1) ("Accepting %s HTTP connections at %s, port %d, FD %d.\n", + getnameinfo(&s->s, SOCKLEN(&s->s), + host, 100, port, 8, NI_NUMERICHOST|NI_NUMERICSERV); + debug(1, 1) ("Accepting %s HTTP connections at %s, port %s, FD %d.\n", s->transparent ? "transparently proxied" : s->accel ? "accelerated" : "proxy", - inet_ntoa(s->s.sin_addr), - (int) ntohs(s->s.sin_port), + host, + port, fd); HttpSockets[NHttpSockets++] = fd; } @@ -4882,8 +4929,7 @@ enter_suid(); fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - s->http.s.sin_addr, - ntohs(s->http.s.sin_port), + &s->http.s, COMM_NONBLOCKING, "HTTPS Socket"); leave_suid(); @@ -4893,8 +4939,10 @@ commSetSelect(fd, COMM_SELECT_READ, httpsAccept, s, 0); commSetDefer(fd, httpAcceptDefer, NULL); debug(1, 1) ("Accepting HTTPS connections at %s, port %d, FD %d.\n", - inet_ntoa(s->http.s.sin_addr), - (int) ntohs(s->http.s.sin_port), + sockaddr_ntoa(&s->http.s), + (int) s->http.s.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&s->http.s)->sin6_port) : + ntohs(((struct sockaddr_in *)&s->http.s)->sin_port) , fd); HttpSockets[NHttpSockets++] = fd; } Index: src/comm.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm.c,v retrieving revision 1.358.2.1 diff -u -I\$Id -r1.358.2.1 comm.c --- src/comm.c 17 Apr 2007 09:39:56 -0000 1.358.2.1 +++ src/comm.c 5 Jul 2008 09:37:35 -0000 @@ -50,18 +50,19 @@ typedef struct { char *host; u_short port; - struct sockaddr_in S; + struct sockaddr_storage S; CNCB *callback; void *data; - struct in_addr in_addr; + struct sockaddr_storage in_addr; int fd; int tries; + int ia_cur; int addrcount; int connstart; } ConnectStateData; /* STATIC */ -static int commBind(int s, struct in_addr, u_short port); +static int commBind(int s, struct sockaddr *S); static void commSetReuseAddr(int); static void commSetNoLinger(int); static void CommWriteStateCallbackAndFree(int fd, int code); @@ -111,7 +112,7 @@ u_short comm_local_port(int fd) { - struct sockaddr_in addr; + struct sockaddr_storage addr; socklen_t addr_len = 0; fde *F = &fd_table[fd]; @@ -122,33 +123,29 @@ } if (F->local_port) return F->local_port; - addr_len = sizeof(addr); + addr_len = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *) &addr, &addr_len)) { debug(5, 1) ("comm_local_port: Failed to retrieve TCP/UDP port number for socket: FD %d: %s\n", fd, xstrerror()); return 0; } - F->local_port = ntohs(addr.sin_port); + F->local_port = (addr.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&addr)->sin6_port): + ntohs(((struct sockaddr_in *)&addr)->sin_port) ; debug(5, 6) ("comm_local_port: FD %d: port %d\n", fd, (int) F->local_port); return F->local_port; } static int -commBind(int s, struct in_addr in_addr, u_short port) +commBind(int s, struct sockaddr *S) { - struct sockaddr_in S; - - memset(&S, '\0', sizeof(S)); - S.sin_family = AF_INET; - S.sin_port = htons(port); - S.sin_addr = in_addr; + char hbuf[80], sbuf[8]; statCounter.syscalls.sock.binds++; - if (bind(s, (struct sockaddr *) &S, sizeof(S)) == 0) + if (bind(s, S, SOCKLEN(S)) == 0) return COMM_OK; - debug(5, 0) ("commBind: Cannot bind socket FD %d to %s:%d: %s\n", - s, - S.sin_addr.s_addr == INADDR_ANY ? "*" : inet_ntoa(S.sin_addr), - (int) port, - xstrerror()); + getnameinfo(S, S->sa_family, hbuf, 80, sbuf, 8, + NI_NUMERICHOST|NI_NUMERICSERV); + debug(5, 0) ("commBind: Cannot bind socket FD %d to %s:%s: %s\n", + s, hbuf, sbuf, xstrerror()); return COMM_ERROR; } @@ -157,12 +154,11 @@ int comm_open(int sock_type, int proto, - struct in_addr addr, - u_short port, + struct sockaddr *addr, int flags, const char *note) { - return comm_openex(sock_type, proto, addr, port, flags, 0, note); + return comm_openex(sock_type, proto, addr, flags, 0, note); } @@ -171,19 +167,19 @@ int comm_openex(int sock_type, int proto, - struct in_addr addr, - u_short port, + struct sockaddr *addr, int flags, unsigned char TOS, const char *note) { int new_socket; + u_short port; int tos = 0; fde *F = NULL; /* Create socket for accepting new connections. */ statCounter.syscalls.sock.sockets++; - if ((new_socket = socket(AF_INET, sock_type, proto)) < 0) { + if ((new_socket = socket(addr->sa_family, sock_type, proto)) < 0) { /* Increase the number of reserved fd's if calls to socket() * are failing because the open file table is full. This * limits the number of simultaneous clients */ @@ -213,12 +209,15 @@ debug(5, 5) ("comm_open: FD %d is a new socket\n", new_socket); fd_open(new_socket, FD_SOCKET, note); F = &fd_table[new_socket]; - F->local_addr = addr; + xmemcpy(&F->local_addr, addr, SOCKLEN(addr)); F->tos = tos; if (!(flags & COMM_NOCLOEXEC)) commSetCloseOnExec(new_socket); if ((flags & COMM_REUSEADDR)) commSetReuseAddr(new_socket); + port = (addr->sa_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)addr)->sin6_port) : + ntohs(((struct sockaddr_in *)addr)->sin_port); if (port > (u_short) 0) { #ifdef _SQUID_MSWIN_ if (sock_type != SOCK_DGRAM) @@ -227,14 +226,38 @@ if (opt_reuseaddr) commSetReuseAddr(new_socket); } - if (addr.s_addr != no_addr.s_addr) { - if (commBind(new_socket, addr, port) != COMM_OK) { + switch (addr->sa_family) { + case AF_INET: + if (((struct sockaddr_in *)addr)->sin_addr.s_addr != no_addr.s_addr) { + if (commBind(new_socket, addr) != COMM_OK) { + comm_close(new_socket); + return -1; + } + } + F->local_port = ntohs(((struct sockaddr_in *)addr)->sin_port); + break; + case AF_INET6: + { + struct in6_addr *s6 = &((struct sockaddr_in6 *)addr)->sin6_addr; + if (!IN6_IS_ADDR_ALLF( (struct in6_addr*)&((struct sockaddr_in6 *)addr)->sin6_addr )){ +#ifdef IPV6_V6ONLY + const int on = 1; + if (setsockopt(new_socket, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { comm_close(new_socket); return -1; } +#endif + if (commBind(new_socket, addr) != COMM_OK) { + comm_close(new_socket); + return -1; + } + } } - F->local_port = port; + F->local_port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); + break; + } + xmemcpy(&F->local_addr, addr, SOCKLEN(addr)); if (flags & COMM_NONBLOCKING) if (commSetNonBlocking(new_socket) == COMM_ERROR) return -1; @@ -268,9 +291,10 @@ } void -commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void *data) +commConnectStart(int fd, const char *host, u_short port, CNCB *callback, void *data) { ConnectStateData *cs; + FwdState *fwdState = data; debug(5, 3) ("commConnectStart: FD %d, %s:%d\n", fd, host, (int) port); cs = cbdataAlloc(ConnectStateData); cs->fd = fd; @@ -278,6 +302,7 @@ cs->port = port; cs->callback = callback; cs->data = data; + cs->ia_cur= fwdState->ia_cur; cbdataLock(cs->data); comm_add_close_handler(fd, commConnectFree, cs); ipcache_nbgethostbyname(host, commConnectDnsHandle, cs); @@ -298,9 +323,15 @@ return; } assert(ia->cur < ia->count); - cs->in_addr = ia->in_addrs[ia->cur]; - if (Config.onoff.balance_on_multiple_ip) - ipcacheCycleAddr(cs->host, NULL); + if (Config.onoff.balance_on_multiple_ip) { + if (cs->ia_cur < 0) { + ipcacheCycleAddr(cs->host, NULL); + cs->ia_cur = ia->cur; + } + } + else + cs->ia_cur = ia->cur; + xmemcpy(&cs->in_addr, &ia->in_addrs[cs->ia_cur], sizeof(struct sockaddr_storage)); cs->addrcount = ia->count; cs->connstart = squid_curtime; commConnectHandle(cs->fd, cs); @@ -311,7 +342,9 @@ { CNCB *callback = cs->callback; void *data = cs->data; + FwdState *fwdState = cs->data; int fd = cs->fd; + fwdState->ia_cur = cs->ia_cur; comm_remove_close_handler(fd, commConnectFree, cs); cs->callback = NULL; cs->data = NULL; @@ -339,10 +372,17 @@ { int fd2; fde *F; + struct sockaddr_storage oldsock; + socklen_t oldsocklen = sizeof(oldsock); if (!cbdataValid(cs->data)) return 0; statCounter.syscalls.sock.sockets++; - fd2 = socket(AF_INET, SOCK_STREAM, 0); + getsockname(cs->fd, (struct sockaddr *)&oldsock, &oldsocklen); + F = &fd_table[cs->fd]; + if (F->local_addr.ss_family == AF_INET6) + fd2 = socket(AF_INET6, SOCK_STREAM, 0); + else + fd2 = socket(AF_INET, SOCK_STREAM, 0); statCounter.syscalls.sock.sockets++; if (fd2 < 0) { debug(5, 0) ("commResetFD: socket: %s\n", xstrerror()); @@ -365,13 +405,12 @@ return 0; } close(fd2); - F = &fd_table[cs->fd]; fd_table[cs->fd].flags.called_connect = 0; /* * yuck, this has assumptions about comm_open() arguments for * the original socket */ - if (commBind(cs->fd, F->local_addr, F->local_port) != COMM_OK) { + if (commBind(cs->fd, &F->local_addr) != COMM_OK) { debug(5, 0) ("commResetFD: bind: %s\n", xstrerror()); return 0; } @@ -426,10 +465,14 @@ commConnectHandle(int fd, void *data) { ConnectStateData *cs = data; - if (cs->S.sin_addr.s_addr == 0) { - cs->S.sin_family = AF_INET; - cs->S.sin_addr = cs->in_addr; - cs->S.sin_port = htons(cs->port); + struct sockaddr *sa; + if ((cs->in_addr.ss_family == AF_INET) || (cs->in_addr.ss_family == AF_INET6)) { + xmemcpy(&cs->S, &cs->in_addr, sizeof(struct sockaddr_storage)); + sa =(struct sockaddr *)&cs->S; + if (sa->sa_family == AF_INET6) + ((struct sockaddr_in6 *)&cs->S)->sin6_port = htons(cs->port); + else + ((struct sockaddr_in *)&cs->S)->sin_port = htons(cs->port); } switch (comm_connect_addr(fd, &cs->S)) { case COMM_INPROGRESS: @@ -437,14 +480,18 @@ commSetSelect(fd, COMM_SELECT_WRITE, commConnectHandle, cs, 0); break; case COMM_OK: - ipcacheMarkGoodAddr(cs->host, cs->S.sin_addr); + ipcacheMarkGoodAddr(cs->host, &cs->S); commConnectCallback(cs, COMM_OK); break; + case COMM_ERR_NOSUPPORT: + case COMM_ERR_INV_ARGS: + commConnectCallback(cs, COMM_ERR_INV_ARGS); + break; default: cs->tries++; - ipcacheMarkBadAddr(cs->host, cs->S.sin_addr); + ipcacheMarkBadAddr(cs->host, &cs->S); if (Config.onoff.test_reachability) - netdbDeleteAddrNetwork(cs->S.sin_addr); + netdbDeleteAddrNetwork(&cs->S); if (commRetryConnect(cs)) { eventAdd("commReconnect", commReconnect, cs, cs->addrcount == 1 ? 0.05 : 0.0, 0); } else { @@ -477,26 +524,31 @@ } int -comm_connect_addr(int sock, const struct sockaddr_in *address) +comm_connect_addr(int sock, const struct sockaddr *address) { int status = COMM_OK; fde *F = &fd_table[sock]; int x; int err = 0; socklen_t errlen; - assert(ntohs(address->sin_port) != 0); + + if (address->sa_family == AF_INET6) + assert(ntohs(((struct sockaddr_in6 *)address)->sin6_port) != 0); + else + assert(ntohs(((struct sockaddr_in *)address)->sin_port) != 0); /* Establish connection. */ errno = 0; if (!F->flags.called_connect) { F->flags.called_connect = 1; statCounter.syscalls.sock.connects++; - x = connect(sock, (struct sockaddr *) address, sizeof(*address)); + x = connect(sock, address, SOCKLEN(address)); if (x < 0) - debug(5, 9) ("connect FD %d: %s\n", sock, xstrerror()); + debug(5, 2) ("connect FD %d to %s : %s\n", sock, + sockaddr_ntoa(address), xstrerror()); } else { #if defined(_SQUID_NEWSOS6_) /* Makoto MATSUSHITA */ - connect(sock, (struct sockaddr *) address, sizeof(*address)); + connect(sock, address, SOCKLEN(address)); if (errno == EINVAL) { errlen = sizeof(err); x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); @@ -524,10 +576,16 @@ status = COMM_OK; else if (ignoreErrno(errno)) status = COMM_INPROGRESS; + else if (errno == COMM_ERR_INV_ARGS) + return COMM_ERR_INV_ARGS; + else if (errno == COMM_ERR_NOSUPPORT) + return COMM_ERR_INV_ARGS; else return COMM_ERROR; - xstrncpy(F->ipaddr, inet_ntoa(address->sin_addr), 16); - F->remote_port = ntohs(address->sin_port); + xstrncpy(F->ipaddr, sockaddr_ntoa(address), 80); + F->remote_port = (address->sa_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)address)->sin6_port) : + ntohs(((struct sockaddr_in *)address)->sin_port); if (status == COMM_OK) { debug(5, 10) ("comm_connect_addr: FD %d connected to %s:%d\n", sock, F->ipaddr, F->remote_port); @@ -540,11 +598,11 @@ /* Wait for an incoming connection on FD. FD should be a socket returned * from comm_listen. */ int -comm_accept(int fd, struct sockaddr_in *pn, struct sockaddr_in *me) +comm_accept(int fd, struct sockaddr *pn, struct sockaddr *me) { int sock; - struct sockaddr_in P; - struct sockaddr_in M; + struct sockaddr_storage P; + struct sockaddr_storage M; socklen_t Slen; fde *F = NULL; Slen = sizeof(P); @@ -562,19 +620,27 @@ } } if (pn) - *pn = P; + xmemcpy(pn, &P, SOCKLEN(&P)); Slen = sizeof(M); memset(&M, '\0', Slen); getsockname(sock, (struct sockaddr *) &M, &Slen); if (me) - *me = M; + xmemcpy(me, &M, SOCKLEN(&M)); commSetCloseOnExec(sock); /* fdstat update */ fd_open(sock, FD_SOCKET, "HTTP Request"); F = &fd_table[sock]; - xstrncpy(F->ipaddr, inet_ntoa(P.sin_addr), 16); - F->remote_port = htons(P.sin_port); - F->local_port = htons(M.sin_port); + xstrncpy(F->ipaddr, sockaddr_ntoa(&P), 80); + switch (P.ss_family) { + case AF_INET6: + F->remote_port = ntohs(((struct sockaddr_in6 *)&P)->sin6_port); + F->local_port = ntohs(((struct sockaddr_in6 *)&M)->sin6_port); + break; + case AF_INET: + F->remote_port = ntohs(((struct sockaddr_in *)&P)->sin_port); + F->local_port = ntohs(((struct sockaddr_in *)&M)->sin_port); + break; + } commSetNonBlocking(sock); return sock; } @@ -762,22 +828,25 @@ /* Send a udp datagram to specified TO_ADDR. */ int comm_udp_sendto(int fd, - const struct sockaddr_in *to_addr, + const struct sockaddr *to_addr, int addr_len, const void *buf, int len) { int x; + char hbuf[100], sbuf[8]; statCounter.syscalls.sock.sendtos++; - x = sendto(fd, buf, len, 0, (struct sockaddr *) to_addr, addr_len); + x = sendto(fd, buf, len, 0, to_addr, SOCKLEN(to_addr)); if (x < 0) { + getnameinfo(to_addr, SOCKLEN(to_addr), hbuf, 100, sbuf, 8, + NI_NUMERICHOST|NI_NUMERICSERV); #ifdef _SQUID_LINUX_ if (ECONNREFUSED != errno) #endif - debug(5, 1) ("comm_udp_sendto: FD %d, %s, port %d: %s\n", + debug(5, 1) ("comm_udp_sendto: FD %d, %s, port %s: %s\n", fd, - inet_ntoa(to_addr->sin_addr), - (int) htons(to_addr->sin_port), + hbuf, + sbuf, xstrerror()); return COMM_ERROR; } Index: src/comm_generic.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_generic.c,v retrieving revision 1.8 diff -u -I\$Id -r1.8 comm_generic.c --- src/comm_generic.c 31 Oct 2006 18:25:15 -0000 1.8 +++ src/comm_generic.c 5 Jul 2008 09:37:35 -0000 @@ -165,6 +165,10 @@ do_call_incoming(theInIcpConnection); if (theOutIcpConnection != theInIcpConnection) do_call_incoming(theOutIcpConnection); + if (theInIcpConnection6 >= 0) + do_call_incoming(theInIcpConnection6); + if (theOutIcpConnection6 != theInIcpConnection6) + do_call_incoming(theOutIcpConnection6); } static inline void Index: src/defines.h =================================================================== RCS file: /cvsroot/squid/squid/src/defines.h,v retrieving revision 1.122.2.1 diff -u -I\$Id -r1.122.2.1 defines.h --- src/defines.h 3 Feb 2007 22:58:20 -0000 1.122.2.1 +++ src/defines.h 5 Jul 2008 09:37:35 -0000 @@ -84,6 +84,8 @@ #define COMM_ERR_CONNECT (-7) #define COMM_ERR_DNS (-8) #define COMM_ERR_CLOSING (-9) +#define COMM_ERR_INV_ARGS (22) +#define COMM_ERR_NOSUPPORT (97) /* Select types. */ #define COMM_SELECT_READ (0x1) @@ -364,4 +366,18 @@ #define DLINK_ISEMPTY(n) ( (n).head == NULL ) #define DLINK_HEAD(n) ( (n).head->data ) +/* + * Macro to compare IPv6 addresses (b is 0, 4, 8, 12) + */ +#define IN6_NTOHL_N(a,b) \ + (ntohl(*(const u_int32_t *)(const void *)(&(a)->s6_addr[(b)]))) + +#define IN6_IS_ADDR_ALLF(a) \ + (IN6_NTOHL_N(a,0) & IN6_NTOHL_N(a,4) & \ + IN6_NTOHL_N(a,8) & IN6_NTOHL_N(a,12) == \ + (u_int32_t)0xffffffff) + +#define SOCKLEN(a) \ + (((struct sockaddr_storage *)(a))->ss_family == AF_INET6 ? \ + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) #endif /* SQUID_DEFINES_H */ Index: src/delay_pools.c =================================================================== RCS file: /cvsroot/squid/squid/src/delay_pools.c,v retrieving revision 1.34 diff -u -I\$Id -r1.34 delay_pools.c --- src/delay_pools.c 23 Oct 2006 11:22:21 -0000 1.34 +++ src/delay_pools.c 5 Jul 2008 09:37:35 -0000 @@ -322,12 +322,13 @@ ch.src_addr = r->indirect_client_addr; } else #endif /* FOLLOW_X_FORWARDED_FOR */ - ch.src_addr = r->client_addr; - ch.my_addr = r->my_addr; + xmemcpy(&ch.src_addr, &r->client_addr, SOCKLEN(&r->client_addr)); + xmemcpy(&ch.my_addr, &r->my_addr, SOCKLEN(&r->my_addr)); ch.my_port = r->my_port; ch.conn = http->conn; ch.request = r; - if (r->client_addr.s_addr == INADDR_BROADCAST) { + if (r->client_addr.ss_family == AF_INET && + ((struct sockaddr_in *)&r->client_addr)->sin_addr.s_addr == INADDR_BROADCAST) { debug(77, 2) ("delayClient: WARNING: Called with 'allones' address, ignoring\n"); return delayId(0, 0); } @@ -343,7 +344,10 @@ if (class == 1) return delayId(pool + 1, 0); if (class == 2) { +/* XXX husni host = ntohl(ch.src_addr.s_addr) & 0xff; +*/ + host = 255; if (host == 255) { if (!delay_data[pool].class2->individual_255_used) { delay_data[pool].class2->individual_255_used = 1; @@ -369,7 +373,10 @@ return delayId(pool + 1, i); } /* class == 3 */ +/* XXX husni host = ntohl(ch.src_addr.s_addr) & 0xffff; +*/ + host = 0xffff; net = host >> 8; host &= 0xff; if (net == 255) { Index: src/dns_internal.c =================================================================== RCS file: /cvsroot/squid/squid/src/dns_internal.c,v retrieving revision 1.61 diff -u -I\$Id -r1.61 dns_internal.c --- src/dns_internal.c 17 Dec 2006 10:51:44 -0000 1.61 +++ src/dns_internal.c 5 Jul 2008 09:37:35 -0000 @@ -89,12 +89,14 @@ struct _idns_query { hash_link hash; + int ia_cur; rfc1035_query query; + char query_key[RFC1035_MAXHOSTNAMESZ+5]; char buf[RESOLV_BUFSZ]; char name[NS_MAXDNAME + 1]; char orig[NS_MAXDNAME + 1]; ssize_t sz; - unsigned short id; + unsigned short id, id_pair; int nsends; struct timeval start_t; struct timeval sent_t; @@ -114,7 +116,7 @@ }; struct _ns { - struct sockaddr_in S; + struct sockaddr_storage S; int nqueries; int nreplies; }; @@ -150,7 +152,7 @@ #endif static void idnsCacheQuery(idns_query * q); static void idnsSendQuery(idns_query * q); -static int idnsFromKnownNameserver(struct sockaddr_in *from); +static int idnsFromKnownNameserver(struct sockaddr *from); static idns_query *idnsFindQuery(unsigned short id); static void idnsGrokReply(const char *buf, size_t sz); static PF idnsRead; @@ -161,12 +163,13 @@ static void idnsAddNameserver(const char *buf) { - struct in_addr A; + struct sockaddr_storage A; if (!safe_inet_addr(buf, &A)) { debug(78, 0) ("WARNING: rejecting '%s' as a name server, because it is not a numeric IP address\n", buf); return; } - if (A.s_addr == 0) { + if ( ((A.ss_family == AF_INET6) && IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&A)->sin6_addr)) || + ((A.ss_family == AF_INET) && (((struct sockaddr_in *)&A)->sin_addr.s_addr == 0)) ) { debug(78, 0) ("WARNING: Squid does not accept 0.0.0.0 in DNS server specifications.\n"); debug(78, 0) ("Will be using 127.0.0.1 instead, assuming you meant that DNS is running on the same machine\n"); safe_inet_addr("127.0.0.1", &A); @@ -185,11 +188,13 @@ safe_free(oldptr); } assert(nns < nns_alloc); - nameservers[nns].S.sin_family = AF_INET; - nameservers[nns].S.sin_port = htons(NS_DEFAULTPORT); - nameservers[nns].S.sin_addr.s_addr = A.s_addr; + xmemcpy(&nameservers[nns].S, &A, sizeof(struct sockaddr_storage)); + if (A.ss_family == AF_INET) + ((struct sockaddr_in *)&nameservers[nns].S)->sin_port = htons(NS_DEFAULTPORT); + if (A.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&nameservers[nns].S)->sin6_port = htons(NS_DEFAULTPORT); debug(78, 3) ("idnsAddNameserver: Added nameserver #%d: %s\n", - nns, inet_ntoa(nameservers[nns].S.sin_addr)); + nns, sockaddr_ntoa(&nameservers[nns].S)); nns++; } @@ -499,7 +504,7 @@ storeAppendPrintf(sentry, "--------------- --------- ---------\n"); for (i = 0; i < nns; i++) { storeAppendPrintf(sentry, "%-15s %9d %9d\n", - inet_ntoa(nameservers[i].S.sin_addr), + sockaddr_ntoa(&nameservers[i].S), nameservers[i].nqueries, nameservers[i].nreplies); } @@ -551,6 +556,7 @@ { int x; int ns; + int DnsSocketTemp; if (DnsSocket < 0) { debug(78, 1) ("idnsSendQuery: Can't send query, no DNS socket!\n"); return; @@ -562,21 +568,29 @@ idnsTcpCleanup(q); try_again: ns = q->nsends % nns; - x = comm_udp_sendto(DnsSocket, + if (nameservers[ns].S.ss_family == AF_INET6) + DnsSocketTemp = DnsSocket6; + else + DnsSocketTemp = DnsSocket; + + x = comm_udp_sendto(DnsSocketTemp, &nameservers[ns].S, - sizeof(nameservers[ns].S), + SOCKLEN(&nameservers[ns].S), q->buf, q->sz); q->nsends++; q->sent_t = current_time; if (x < 0) { debug(50, 1) ("idnsSendQuery: FD %d: sendto: %s\n", - DnsSocket, xstrerror()); + DnsSocketTemp, xstrerror()); if (q->nsends % nns != 0) goto try_again; } else { - fd_bytes(DnsSocket, x, FD_WRITE); - commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0); + fd_bytes(DnsSocketTemp, x, FD_WRITE); +/* + if (q->query.qtype == RFC1035_TYPE_A) +*/ + commSetSelect(DnsSocketTemp, COMM_SELECT_READ, idnsRead, NULL, 0); } nameservers[ns].nqueries++; dlinkAdd(q, &q->lru, &lru_list); @@ -584,13 +598,19 @@ } static int -idnsFromKnownNameserver(struct sockaddr_in *from) +idnsFromKnownNameserver(struct sockaddr *from) { int i; for (i = 0; i < nns; i++) { - if (nameservers[i].S.sin_addr.s_addr != from->sin_addr.s_addr) + if (nameservers[i].S.ss_family != from->sa_family) + continue; + if (from->sa_family == AF_INET && + (((struct sockaddr_in *)&nameservers[i].S)->sin_addr.s_addr != ((struct sockaddr_in *)from)->sin_addr.s_addr || + ((struct sockaddr_in *)&nameservers[i].S)->sin_port != ((struct sockaddr_in *)from)->sin_port)) continue; - if (nameservers[i].S.sin_port != from->sin_port) + if (from->sa_family == AF_INET6 && + (!IN6_ARE_ADDR_EQUAL( &((struct sockaddr_in6 *)&nameservers[i].S)->sin6_addr, &((struct sockaddr_in6 *)from)->sin6_addr) || + ((struct sockaddr_in6 *)&nameservers[i].S)->sin6_port != ((struct sockaddr_in6 *)from)->sin6_port)) continue; return i; } @@ -724,23 +744,34 @@ static void idnsRetryTcp(idns_query * q) { - struct in_addr addr; + struct sockaddr_storage addr; + char host[100], port[8]; int ns = (q->nsends - 1) % nns; idnsTcpCleanup(q); - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) - addr = Config.Addrs.udp_outgoing; - else - addr = Config.Addrs.udp_incoming; + if (nameservers[ns].S.ss_family == AF_INET6) { + if (!IN6_IS_ADDR_ALLF(&((struct sockaddr_in6 *)&Config.Addrs.udp6_outgoing)->sin6_addr)) + xmemcpy(&addr, &Config.Addrs.udp6_outgoing, sizeof(addr)); + else + xmemcpy(&addr, &Config.Addrs.udp6_incoming, sizeof(addr)); + } + else { + if (((struct sockaddr_in *)&Config.Addrs.udp_outgoing)->sin_addr.s_addr != no_addr.s_addr) + xmemcpy(&addr, &Config.Addrs.udp_outgoing, sizeof(addr)); + else + xmemcpy(&addr, &Config.Addrs.udp_incoming, sizeof(addr)); + } q->tcp_socket = comm_open(SOCK_STREAM, IPPROTO_TCP, - addr, - 0, + &addr, COMM_NONBLOCKING, "DNS TCP Socket"); dlinkAdd(q, &q->lru, &lru_list); + q->ia_cur = -1; commConnectStart(q->tcp_socket, - inet_ntoa(nameservers[ns].S.sin_addr), - ntohs(nameservers[ns].S.sin_port), + sockaddr_ntoa(&nameservers[ns].S), + nameservers[ns].S.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&nameservers[ns])->sin6_port) : + ntohs(((struct sockaddr_in *)&nameservers[ns])->sin_port) , idnsSendTcpQuery, q ); @@ -751,7 +782,7 @@ { int n; rfc1035_message *message = NULL; - idns_query *q; + idns_query *q, *q_pair; n = rfc1035MessageUnpack(buf, sz, &message); @@ -768,6 +799,9 @@ rfc1035MessageDestroy(message); return; } + + q_pair = idnsFindQuery(q->id_pair); + if (rfc1035QueryCompare(&q->query, message->query) != 0) { debug(78, 3) ("idnsGrokReply: Query mismatch (%s != %s)\n", q->query.name, message->query->name); rfc1035MessageDestroy(message); @@ -823,6 +857,9 @@ return; } } + if (q_pair) + n = n + 10000; + debug(78, 3) ("idnsGrokReply: id %d pair %d: %d\n", q->id, q_pair ? q->id_pair: -1, n); idnsCallback(q, message->answer, n, q->error); rfc1035MessageDestroy(message); @@ -835,7 +872,7 @@ { int *N = &incoming_sockets_accepted; ssize_t len; - struct sockaddr_in from; + struct sockaddr_storage from; socklen_t from_len; int max = INCOMING_DNS_MAX; static char rbuf[SQUID_UDP_SO_RCVBUF]; @@ -861,13 +898,13 @@ fd, xstrerror()); break; } - fd_bytes(DnsSocket, len, FD_READ); + fd_bytes(fd, len, FD_READ); assert(N); (*N)++; debug(78, 3) ("idnsRead: FD %d: received %d bytes from %s.\n", fd, (int) len, - inet_ntoa(from.sin_addr)); + sockaddr_ntoa(&from)); ns = idnsFromKnownNameserver(&from); if (ns >= 0) { nameservers[ns].nreplies++; @@ -875,7 +912,7 @@ static time_t last_warning = 0; if (squid_curtime - last_warning > 60) { debug(78, 1) ("WARNING: Reply from unknown nameserver [%s]\n", - inet_ntoa(from.sin_addr)); + sockaddr_ntoa(&from)); last_warning = squid_curtime; } continue; @@ -883,7 +920,7 @@ idnsGrokReply(rbuf, len); } if (lru_list.head) - commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0); + commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0); } static void @@ -945,15 +982,15 @@ CBDATA_INIT_TYPE(idns_query); if (DnsSocket < 0) { int port; - struct in_addr addr; - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) - addr = Config.Addrs.udp_outgoing; - else - addr = Config.Addrs.udp_incoming; + struct sockaddr_storage addr; + memset(&addr, 0, sizeof(addr)); + addr.ss_family = AF_INET; +#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + addr.ss_len = sizeof(struct sockaddr_in); +#endif DnsSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, - addr, - 0, + &addr, COMM_NONBLOCKING, "DNS Socket"); if (DnsSocket < 0) @@ -963,9 +1000,32 @@ */ port = comm_local_port(DnsSocket); debug(78, 1) ("DNS Socket created at %s, port %d, FD %d\n", - inet_ntoa(addr), + sockaddr_ntoa(&addr), port, DnsSocket); } + if (DnsSocket6 < 0) { + int port; + struct sockaddr_storage addr; + memset(&addr, 0, sizeof(addr)); + addr.ss_family = AF_INET6; +#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + addr.ss_len = sizeof(struct sockaddr_in6); +#endif + DnsSocket6 = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + &addr, + COMM_NONBLOCKING, + "DNS Socket v6"); + if (DnsSocket < 0) + fatal("Could not create a DNS socket"); + /* Ouch... we can't call functions using debug from a debug + * statement. Doing so messes up the internal _db_level + */ + port = comm_local_port(DnsSocket6); + debug(78, 1) ("DNS Socket v6 created at %s, port %d, FD %d\n", + sockaddr_ntoa(&addr), + port, DnsSocket6); + } assert(0 == nns); idnsParseNameservers(); #ifndef _SQUID_MSWIN_ @@ -1000,10 +1060,12 @@ void idnsShutdown(void) { - if (DnsSocket < 0) + if (DnsSocket < 0 && DnsSocket6 < 0) return; comm_close(DnsSocket); + comm_close(DnsSocket6); DnsSocket = -1; + DnsSocket6 = -1; idnsFreeNameservers(); idnsFreeSearchpath(); } @@ -1028,21 +1090,84 @@ static void idnsCacheQuery(idns_query * q) { - q->hash.key = q->query.name; + q->hash.key = q->query_key; hash_join(idns_lookup_hash, &q->hash); } +static void +idnsAAAALookup(const char *name, IDNSCB * callback, void *data, unsigned short id_pair, unsigned short id) +{ + unsigned int i; + int nd = 0; + idns_query *q; + char query_key[RFC1035_MAXHOSTNAMESZ+5]; + snprintf(query_key, RFC1035_MAXHOSTNAMESZ+5, "%s%d", name, RFC1035_TYPE_AAAA); + if (idnsCachedLookup(query_key, callback, data)) + return; + if (!id_pair && !id) + return; + q = cbdataAlloc(idns_query); + q->tcp_socket = -1; + q->id = id; + q->id_pair = id_pair; + + for (i = 0; i < strlen(name); i++) { + if (name[i] == '.') { + nd++; + } + } + + if (Config.onoff.res_defnames && npc > 0 && name[strlen(name) - 1] != '.') { + q->do_searchpath = 1; + } else { + q->do_searchpath = 0; + } + strcpy(q->orig, name); + strcpy(q->name, q->orig); + if (q->do_searchpath && nd < ndots) { + q->domain = 0; + strcat(q->name, "."); + strcat(q->name, searchpath[q->domain].domain); + debug(78, 3) ("idnsALookup: searchpath used for %s\n", + q->name); + } + q->sz = rfc1035BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->id, + &q->query); + + if (q->sz < 0) { + /* problem with query data -- query not sent */ + callback(data, NULL, 0, "Internal error"); + cbdataFree(q); + return; + } + debug(78, 3) ("idnsAAAALookup: buf is %d bytes for %s, id = %#hx\n", + (int) q->sz, q->name, q->id); + snprintf(q->query_key, RFC1035_MAXHOSTNAMESZ+5, "%s%d", q->query.name, q->query.qtype); + q->callback = callback; + q->callback_data = data; + cbdataLock(q->callback_data); + q->start_t = current_time; + idnsCacheQuery(q); + idnsSendQuery(q); +} + + void idnsALookup(const char *name, IDNSCB * callback, void *data) { unsigned int i; int nd = 0; idns_query *q; - if (idnsCachedLookup(name, callback, data)) + char query_key[RFC1035_MAXHOSTNAMESZ+5]; + snprintf(query_key, RFC1035_MAXHOSTNAMESZ+5, "%s%d", name, RFC1035_TYPE_A); + if (idnsCachedLookup(query_key, callback, data)) { + idnsAAAALookup(name, callback, data, 0, 0); return; + } q = cbdataAlloc(idns_query); q->tcp_socket = -1; q->id = idnsQueryID(); + q->id_pair = idnsQueryID(); for (i = 0; i < strlen(name); i++) { if (name[i] == '.') { @@ -1075,19 +1200,21 @@ } debug(78, 3) ("idnsALookup: buf is %d bytes for %s, id = %#hx\n", (int) q->sz, q->name, q->id); + snprintf(q->query_key, RFC1035_MAXHOSTNAMESZ+5, "%s%d", q->query.name, q->query.qtype); q->callback = callback; q->callback_data = data; cbdataLock(q->callback_data); q->start_t = current_time; idnsCacheQuery(q); idnsSendQuery(q); + idnsAAAALookup(name, callback, data, q->id, q->id_pair); } void -idnsPTRLookup(const struct in_addr addr, IDNSCB * callback, void *data) +idnsPTRLookup(const struct sockaddr *addr, IDNSCB * callback, void *data) { idns_query *q; - const char *ip = inet_ntoa(addr); + const char *ip = sockaddr_ntoa(addr); q = cbdataAlloc(idns_query); q->tcp_socket = -1; q->id = idnsQueryID(); Index: src/errorpage.c =================================================================== RCS file: /cvsroot/squid/squid/src/errorpage.c,v retrieving revision 1.190 diff -u -I\$Id -r1.190 errorpage.c --- src/errorpage.c 19 Jan 2007 00:21:01 -0000 1.190 +++ src/errorpage.c 5 Jul 2008 09:37:35 -0000 @@ -507,7 +507,7 @@ p = "[unknown host]"; break; case 'i': - memBufPrintf(&mb, "%s", inet_ntoa(err->src_addr)); + memBufPrintf(&mb, "%s", sockaddr_ntoa(&err->src_addr)); break; case 'I': if (r && r->hier.host) { Index: src/external_acl.c =================================================================== RCS file: /cvsroot/squid/squid/src/external_acl.c,v retrieving revision 1.29 diff -u -I\$Id -r1.29 external_acl.c --- src/external_acl.c 1 Jan 2007 23:32:13 -0000 1.29 +++ src/external_acl.c 5 Jul 2008 09:37:35 -0000 @@ -639,14 +639,14 @@ break; #endif case EXT_ACL_SRC: - str = inet_ntoa(ch->src_addr); + str = sockaddr_ntoa(&ch->src_addr); break; case EXT_ACL_SRCPORT: snprintf(buf, sizeof(buf), "%d", request->client_port); str = buf; break; case EXT_ACL_MYADDR: - str = inet_ntoa(request->my_addr); + str = sockaddr_ntoa(&request->my_addr); break; case EXT_ACL_MYPORT: snprintf(buf, sizeof(buf), "%d", request->my_port); Index: src/forward.c =================================================================== RCS file: /cvsroot/squid/squid/src/forward.c,v retrieving revision 1.120.2.3 diff -u -I\$Id -r1.120.2.3 forward.c --- src/forward.c 17 Apr 2007 09:35:17 -0000 1.120.2.3 +++ src/forward.c 5 Jul 2008 09:37:35 -0000 @@ -348,6 +348,15 @@ err->dnsserver_msg = xstrdup(dns_error_message); fwdFail(fwdState, err); comm_close(server_fd); + } else if (status == COMM_ERR_INV_ARGS) { + assert(fs); + err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, fwdState->request); + err->xerrno = errno; + fwdState->server_fd_was_inv_args = 1; + fwdFail(fwdState, err); + if (fs->peer) + peerConnectFailed(fs->peer); + comm_close(server_fd); } else if (status != COMM_OK) { assert(fs); err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, fwdState->request); @@ -387,23 +396,32 @@ /* * This marks the peer DOWN ... */ - if (fwdState->servers) + if (fwdState->servers) { if (fwdState->servers->peer) peerConnectFailed(fwdState->servers->peer); + if (fwdState->servers->code == HIER_DIRECT) { + struct sockaddr_storage host_addr; + safe_inet_addr(fwdState->request->hier.host, (struct sockaddr *)&host_addr); + ipcacheMarkBadAddr(fwdState->request->host, (struct sockaddr *)&host_addr); + } + } } comm_close(fd); } -static struct in_addr +static struct sockaddr_storage * aclMapAddr(acl_address * head, aclCheck_t * ch) { acl_address *l; - struct in_addr addr; + struct sockaddr_storage *addr; + struct sockaddr_in *addr4; for (l = head; l; l = l->next) { if (aclMatchAclList(l->acl_list, ch)) - return l->addr; + return &l->addr; } - addr.s_addr = INADDR_ANY; + addr = xmalloc(sizeof(struct sockaddr_storage)); + addr4 = (struct sockaddr_in *)addr; + addr4->sin_addr.s_addr = INADDR_ANY; return addr; } @@ -418,14 +436,14 @@ return 0; } -struct in_addr +struct sockaddr_storage * getOutgoingAddr(request_t * request) { aclCheck_t ch; memset(&ch, '\0', sizeof(aclCheck_t)); if (request) { - ch.src_addr = request->client_addr; - ch.my_addr = request->my_addr; + xmemcpy(&ch.src_addr, &request->client_addr, sizeof(struct sockaddr_storage)); + xmemcpy(&ch.my_addr, &request->my_addr, sizeof(struct sockaddr_storage)); ch.my_port = request->my_port; ch.request = request; } @@ -439,7 +457,8 @@ memset(&ch, '\0', sizeof(aclCheck_t)); if (request) { ch.src_addr = request->client_addr; - ch.my_addr = request->my_addr; + xmemcpy(&ch.src_addr, &request->client_addr, sizeof(struct sockaddr_storage)); + xmemcpy(&ch.my_addr, &request->my_addr, sizeof(struct sockaddr_storage)); ch.my_port = request->my_port; ch.request = request; } @@ -456,11 +475,13 @@ FwdServer *fs = fwdState->servers; const char *host; const char *name; + char portstr[8]; unsigned short port; const char *domain = NULL; int ctimeout; int ftimeout = Config.Timeout.forward - (squid_curtime - fwdState->start); - struct in_addr outgoing; + struct sockaddr_storage outgoing, peerinfo; + struct addrinfo hints, *res; unsigned short tos; #if LINUX_TPROXY struct in_tproxy itp; @@ -469,6 +490,9 @@ assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); + debug(17, 3) (" fwdState: 0x%x was IPv6: %d tries: %d err: %d\n", + fwdState, fwdState->server_fd_was_v6, fwdState->n_tries, + fwdState->err ? fwdState->err->xerrno : 0); if (fs->peer) { host = fs->peer->host; name = fs->peer->name; @@ -517,7 +541,7 @@ fd = pconnPop(name, port, domain, &fwdState->request->client_addr, 0); #endif if (fd == -1) - fd = pconnPop(name, port, domain, NULL, 0); + fd = pconnPop(name, port, domain, NULL); if (fd != -1) { if (fwdCheckRetriable(fwdState)) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); @@ -545,15 +569,44 @@ #if URL_CHECKSUM_DEBUG assert(fwdState->entry->mem_obj->chksum == url_checksum(url)); #endif + + if (fwdState->server_fd_was_inv_args) { + fwdState->n_tries--; + if (!fs->peer) + fwdState->origin_tries--; + } + else + fwdState->ia_cur = -1; + memset(&outgoing, 0, sizeof(outgoing)); + if (fwdState->server_fd_was_v6) + outgoing.ss_family = fwdState->server_fd_was_inv_args ? + AF_INET : AF_INET6 ; + else + outgoing.ss_family = fwdState->server_fd_was_inv_args ? + AF_INET6 : AF_INET ; + fwdState->server_fd_was_inv_args = 0; + + if (fs->peer && fs->peer->in_addr.ss_family == AF_INET6) + outgoing.ss_family = AF_INET6; + if (outgoing.ss_family == AF_INET6) + fwdState->server_fd_was_v6 = 1; + else + fwdState->server_fd_was_v6 = 0; +#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + outgoing.ss_len = outgoing.ss_family == AF_INET6 ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); +#endif + tos = 0; +/* HUSNI skip ACL outgoing = getOutgoingAddr(fwdState->request); tos = getOutgoingTOS(fwdState->request); +*/ debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n", - inet_ntoa(outgoing), tos); + sockaddr_ntoa(&outgoing), tos); fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, - outgoing, - 0, + &outgoing, COMM_NONBLOCKING, tos, url); @@ -813,13 +866,13 @@ * from peer_digest.c, asn.c, netdb.c, etc and should always * be allowed. yuck, I know. */ - if (r->client_addr.s_addr != no_addr.s_addr && r->protocol != PROTO_INTERNAL && r->protocol != PROTO_CACHEOBJ) { + if (((struct sockaddr_in *)&r->client_addr)->sin_addr.s_addr != no_addr.s_addr && r->protocol != PROTO_INTERNAL && r->protocol != PROTO_CACHEOBJ) { /* * Check if this host is allowed to fetch MISSES from us (miss_access) */ memset(&ch, '\0', sizeof(aclCheck_t)); - ch.src_addr = r->client_addr; - ch.my_addr = r->my_addr; + xmemcpy(&ch.src_addr, &r->client_addr, sizeof(struct sockaddr_storage)); + xmemcpy(&ch.my_addr, &r->my_addr, sizeof(struct sockaddr_storage)); ch.my_port = r->my_port; ch.request = r; answer = aclCheckFast(Config.accessList.miss, &ch); @@ -871,9 +924,7 @@ #if LINUX_TPROXY /* If we need to transparently proxy the request * then we need the client source address and port */ - fwdState->src.sin_family = AF_INET; - fwdState->src.sin_addr = r->client_addr; - fwdState->src.sin_port = r->client_port; + xmemcpy(&fwdState->src, &r->client_addr, sizeof(struct sockaddr_storage)); #endif storeLockObject(e); @@ -947,6 +998,11 @@ err_type_str[errorState->type], httpStatusString(errorState->http_status), storeUrl(fwdState->entry)); + if (fwdState->server_fd_was_inv_args) { + errorStateFree(errorState); + return; + } + fwdState->server_fd_was_inv_args = 0; if (fwdState->err) errorStateFree(fwdState->err); fwdState->err = errorState; Index: src/fqdncache.c =================================================================== RCS file: /cvsroot/squid/squid/src/fqdncache.c,v retrieving revision 1.156 diff -u -I\$Id -r1.156 fqdncache.c --- src/fqdncache.c 30 May 2006 00:56:11 -0000 1.156 +++ src/fqdncache.c 5 Jul 2008 09:37:35 -0000 @@ -351,11 +351,12 @@ } void -fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerData) +fqdncache_nbgethostbyaddr(struct sockaddr *addr, FQDNH * handler, void *handlerData) { fqdncache_entry *f = NULL; - char *name = inet_ntoa(addr); + char name[80]; generic_cbdata *c; + getnameinfo(addr, SOCKLEN(addr), name, 80, NULL, 0, NULL); assert(handler); debug(35, 4) ("fqdncache_nbgethostbyaddr: Name '%s'.\n", name); FqdncacheStats.requests++; @@ -427,11 +428,12 @@ } const char * -fqdncache_gethostbyaddr(struct in_addr addr, int flags) +fqdncache_gethostbyaddr(struct sockaddr *addr, int flags) { - char *name = inet_ntoa(addr); + char name[80]; fqdncache_entry *f = NULL; struct in_addr ip; + getnameinfo(addr, SOCKLEN(addr), name, 80, NULL, 0, NULL); assert(name); FqdncacheStats.requests++; f = fqdncache_get(name); @@ -452,7 +454,7 @@ } dns_error_message = NULL; /* check if it's already a FQDN address in text form. */ - if (!safe_inet_addr(name, &ip)) + if (!safe_inet_addr(name, &ip)) return name; FqdncacheStats.misses++; if (flags & FQDN_LOOKUP_IF_MISS) @@ -506,13 +508,13 @@ } const char * -fqdnFromAddr(struct in_addr addr) +fqdnFromAddr(struct sockaddr *addr) { const char *n; - static char buf[32]; + static char buf[80]; if (Config.onoff.log_fqdn && (n = fqdncache_gethostbyaddr(addr, 0))) return n; - xstrncpy(buf, inet_ntoa(addr), 32); + xstrncpy(buf, sockaddr_ntoa(addr), 80); return buf; } Index: src/ftp.c =================================================================== RCS file: /cvsroot/squid/squid/src/ftp.c,v retrieving revision 1.342.2.2 diff -u -I\$Id -r1.342.2.2 ftp.c --- src/ftp.c 26 Mar 2007 23:41:43 -0000 1.342.2.2 +++ src/ftp.c 5 Jul 2008 09:37:35 -0000 @@ -81,6 +81,8 @@ }; typedef struct _Ftpdata { + hash_link hash; /* dummy, must be fist */ + int ia_cur; StoreEntry *entry; request_t *request; char user[MAX_URL]; @@ -1067,7 +1069,11 @@ strCat(ftpState->title_url, ftpState->user); strCat(ftpState->title_url, "@"); } + if (strchr(request->host, ':')) + strCat(ftpState->title_url, "["); strCat(ftpState->title_url, request->host); + if (strchr(request->host, ':')) + strCat(ftpState->title_url, "]"); if (request->port != urlDefaultPort(PROTO_FTP)) { strCat(ftpState->title_url, ":"); strCat(ftpState->title_url, xitoa(request->port)); @@ -1727,7 +1733,7 @@ ftpSendPasv(FtpStateData * ftpState) { int fd; - struct sockaddr_in addr; + struct sockaddr_storage addr; socklen_t addr_len; if (ftpState->request->method == METHOD_HEAD && (ftpState->flags.isdir || ftpState->size != -1)) { /* Terminate here for HEAD requests */ @@ -1760,10 +1766,14 @@ return; } /* Open data channel with the same local address as control channel */ + if (addr.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&addr)->sin6_port = 0; + else + ((struct sockaddr_in *)&addr)->sin_port = 0; + fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - addr.sin_addr, - 0, + &addr, COMM_NONBLOCKING, storeUrl(ftpState->entry)); debug(9, 3) ("ftpSendPasv: Unconnected data socket created on FD %d\n", fd); @@ -1782,7 +1792,10 @@ * managed correctly and comm close handlers are cbdata fenced */ ftpState->data.fd = fd; - snprintf(cbuf, 1024, "PASV\r\n"); + if (addr.ss_family == AF_INET6) + snprintf(cbuf, 1024, "EPSV\r\n"); + else + snprintf(cbuf, 1024, "PASV\r\n"); ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_PASV; /* @@ -1803,12 +1816,22 @@ int fd = ftpState->data.fd; char *buf; LOCAL_ARRAY(char, ipaddr, 1024); + struct sockaddr_storage ipaddr_sock; + socklen_t addr_len; debug(9, 3) ("This is ftpReadPasv\n"); - if (code != 227) { + addr_len = sizeof(ipaddr_sock); + if (getsockname(ftpState->ctrl.fd, (struct sockaddr *) &ipaddr_sock, &addr_len)) { + debug(9, 0) ("ftpSendPasv: getsockname(%d,..): %s\n", + ftpState->ctrl.fd, xstrerror()); + ftpFail(ftpState); + return; + } + if (code != 227 && code != 229) { debug(9, 3) ("PASV not supported by remote end\n"); ftpSendPort(ftpState); return; } + if (code == 227) { /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ /* ANSI sez [^0-9] is undefined, it breaks on Watcom cc */ debug(9, 5) ("scanning: %s\n", ftpState->ctrl.last_reply); @@ -1820,12 +1843,24 @@ return; } snprintf(ipaddr, 1024, "%d.%d.%d.%d", h1, h2, h3, h4); - if (!safe_inet_addr(ipaddr, NULL)) { + port = ((p1 << 8) + p2); + memset(&ipaddr_sock, 0, sizeof(ipaddr_sock)); + if (!safe_inet_addr(ipaddr, &ipaddr_sock)) { debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); ftpSendPort(ftpState); return; } - port = ((p1 << 8) + p2); + } + if (code == 229) { + debug(9, 5) ("scanning: %s\n", ftpState->ctrl.last_reply); + buf = ftpState->ctrl.last_reply + strcspn(ftpState->ctrl.last_reply, "("); + n = sscanf(buf, "(|||%d||)",&p1); + port = p1; + } + if (ipaddr_sock.ss_family == AF_INET) + ((struct sockaddr_in *)&ipaddr_sock)->sin_port = htons(port); + if (ipaddr_sock.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&ipaddr_sock)->sin6_port = htons(port); if (0 == port) { debug(9, 1) ("Unsafe PASV reply from %s: %s\n", fd_table[ftpState->ctrl.fd].ipaddr, ftpState->ctrl.last_reply); ftpSendPort(ftpState); @@ -1842,12 +1877,13 @@ if (Config.Ftp.sanitycheck) ftpState->data.host = xstrdup(fd_table[ftpState->ctrl.fd].ipaddr); else - ftpState->data.host = xstrdup(ipaddr); + ftpState->data.host = xstrdup(sockaddr_ntoa(&ipaddr_sock)); safe_free(ftpState->ctrl.last_command); safe_free(ftpState->ctrl.last_reply); ftpState->ctrl.last_command = xstrdup("Connect to server data port"); + ftpState->ia_cur = -1; debug(9, 5) ("ftpReadPasv: connecting to %s, port %d\n", ftpState->data.host, ftpState->data.port); - commConnectStart(fd, ipaddr, port, ftpPasvCallback, ftpState); + commConnectStart(fd, ftpState->data.host, port, ftpPasvCallback, ftpState); } static void @@ -1870,7 +1906,7 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) { int fd; - struct sockaddr_in addr; + struct sockaddr_storage addr; socklen_t addr_len; int on = 1; u_short port = 0; @@ -1898,12 +1934,18 @@ */ if (fallback) { setsockopt(ftpState->ctrl.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); - port = ntohs(addr.sin_port); + port = (addr.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&addr)->sin6_port) : + ntohs(((struct sockaddr_in *)&addr)->sin_port); } + else + if (addr.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&addr)->sin6_port = 0; + else + ((struct sockaddr_in *)&addr)->sin_port = 0; fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - addr.sin_addr, - port, + &addr, COMM_NONBLOCKING | (fallback ? COMM_REUSEADDR : 0), storeUrl(ftpState->entry)); debug(9, 3) ("ftpOpenListenSocket: Unconnected data socket created on FD %d\n", fd); @@ -1925,7 +1967,7 @@ ftpSendPort(FtpStateData * ftpState) { int fd; - struct sockaddr_in addr; + struct sockaddr_storage addr; socklen_t addr_len; unsigned char *addrptr; unsigned char *portptr; @@ -1939,11 +1981,18 @@ ftpFail(ftpState); return; } - addrptr = (unsigned char *) &addr.sin_addr.s_addr; - portptr = (unsigned char *) &addr.sin_port; + if (addr.ss_family == AF_INET) { + addrptr = (unsigned char *) &((struct sockaddr_in *)&addr)->sin_addr.s_addr; + portptr = (unsigned char *) &((struct sockaddr_in *)&addr)->sin_port; snprintf(cbuf, 1024, "PORT %d,%d,%d,%d,%d,%d\r\n", addrptr[0], addrptr[1], addrptr[2], addrptr[3], portptr[0], portptr[1]); + } + if (addr.ss_family == AF_INET6) { + snprintf(cbuf, 1024, "EPRT |2|%s|%u|\r\n", + sockaddr_ntoa(&addr), + ntohs(((struct sockaddr_in6 *)&addr)->sin6_port)); + } ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_PORT; } @@ -1966,7 +2015,7 @@ ftpAcceptDataConnection(int fd, void *data) { FtpStateData *ftpState = data; - struct sockaddr_in my_peer, me; + struct sockaddr_storage my_peer, me; debug(9, 3) ("ftpAcceptDataConnection\n"); if (EBIT_TEST(ftpState->entry->flags, ENTRY_ABORTED)) { @@ -1975,9 +2024,12 @@ } fd = comm_accept(fd, &my_peer, &me); if (Config.Ftp.sanitycheck) { - char *ipaddr = inet_ntoa(my_peer.sin_addr); - if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ipaddr) != 0) { - debug(9, 1) ("FTP data connection from unexpected server (%s:%d), expecting %s\n", ipaddr, (int) ntohs(my_peer.sin_port), fd_table[ftpState->ctrl.fd].ipaddr); + if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, sockaddr_ntoa(&my_peer)) != 0) { + debug(9, 1) ("FTP data connection from unexpected server (%s:%d), expecting %s\n", sockaddr_ntoa(&my_peer), (int)( + my_peer.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&my_peer)->sin6_port) : + ntohs(((struct sockaddr_in *)&my_peer)->sin_port) ), + fd_table[ftpState->ctrl.fd].ipaddr); comm_close(fd); commSetSelect(ftpState->data.fd, COMM_SELECT_READ, @@ -1997,8 +2049,10 @@ comm_close(ftpState->data.fd); debug(9, 3) ("ftpAcceptDataConnection: Connected data socket on FD %d\n", fd); ftpState->data.fd = fd; - ftpState->data.port = ntohs(my_peer.sin_port); - ftpState->data.host = xstrdup(inet_ntoa(my_peer.sin_addr)); + ftpState->data.port = my_peer.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&my_peer)->sin6_port) : + ntohs(((struct sockaddr_in *)&my_peer)->sin_port); + ftpState->data.host = xstrdup(sockaddr_ntoa(&my_peer)); commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState); Index: src/globals.h =================================================================== RCS file: /cvsroot/squid/squid/src/globals.h,v retrieving revision 1.123 diff -u -I\$Id -r1.123 globals.h --- src/globals.h 19 Jan 2007 00:19:26 -0000 1.123 +++ src/globals.h 5 Jul 2008 09:37:35 -0000 @@ -97,6 +97,9 @@ extern int theInIcpConnection; /* -1 */ extern int theOutIcpConnection; /* -1 */ extern int DnsSocket; /* -1 */ +extern int theInIcpConnection6; /* -1 */ +extern int theOutIcpConnection6; /* -1 */ +extern int DnsSocket6; /* -1 */ #ifdef SQUID_SNMP extern int theInSnmpConnection; /* -1 */ extern int theOutSnmpConnection; /* -1 */ @@ -108,7 +111,8 @@ extern struct in_addr any_addr; extern struct in_addr local_addr; extern struct in_addr no_addr; -extern struct in_addr theOutICPAddr; +extern struct sockaddr_storage theOutICPAddr; +extern struct sockaddr_storage theOutICPAddr6; extern struct in_addr theOutSNMPAddr; extern struct timeval current_time; extern struct timeval squid_start; Index: src/htcp.c =================================================================== RCS file: /cvsroot/squid/squid/src/htcp.c,v retrieving revision 1.54 diff -u -I\$Id -r1.54 htcp.c --- src/htcp.c 4 Nov 2006 14:14:07 -0000 1.54 +++ src/htcp.c 5 Jul 2008 09:37:35 -0000 @@ -176,10 +176,12 @@ static u_num32 msg_id_counter = 0; static int htcpInSocket = -1; static int htcpOutSocket = -1; +static int htcpInSocket6 = -1; +static int htcpOutSocket6 = -1; #define N_QUERIED_KEYS 8192 static u_num32 queried_id[N_QUERIED_KEYS]; static cache_key queried_keys[N_QUERIED_KEYS][MD5_DIGEST_CHARS]; -static struct sockaddr_in queried_addr[N_QUERIED_KEYS]; +static struct sockaddr_storage queried_addr[N_QUERIED_KEYS]; static MemPool *htcpSpecifierPool = NULL; static MemPool *htcpDetailPool = NULL; @@ -195,17 +197,17 @@ static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff); static void htcpFreeSpecifier(htcpSpecifier * s); static void htcpFreeDetail(htcpDetail * s); -static void htcpHandle(char *buf, int sz, struct sockaddr_in *from); -static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from); -static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); -static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); -static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); -static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); +static void htcpHandle(char *buf, int sz, struct sockaddr *from); +static void htcpHandleData(char *buf, int sz, struct sockaddr *from); +static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr *from); +static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr *from); +static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr *from); +static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr *from); static void htcpRecv(int fd, void *data); -static void htcpSend(const char *buf, int len, struct sockaddr_in *to); -static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr_in *); -static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); -static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *); +static void htcpSend(const char *buf, int len, struct sockaddr *to); +static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr *); +static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr *from); +static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr *); static StoreEntry *htcpCheckHit(const htcpSpecifier *); static int old_squid_format = 0; @@ -436,15 +438,18 @@ } static void -htcpSend(const char *buf, int len, struct sockaddr_in *to) +htcpSend(const char *buf, int len, struct sockaddr *to) { int x; debug(31, 3) ("htcpSend: %s/%d\n", - inet_ntoa(to->sin_addr), (int) ntohs(to->sin_port)); + sockaddr_ntoa(to), (int) (to->sa_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)to)->sin6_port) : + ntohs(((struct sockaddr_in *)to)->sin_port) + ); htcpHexdump("htcpSend", buf, len); x = comm_udp_sendto(htcpOutSocket, to, - sizeof(struct sockaddr_in), + sizeof(struct sockaddr_storage), buf, len); if (x < 0) @@ -624,18 +629,27 @@ } static int -htcpAccessCheck(acl_access * acl, htcpSpecifier * s, struct sockaddr_in *from) +htcpAccessCheck(acl_access * acl, htcpSpecifier * s, struct sockaddr *from) { aclCheck_t checklist; + struct sockaddr_storage no_addr6; + + safe_inet_addr("ffff:ffff:ffff:ffff:fffff:ffff:ffff:ffff", &no_addr6); memset(&checklist, '\0', sizeof(checklist)); - checklist.src_addr = from->sin_addr; - checklist.my_addr = no_addr; + xmemcpy(&checklist.src_addr, from, sizeof(struct sockaddr_storage)); + if (from->sa_family == AF_INET) { + ((struct sockaddr *)&checklist.my_addr)->sa_family = AF_INET; + ((struct sockaddr_in *)&checklist.my_addr)->sin_addr = no_addr; + } + else { + xmemcpy(&checklist.my_addr, &no_addr6, sizeof(struct sockaddr_storage)); + } checklist.request = s->request; return aclCheckFast(acl, &checklist); } static void -htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from) +htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr *from) { htcpStuff stuff; static char pkt[8192]; @@ -707,7 +721,7 @@ } static void -htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, struct sockaddr_in *from) +htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, struct sockaddr *from) { htcpStuff stuff; static char pkt[8192]; @@ -733,7 +747,7 @@ } static void -htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr *from) { debug(31, 3) ("htcpHandleNop: Unimplemented\n"); } @@ -815,7 +829,7 @@ } static void -htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr *from) { debug(31, 3) ("htcpHandleTst: sz = %d\n", (int) sz); if (hdr->RR == RR_REQUEST) @@ -825,26 +839,31 @@ } static void -htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr *from) { htcpReplyData htcpReply; cache_key *key = NULL; - struct sockaddr_in *peer; + struct sockaddr_storage *peer; htcpDetail *d = NULL; char *t; if (queried_id[hdr->msg_id % N_QUERIED_KEYS] != hdr->msg_id) { - debug(31, 2) ("htcpHandleTstResponse: No matching query id '%d' (expected %d) from '%s'\n", hdr->msg_id, queried_id[hdr->msg_id % N_QUERIED_KEYS], inet_ntoa(from->sin_addr)); + debug(31, 2) ("htcpHandleTstResponse: No matching query id '%d' (expected %d) from '%s'\n", hdr->msg_id, queried_id[hdr->msg_id % N_QUERIED_KEYS], sockaddr_ntoa(from)); return; } key = queried_keys[hdr->msg_id % N_QUERIED_KEYS]; if (!key) { - debug(31, 1) ("htcpHandleTstResponse: No query key for response id '%d' from '%s'\n", hdr->msg_id, inet_ntoa(from->sin_addr)); + debug(31, 1) ("htcpHandleTstResponse: No query key for response id '%d' from '%s'\n", hdr->msg_id, sockaddr_ntoa(from)); return; } peer = &queried_addr[hdr->msg_id % N_QUERIED_KEYS]; - if (peer->sin_addr.s_addr != from->sin_addr.s_addr || peer->sin_port != from->sin_port) { - debug(31, 1) ("htcpHandleTstResponse: Unexpected response source %s\n", inet_ntoa(from->sin_addr)); + if ((peer->ss_family != from->sa_family) || + (peer->ss_family == AF_INET6 && + (!memcmp(&((struct sockaddr_in6 *)peer)->sin6_addr, &((struct sockaddr_in6 *)from)->sin6_addr, sizeof(struct in6_addr)) || ((struct sockaddr_in6 *)peer)->sin6_port != ((struct sockaddr_in6 *)from)->sin6_port)) || + (peer->ss_family == AF_INET && + (!memcmp(&((struct sockaddr_in *)peer)->sin_addr, &((struct sockaddr_in6 *)from)->sin6_addr, sizeof(struct in_addr)) || ((struct sockaddr_in6 *)peer)->sin6_port != ((struct sockaddr_in6 *)from)->sin6_port)) ) { +/* if (peer->sin_addr.s_addr != from->sin_addr.s_addr || peer->sin_port != from->sin_port) {*/ + debug(31, 1) ("htcpHandleTstResponse: Unexpected response source %s\n", sockaddr_ntoa(from)); return; } if (hdr->F1 == 1) { @@ -880,7 +899,7 @@ } static void -htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr *from) { /* buf should be a SPECIFIER */ htcpSpecifier *s; @@ -919,19 +938,19 @@ } static void -htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr *from) { debug(31, 3) ("htcpHandleMon: Unimplemented\n"); } static void -htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr *from) { debug(31, 3) ("htcpHandleSet: Unimplemented\n"); } static void -htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr *from) { htcpSpecifier *s; /* buf[0/1] is reserved and reason */ @@ -979,7 +998,7 @@ } static void -htcpHandleData(char *buf, int sz, struct sockaddr_in *from) +htcpHandleData(char *buf, int sz, struct sockaddr *from) { htcpDataHeader hdr; if (sz < sizeof(htcpDataHeader)) { @@ -1005,7 +1024,7 @@ debug(31, 3) ("htcpHandleData: length = %d\n", (int) hdr.length); if (hdr.opcode >= HTCP_END) { debug(31, 1) ("htcpHandleData: client %s, opcode %d out of range\n", - inet_ntoa(from->sin_addr), + sockaddr_ntoa(from), (int) hdr.opcode); return; } @@ -1050,7 +1069,7 @@ } static void -htcpHandle(char *buf, int sz, struct sockaddr_in *from) +htcpHandle(char *buf, int sz, struct sockaddr *from) { htcpHeader htcpHdr; if (sz < sizeof(htcpHeader)) { @@ -1070,13 +1089,17 @@ if (sz != htcpHdr.length) { debug(31, 1) ("htcpHandle: sz/%d != htcpHdr.length/%d from %s:%d\n", sz, htcpHdr.length, - inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port)); + sockaddr_ntoa(from), (int) from->sa_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)from)->sin6_port) : + ntohs(((struct sockaddr_in *)from)->sin_port) ); return; } if (htcpHdr.major != 0) { debug(31, 1) ("htcpHandle: Unknown major version %d from %s:%d\n", htcpHdr.major, - inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port)); + sockaddr_ntoa(from), (int) from->sa_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)from)->sin6_port) : + ntohs(((struct sockaddr_in *)from)->sin_port) ); return; } buf += sizeof(htcpHeader); @@ -1089,14 +1112,17 @@ { static char buf[8192]; int len; - static struct sockaddr_in from; - socklen_t flen = sizeof(struct sockaddr_in); + static struct sockaddr_storage from; + socklen_t flen = sizeof(struct sockaddr_storage); memset(&from, '\0', flen); statCounter.syscalls.sock.recvfroms++; /* Receive up to 8191 bytes, leaving room for a null */ len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &from, &flen); debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%d\n", - fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port)); + fd, len, + sockaddr_ntoa(&from), (int) from.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&from)->sin6_port) : + ntohs(((struct sockaddr_in *)&from)->sin_port) ); if (len) statCounter.htcp.pkts_recv++; htcpHandle(buf, len, &from); @@ -1112,29 +1138,47 @@ void htcpInit(void) { + u_short port; + struct sockaddr_storage addr; + struct sockaddr_storage xaddr; + if (Config.Port.htcp <= 0) { debug(31, 1) ("HTCP Disabled.\n"); return; } enter_suid(); + xmemcpy(&addr, &Config.Addrs.udp_incoming, sizeof(addr)); + ((struct sockaddr_in *)&addr)->sin_port = htons(Config.Port.htcp); htcpInSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.udp_incoming, - Config.Port.htcp, + &addr, COMM_NONBLOCKING, "HTCP Socket"); + xmemcpy(&addr, &Config.Addrs.udp6_incoming, sizeof(addr)); + ((struct sockaddr_in6 *)&addr)->sin6_port = htons(Config.Port.htcp); + htcpInSocket6 = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + &addr, + COMM_NONBLOCKING, + "HTCP Socket v6"); leave_suid(); if (htcpInSocket < 0) fatal("Cannot open HTCP Socket"); commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0); debug(31, 1) ("Accepting HTCP messages on port %d, FD %d.\n", (int) Config.Port.htcp, htcpInSocket); - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) { + if (htcpInSocket6 < 0) + fatal("Cannot open HTCP Socket v6"); + commSetSelect(htcpInSocket6, COMM_SELECT_READ, htcpRecv, NULL, 0); + debug(31, 1) ("Accepting HTCP messages v6 on port %d, FD %d.\n", + (int) Config.Port.htcp, htcpInSocket6); + if (((struct sockaddr_in *)&Config.Addrs.udp_outgoing)->sin_addr.s_addr != no_addr.s_addr) { enter_suid(); + xmemcpy(&addr, &Config.Addrs.udp_outgoing, sizeof(addr)); + ((struct sockaddr_in *)&addr)->sin_port = htons(Config.Port.htcp); htcpOutSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.udp_outgoing, - Config.Port.htcp, + &addr, COMM_NONBLOCKING, "Outgoing HTCP Socket"); leave_suid(); @@ -1147,6 +1191,24 @@ } else { htcpOutSocket = htcpInSocket; } + if (!IN6_IS_ADDR_ALLF(&((struct sockaddr_in6 *)&Config.Addrs.udp6_outgoing)->sin6_addr) ) { + xmemcpy(&addr, &Config.Addrs.udp6_outgoing, sizeof(addr)); + ((struct sockaddr_in6 *)&addr)->sin6_port = htons(Config.Port.htcp); + htcpOutSocket6 = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + &addr, + COMM_NONBLOCKING, + "Outgoing HTCP Socket"); + leave_suid(); + if (htcpOutSocket < 0) + fatal("Cannot open Outgoing HTCP Socket"); + commSetSelect(htcpOutSocket6, COMM_SELECT_READ, htcpRecv, NULL, 0); + debug(31, 1) ("Outgoing HTCP messages v6 on port %d, FD %d.\n", + (int) Config.Port.htcp, htcpOutSocket6); + fd_note(htcpInSocket, "Incoming HTCP socket v6"); + } else { + htcpOutSocket6 = htcpInSocket6; + } if (!htcpSpecifierPool) { htcpSpecifierPool = memPoolCreate("htcpSpecifier", sizeof(htcpSpecifier)); htcpDetailPool = memPoolCreate("htcpDetail", sizeof(htcpDetail)); @@ -1215,6 +1277,10 @@ debug(12, 1) ("FD %d Closing HTCP socket\n", htcpInSocket); comm_close(htcpInSocket); } + if (htcpInSocket6 != htcpOutSocket6) { + debug(12, 1) ("FD %d Closing HTCP socket v6\n", htcpInSocket6); + comm_close(htcpInSocket6); + } /* * Here we set 'htcpInSocket' to -1 even though the HTCP 'in' * and 'out' sockets might be just one FD. This prevents this @@ -1222,6 +1288,7 @@ * exit or restart, main will comm_close the 'out' descriptor. */ htcpInSocket = -1; + htcpInSocket6 = -1; /* * Normally we only write to the outgoing HTCP socket, but * we also have a read handler there to catch messages sent @@ -1233,6 +1300,8 @@ */ assert(htcpOutSocket > -1); commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0); + assert(htcpOutSocket6 > -1); + commSetSelect(htcpOutSocket6, COMM_SELECT_READ, NULL, NULL, 0); } void @@ -1244,4 +1313,9 @@ comm_close(htcpOutSocket); htcpOutSocket = -1; } + if (htcpOutSocket6 > -1) { + debug(12, 1) ("FD %d Closing HTCP socket v6\n", htcpOutSocket6); + comm_close(htcpOutSocket6); + htcpOutSocket6 = -1; + } } Index: src/http.c =================================================================== RCS file: /cvsroot/squid/squid/src/http.c,v retrieving revision 1.419.2.7 diff -u -I\$Id -r1.419.2.7 http.c --- src/http.c 26 Mar 2007 23:08:00 -0000 1.419.2.7 +++ src/http.c 5 Jul 2008 09:37:35 -0000 @@ -628,7 +628,7 @@ StoreEntry *entry = httpState->entry; const request_t *request = httpState->request; const request_t *orig_request = httpState->orig_request; - struct in_addr *client_addr = NULL; + struct sockaddr *client_addr = NULL; u_short client_port = 0; int fd = httpState->fd; int complete = httpState->eof; @@ -804,11 +804,11 @@ clientPinConnection(orig_request->pinned_connection, fd, orig_request, httpState->peer, request->flags.connection_auth); } else if (httpState->peer) { if (httpState->peer->options.originserver) - pconnPush(fd, httpState->peer->name, httpState->peer->http_port, httpState->orig_request->host, client_addr, client_port); + pconnPush(fd, httpState->peer->name, httpState->peer->http_port, httpState->orig_request->host, client_addr); else - pconnPush(fd, httpState->peer->name, httpState->peer->http_port, NULL, client_addr, client_port); + pconnPush(fd, httpState->peer->name, httpState->peer->http_port, NULL, client_addr); } else { - pconnPush(fd, request->host, request->port, NULL, client_addr, client_port); + pconnPush(fd, request->host, request->port, NULL, client_addr); } fwdComplete(httpState->fwd); httpState->fd = -1; @@ -1212,10 +1212,23 @@ } /* append X-Forwarded-For */ if (opt_forwarded_for) { + int known_addr = 0; strFwd = httpHeaderGetList(hdr_in, HDR_X_FORWARDED_FOR); + if ((orig_request->client_addr.ss_family == AF_INET) && + (((struct sockaddr_in *)&orig_request->client_addr)->sin_addr.s_addr != no_addr.s_addr) ) { strListAdd(&strFwd, - (((orig_request->client_addr.s_addr != no_addr.s_addr) && opt_forwarded_for) ? - inet_ntoa(orig_request->client_addr) : "unknown"), ','); + sockaddr_ntoa(&orig_request->client_addr), ','); + known_addr = 1; + } + if ((orig_request->client_addr.ss_family == AF_INET6) && + !IN6_IS_ADDR_ALLF(&((struct sockaddr_in6 *)&orig_request->client_addr)->sin6_addr)) { + strListAdd(&strFwd, + sockaddr_ntoa(&orig_request->client_addr), ','); + known_addr = 1; + } + if (!known_addr) + strListAdd(&strFwd, "unknown" , ','); + httpHeaderPutStr(hdr_out, HDR_X_FORWARDED_FOR, strBuf(strFwd)); stringClean(&strFwd); } @@ -1540,7 +1553,7 @@ if (httpState->reply_hdr_state >= 2 && !httpState->flags.abuse_detected) { httpState->flags.abuse_detected = 1; debug(11, 1) ("httpSendRequestEntryDone: Likely proxy abuse detected '%s' -> '%s'\n", - inet_ntoa(httpState->orig_request->client_addr), + sockaddr_ntoa(&httpState->orig_request->client_addr), storeUrl(httpState->entry)); if (httpState->entry->mem_obj->reply->sline.status == HTTP_INVALID_HEADER) { memFree8K(buf); Index: src/icp_v2.c =================================================================== RCS file: /cvsroot/squid/squid/src/icp_v2.c,v retrieving revision 1.72 diff -u -I\$Id -r1.72 icp_v2.c --- src/icp_v2.c 25 Jun 2006 15:53:14 -0000 1.72 +++ src/icp_v2.c 5 Jul 2008 09:37:35 -0000 @@ -35,8 +35,8 @@ #include "squid.h" -static void icpLogIcp(struct in_addr, log_type, int, const char *, int); -static void icpHandleIcpV2(int, struct sockaddr_in, char *, int); +static void icpLogIcp(struct sockaddr *, log_type, int, const char *, int); +static void icpHandleIcpV2(int, struct sockaddr *, char *, int); static void icpCount(void *, int, size_t, int); /* @@ -46,7 +46,7 @@ static icpUdpData *IcpQueueTail = NULL; static void -icpLogIcp(struct in_addr caddr, log_type logcode, int len, const char *url, int delay) +icpLogIcp(struct sockaddr *caddr, log_type logcode, int len, const char *url, int delay) { AccessLogEntry al; if (LOG_TAG_NONE == logcode) @@ -59,7 +59,7 @@ memset(&al, '\0', sizeof(al)); al.icp.opcode = ICP_QUERY; al.url = url; - al.cache.caddr = caddr; + xmemcpy(&al.cache.caddr, caddr, SOCKLEN(caddr)); al.cache.size = len; al.cache.code = logcode; al.cache.msec = delay; @@ -106,7 +106,7 @@ headerp->reqnum = htonl(reqnum); headerp->flags = htonl(flags); headerp->pad = htonl(pad); - headerp->shostid = theOutICPAddr.s_addr; + xmemcpy(&headerp->shostid, &theOutICPAddr, sizeof(struct sockaddr_storage)); urloffset = buf + sizeof(icp_common_t); if (opcode == ICP_QUERY) urloffset += sizeof(u_num32); @@ -116,7 +116,7 @@ int icpUdpSend(int fd, - const struct sockaddr_in *to, + const struct sockaddr *to, icp_common_t * msg, log_type logcode, int delay) @@ -124,23 +124,25 @@ icpUdpData *queue; int x; int len; + char host[100], port[8]; len = (int) ntohs(msg->length); - debug(12, 5) ("icpUdpSend: FD %d sending %s, %d bytes to %s:%d\n", + getnameinfo(to, SOCKLEN(to), host, 100, port, 8, NI_NUMERICHOST|NI_NUMERICSERV); + debug(12, 5) ("icpUdpSend: FD %d sending %s, %d bytes to %s:%s\n", fd, icp_opcode_str[msg->opcode], len, - inet_ntoa(to->sin_addr), - ntohs(to->sin_port)); - x = comm_udp_sendto(fd, to, sizeof(*to), msg, len); + host, + port); + x = comm_udp_sendto(fd, to, SOCKLEN(to), msg, len); if (x >= 0) { /* successfully written */ - icpLogIcp(to->sin_addr, logcode, len, (char *) (msg + 1), delay); + icpLogIcp(to, logcode, len, (char *) (msg + 1), delay); icpCount(msg, SENT, (size_t) len, delay); safe_free(msg); } else if (0 == delay) { /* send failed, but queue it */ queue = xcalloc(1, sizeof(icpUdpData)); - queue->address = *to; + xmemcpy(&queue->address, to, SOCKLEN(to)); queue->msg = msg; queue->len = (int) ntohs(msg->length); queue->queue_time = current_time; @@ -179,7 +181,7 @@ } static void -icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) +icpHandleIcpV2(int fd, struct sockaddr *from, char *buf, int len) { icp_common_t header; StoreEntry *entry = NULL; @@ -224,22 +226,23 @@ break; } memset(&checklist, '\0', sizeof(checklist)); - checklist.src_addr = from.sin_addr; - checklist.my_addr = no_addr; + xmemcpy(&checklist.src_addr, from, SOCKLEN(from)); + memset(&checklist.my_addr, 0, sizeof(checklist.my_addr)); + checklist.my_addr.ss_family = checklist.src_addr.ss_family; checklist.request = icp_request; allow = aclCheckFast(Config.accessList.icp, &checklist); if (!allow) { debug(12, 2) ("icpHandleIcpV2: Access Denied for %s by %s.\n", - inet_ntoa(from.sin_addr), AclMatchedName); - if (clientdbCutoffDenied(from.sin_addr)) { + sockaddr_ntoa(from), AclMatchedName); + if (clientdbCutoffDenied(from)) { /* * count this DENIED query in the clientdb, even though * we're not sending an ICP reply... */ - clientdbUpdate(from.sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0); + clientdbUpdate(from, LOG_UDP_DENIED, PROTO_ICP, 0); } else { reply = icpCreateMessage(ICP_DENIED, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_DENIED, 0); + icpUdpSend(fd, from, reply, LOG_UDP_DENIED, 0); } break; } @@ -255,7 +258,7 @@ debug(12, 5) ("icpHandleIcpV2: OPCODE %s\n", icp_opcode_str[header.opcode]); if (icpCheckUdpHit(entry, icp_request)) { reply = icpCreateMessage(ICP_HIT, flags, url, header.reqnum, src_rtt); - icpUdpSend(fd, &from, reply, LOG_UDP_HIT, 0); + icpUdpSend(fd, from, reply, LOG_UDP_HIT, 0); break; } if (Config.onoff.test_reachability && rtt == 0) { @@ -265,16 +268,16 @@ /* if store is rebuilding, return a UDP_HIT, but not a MISS */ if (store_dirs_rebuilding && opt_reload_hit_only) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (hit_only_mode_until > squid_curtime) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (Config.onoff.test_reachability && rtt == 0) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS_NOFETCH, 0); } else { reply = icpCreateMessage(ICP_MISS, flags, url, header.reqnum, src_rtt); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS, 0); } break; @@ -288,18 +291,18 @@ case ICP_MISS_NOFETCH: if (neighbors_do_private_keys && header.reqnum == 0) { debug(12, 0) ("icpHandleIcpV2: Neighbor %s returned reqnum = 0\n", - inet_ntoa(from.sin_addr)); + sockaddr_ntoa(from)); debug(12, 0) ("icpHandleIcpV2: Disabling use of private keys\n"); neighbors_do_private_keys = 0; } url = buf + sizeof(icp_common_t); debug(12, 3) ("icpHandleIcpV2: %s from %s for '%s'\n", icp_opcode_str[header.opcode], - inet_ntoa(from.sin_addr), + sockaddr_ntoa(from), url); key = icpGetCacheKey(url, (int) header.reqnum); /* call neighborsUdpAck even if ping_status != PING_WAITING */ - neighborsUdpAck(key, &header, &from); + neighborsUdpAck(key, &header, from); break; case ICP_INVALID: @@ -308,7 +311,7 @@ default: debug(12, 0) ("icpHandleIcpV2: UNKNOWN OPCODE: %d from %s\n", - header.opcode, inet_ntoa(from.sin_addr)); + header.opcode, sockaddr_ntoa(from)); break; } if (icp_request) @@ -338,7 +341,7 @@ icpHandleUdp(int sock, void *data) { int *N = &incoming_sockets_accepted; - struct sockaddr_in from; + struct sockaddr_storage from; socklen_t from_len; LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF); int len; @@ -377,7 +380,7 @@ debug(12, 4) ("icpHandleUdp: FD %d: received %d bytes from %s.\n", sock, len, - inet_ntoa(from.sin_addr)); + sockaddr_ntoa((struct sockaddr *)&from)); #ifdef ICP_PACKET_DUMP icpPktDump(buf); #endif @@ -387,14 +390,17 @@ } icp_version = (int) buf[1]; /* cheat! */ if (icp_version == ICP_VERSION_2) - icpHandleIcpV2(sock, from, buf, len); + icpHandleIcpV2(sock, &from, buf, len); else if (icp_version == ICP_VERSION_3) - icpHandleIcpV3(sock, from, buf, len); + icpHandleIcpV3(sock, &from, buf, len); else debug(12, 1) ("WARNING: Unused ICP version %d received from %s:%d\n", icp_version, - inet_ntoa(from.sin_addr), - ntohs(from.sin_port)); + sockaddr_ntoa((struct sockaddr *)&from), + from.ss_family == AF_INET6 ? + ntohs(((struct sockaddr_in6 *)&from)->sin6_port) : + ntohs(((struct sockaddr_in *)&from)->sin_port) + ); } } @@ -402,20 +408,28 @@ icpConnectionsOpen(void) { u_short port; - struct in_addr addr; - struct sockaddr_in xaddr; + struct sockaddr_storage addr; + struct sockaddr_storage xaddr; int x; socklen_t len; wordlist *s; if ((port = Config.Port.icp) <= 0) return; enter_suid(); + xmemcpy(&addr, &Config.Addrs.udp_incoming, sizeof(addr)); + ((struct sockaddr_in *)&addr)->sin_port = htons(port); theInIcpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.udp_incoming, - port, + &addr, COMM_NONBLOCKING, "ICP Socket"); + xmemcpy(&addr, &Config.Addrs.udp6_incoming, sizeof(addr)); + ((struct sockaddr_in6 *)&addr)->sin6_port = htons(port); + theInIcpConnection6 = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + &addr, + COMM_NONBLOCKING, + "ICP Socket v6"); leave_suid(); if (theInIcpConnection < 0) fatal("Cannot open ICP Port"); @@ -424,17 +438,29 @@ icpHandleUdp, NULL, 0); + if (theInIcpConnection6 < 0) + fatal("Cannot open ICP Port v6"); + commSetSelect(theInIcpConnection6, + COMM_SELECT_READ, + icpHandleUdp, + NULL, + 0); for (s = Config.mcast_group_list; s; s = s->next) ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); debug(12, 1) ("Accepting ICP messages at %s, port %d, FD %d.\n", - inet_ntoa(Config.Addrs.udp_incoming), + sockaddr_ntoa((struct sockaddr *)&Config.Addrs.udp_incoming), (int) port, theInIcpConnection); - if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) { + debug(12, 1) ("Accepting ICP messages v6 at %s, port %d, FD %d.\n", + sockaddr_ntoa((struct sockaddr *)&Config.Addrs.udp6_incoming), + (int) port, theInIcpConnection6); + + if (((struct sockaddr_in *)&Config.Addrs.udp_outgoing)->sin_addr.s_addr != no_addr.s_addr) { + xmemcpy(&addr, &Config.Addrs.udp_outgoing, sizeof(addr)); + ((struct sockaddr_in *)&addr)->sin_port = htons(port); enter_suid(); theOutIcpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - addr, - port, + &addr, COMM_NONBLOCKING, "ICP Port"); leave_suid(); @@ -452,8 +478,33 @@ } else { theOutIcpConnection = theInIcpConnection; } - memset(&theOutICPAddr, '\0', sizeof(struct in_addr)); - len = sizeof(struct sockaddr_in); + if (!IN6_IS_ADDR_ALLF(&((struct sockaddr_in6 *)&Config.Addrs.udp6_outgoing)->sin6_addr) ) { + xmemcpy(&addr, &Config.Addrs.udp6_outgoing, sizeof(addr)); + ((struct sockaddr_in6 *)&addr)->sin6_port = htons(port); + enter_suid(); + theOutIcpConnection6 = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + &addr, + COMM_NONBLOCKING, + "ICP Port v6"); + leave_suid(); + if (theOutIcpConnection6 < 0) + fatal("Cannot open Outgoing ICP Port v6"); + commSetSelect(theOutIcpConnection6, + COMM_SELECT_READ, + icpHandleUdp, + NULL, + 0); + debug(12, 1) ("Outgoing ICP messages v6 on port %d, FD %d.\n", + (int) port, theOutIcpConnection6); + fd_note(theOutIcpConnection6, "Outgoing ICP socket v6"); + fd_note(theInIcpConnection6, "Incoming ICP socket v6"); + } else { + theOutIcpConnection6 = theInIcpConnection6; + } + + memset(&theOutICPAddr, '\0', sizeof(struct sockaddr_storage)); + len = sizeof(struct sockaddr_storage); memset(&xaddr, '\0', len); x = getsockname(theOutIcpConnection, (struct sockaddr *) &xaddr, &len); @@ -461,7 +512,18 @@ debug(12, 1) ("theOutIcpConnection FD %d: getsockname: %s\n", theOutIcpConnection, xstrerror()); else - theOutICPAddr = xaddr.sin_addr; + xmemcpy(&theOutICPAddr, &xaddr, sizeof(xaddr)); + + memset(&theOutICPAddr6, '\0', sizeof(struct sockaddr_storage)); + len = sizeof(struct sockaddr_storage); + memset(&xaddr, '\0', len); + x = getsockname(theOutIcpConnection6, + (struct sockaddr *) &xaddr, &len); + if (x < 0) + debug(12, 1) ("theOutIcpConnection6 FD %d: getsockname: %s\n", + theOutIcpConnection6, xstrerror()); + else + xmemcpy(&theOutICPAddr6, &xaddr, sizeof(xaddr)); } /* @@ -471,12 +533,16 @@ void icpConnectionShutdown(void) { - if (theInIcpConnection < 0) + if (theInIcpConnection < 0 && theInIcpConnection6 < 0) return; - if (theInIcpConnection != theOutIcpConnection) { + if (theInIcpConnection > 0 && theInIcpConnection != theOutIcpConnection) { debug(12, 1) ("FD %d Closing ICP connection\n", theInIcpConnection); comm_close(theInIcpConnection); } + if (theInIcpConnection6> 0 && theInIcpConnection6!=theOutIcpConnection6) { + debug(12, 1) ("FD %d Closing ICP connection6\n", theInIcpConnection6); + comm_close(theInIcpConnection6); + } /* * Here we set 'theInIcpConnection' to -1 even though the ICP 'in' * and 'out' sockets might be just one FD. This prevents this @@ -484,6 +550,7 @@ * exit or restart, main will comm_close the 'out' descriptor. */ theInIcpConnection = -1; + theInIcpConnection6 = -1; /* * Normally we only write to the outgoing ICP socket, but * we also have a read handler there to catch messages sent @@ -491,7 +558,9 @@ * disable reading on the outgoing socket. */ assert(theOutIcpConnection > -1); + assert(theOutIcpConnection6 > -1); commSetSelect(theOutIcpConnection, COMM_SELECT_READ, NULL, NULL, 0); + commSetSelect(theOutIcpConnection6, COMM_SELECT_READ, NULL, NULL, 0); } void @@ -503,6 +572,11 @@ comm_close(theOutIcpConnection); theOutIcpConnection = -1; } + if (theOutIcpConnection6 > -1) { + debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection6); + comm_close(theOutIcpConnection6); + theOutIcpConnection6 = -1; + } } static void Index: src/icp_v3.c =================================================================== RCS file: /cvsroot/squid/squid/src/icp_v3.c,v retrieving revision 1.35 diff -u -I\$Id -r1.35 icp_v3.c --- src/icp_v3.c 17 May 2005 16:56:38 -0000 1.35 +++ src/icp_v3.c 5 Jul 2008 09:37:35 -0000 @@ -37,7 +37,7 @@ /* Currently Harvest cached-2.x uses ICP_VERSION_3 */ void -icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len) +icpHandleIcpV3(int fd, struct sockaddr *from, char *buf, int len) { icp_common_t header; icp_common_t *reply; @@ -69,31 +69,32 @@ if (strpbrk(url, w_space)) { url = rfc1738_escape(url); reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0); + icpUdpSend(fd, from, reply, LOG_UDP_INVALID, 0); break; } if ((icp_request = urlParse(METHOD_GET, url)) == NULL) { reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0); + icpUdpSend(fd, from, reply, LOG_UDP_INVALID, 0); break; } memset(&checklist, '\0', sizeof(checklist)); - checklist.src_addr = from.sin_addr; - checklist.my_addr = no_addr; + xmemcpy(&checklist.src_addr, from, SOCKLEN(from)); + memset(&checklist.my_addr, '\0', sizeof(checklist.my_addr)); + checklist.my_addr.ss_family = from->sa_family; checklist.request = icp_request; allow = aclCheckFast(Config.accessList.icp, &checklist); if (!allow) { debug(12, 2) ("icpHandleIcpV3: Access Denied for %s by %s.\n", - inet_ntoa(from.sin_addr), AclMatchedName); - if (clientdbCutoffDenied(from.sin_addr)) { + sockaddr_ntoa(from), AclMatchedName); + if (clientdbCutoffDenied(from)) { /* * count this DENIED query in the clientdb, even though * we're not sending an ICP reply... */ - clientdbUpdate(from.sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0); + clientdbUpdate(from, LOG_UDP_DENIED, PROTO_ICP, 0); } else { reply = icpCreateMessage(ICP_DENIED, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_DENIED, 0); + icpUdpSend(fd, from, reply, LOG_UDP_DENIED, 0); } break; } @@ -103,19 +104,19 @@ icp_opcode_str[header.opcode]); if (icpCheckUdpHit(entry, icp_request)) { reply = icpCreateMessage(ICP_HIT, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_HIT, 0); + icpUdpSend(fd, from, reply, LOG_UDP_HIT, 0); break; } /* if store is rebuilding, return a UDP_HIT, but not a MISS */ if (opt_reload_hit_only && store_dirs_rebuilding) { reply = icpCreateMessage(ICP_MISS_NOFETCH, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (hit_only_mode_until > squid_curtime) { reply = icpCreateMessage(ICP_MISS_NOFETCH, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS_NOFETCH, 0); } else { reply = icpCreateMessage(ICP_MISS, 0, url, header.reqnum, 0); - icpUdpSend(fd, &from, reply, LOG_UDP_MISS, 0); + icpUdpSend(fd, from, reply, LOG_UDP_MISS, 0); } break; @@ -129,18 +130,18 @@ case ICP_MISS_NOFETCH: if (neighbors_do_private_keys && header.reqnum == 0) { debug(12, 0) ("icpHandleIcpV3: Neighbor %s returned reqnum = 0\n", - inet_ntoa(from.sin_addr)); + sockaddr_ntoa(from)); debug(12, 0) ("icpHandleIcpV3: Disabling use of private keys\n"); neighbors_do_private_keys = 0; } url = buf + sizeof(icp_common_t); debug(12, 3) ("icpHandleIcpV3: %s from %s for '%s'\n", icp_opcode_str[header.opcode], - inet_ntoa(from.sin_addr), + sockaddr_ntoa(from), url); key = icpGetCacheKey(url, (int) header.reqnum); /* call neighborsUdpAck even if ping_status != PING_WAITING */ - neighborsUdpAck(key, &header, &from); + neighborsUdpAck(key, &header, from); break; case ICP_INVALID: @@ -149,7 +150,7 @@ default: debug(12, 0) ("icpHandleIcpV3: UNKNOWN OPCODE: %d from %s\n", - header.opcode, inet_ntoa(from.sin_addr)); + header.opcode, sockaddr_ntoa(from)); break; } if (icp_request) Index: src/ident.c =================================================================== RCS file: /cvsroot/squid/squid/src/ident.c,v retrieving revision 1.63 diff -u -I\$Id -r1.63 ident.c --- src/ident.c 12 May 2006 22:08:37 -0000 1.63 +++ src/ident.c 5 Jul 2008 09:37:35 -0000 @@ -48,9 +48,10 @@ typedef struct _IdentStateData { hash_link hash; /* must be first */ + int ia_cur; /* dummy, for commConnectStart */ int fd; /* IDENT fd */ - struct sockaddr_in me; - struct sockaddr_in my_peer; + struct sockaddr_storage me; + struct sockaddr_storage my_peer; IdentClient *clients; } IdentStateData; @@ -94,7 +95,7 @@ { IdentStateData *state = data; debug(30, 3) ("identTimeout: FD %d, %s\n", fd, - inet_ntoa(state->my_peer.sin_addr)); + sockaddr_ntoa(&state->my_peer)); comm_close(fd); } @@ -123,8 +124,12 @@ } memBufDefInit(&mb); memBufPrintf(&mb, "%d, %d\r\n", - ntohs(state->my_peer.sin_port), - ntohs(state->me.sin_port)); + (state->my_peer.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&state->my_peer)->sin6_port): + ntohs(((struct sockaddr_in *)&state->my_peer)->sin_port), + (state->my_peer.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&state->me)->sin6_port): + ntohs(((struct sockaddr_in *)&state->me)->sin_port) ); comm_write_mbuf(fd, mb, NULL, state); commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); @@ -187,19 +192,18 @@ * start a TCP connection to the peer host on port 113 */ void -identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) +identStart(struct sockaddr *me, struct sockaddr *my_peer, IDCB * callback, void *data) { IdentStateData *state; int fd; char key1[IDENT_KEY_SZ]; char key2[IDENT_KEY_SZ]; char key[IDENT_KEY_SZ]; - snprintf(key1, IDENT_KEY_SZ, "%s:%d", - inet_ntoa(me->sin_addr), - ntohs(me->sin_port)); - snprintf(key2, IDENT_KEY_SZ, "%s:%d", - inet_ntoa(my_peer->sin_addr), - ntohs(my_peer->sin_port)); + char ahost[100], aport[8]; + getnameinfo(me, SOCKLEN(me), ahost, 100, aport, 8, NI_NUMERICHOST|NI_NUMERICSERV); + snprintf(key1, IDENT_KEY_SZ, "%s:%s", ahost, aport); + getnameinfo(my_peer, SOCKLEN(my_peer), ahost, 100, aport, 8, NI_NUMERICHOST|NI_NUMERICSERV); + snprintf(key2, IDENT_KEY_SZ, "%s:%s", ahost, aport); snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2); if ((state = hash_lookup(ident_hash, key)) != NULL) { identClientAdd(state, callback, data); @@ -207,8 +211,7 @@ } fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - me->sin_addr, - 0, + me, COMM_NONBLOCKING, "ident"); if (fd == COMM_ERROR) { @@ -220,8 +223,8 @@ state = cbdataAlloc(IdentStateData); state->hash.key = xstrdup(key); state->fd = fd; - state->me = *me; - state->my_peer = *my_peer; + xmemcpy(&state->me, me, SOCKLEN(me)); + xmemcpy(&state->my_peer, my_peer, SOCKLEN(my_peer)); identClientAdd(state, callback, data); hash_join(ident_hash, &state->hash); comm_add_close_handler(fd, @@ -229,8 +232,7 @@ state); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); commConnectStart(fd, - inet_ntoa(state->my_peer.sin_addr), - IDENT_PORT, + sockaddr_ntoa(my_peer), IDENT_PORT, identConnectDone, state); } Index: src/internal.c =================================================================== RCS file: /cvsroot/squid/squid/src/internal.c,v retrieving revision 1.32 diff -u -I\$Id -r1.32 internal.c --- src/internal.c 25 Aug 2006 12:26:07 -0000 1.32 +++ src/internal.c 5 Jul 2008 09:37:35 -0000 @@ -46,7 +46,7 @@ const char *upath = strBuf(request->urlpath); http_version_t version; debug(76, 3) ("internalStart: %s requesting '%s'\n", - inet_ntoa(request->client_addr), upath); + sockaddr_ntoa(&request->client_addr), upath); if (0 == strcmp(upath, "/squid-internal-dynamic/netdb")) { netdbBinaryExchange(entry); } else if (0 == strcmp(upath, "/squid-internal-periodic/store_digest")) { @@ -99,10 +99,17 @@ /* convert host name to lower case */ xstrncpy(lc_host, host, SQUIDHOSTNAMELEN); Tolower(lc_host); + + /* + * host is IPv6 address + */ + if (strchr(lc_host, ':')) + snprintf(lc_host, SQUIDHOSTNAMELEN, "[%s]", host); /* * append the domain in order to mirror the requests with appended * domains */ + else if (Config.appendDomain && !strchr(lc_host, '.')) strncat(lc_host, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(lc_host) - 1); Index: src/ipc.c =================================================================== RCS file: /cvsroot/squid/squid/src/ipc.c,v retrieving revision 1.39 diff -u -I\$Id -r1.39 ipc.c --- src/ipc.c 8 Sep 2006 19:41:24 -0000 1.39 +++ src/ipc.c 5 Jul 2008 09:37:35 -0000 @@ -87,30 +87,32 @@ if (hIpc) *hIpc = NULL; + CS.sin_family = AF_INET; +#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + CS.sin_len = sizeof(CS); +#endif + CS.sin_addr = local_addr; + CS.sin_port = 0; if (type == IPC_TCP_SOCKET) { crfd = cwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, - local_addr, - 0, + &CS, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, /* protocol */ - local_addr, - 0, /* port */ + &CS, 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, - local_addr, - 0, + &CS, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, - local_addr, - 0, + &CS, 0, name); } else if (type == IPC_FIFO) { Index: src/ipcache.c =================================================================== RCS file: /cvsroot/squid/squid/src/ipcache.c,v retrieving revision 1.245 diff -u -I\$Id -r1.245 ipcache.c --- src/ipcache.c 16 Aug 2006 00:27:20 -0000 1.245 +++ src/ipcache.c 5 Jul 2008 09:37:35 -0000 @@ -112,7 +112,7 @@ static void ipcacheRelease(ipcache_entry * i) { - debug(14, 3) ("ipcacheRelease: Releasing entry for '%s'\n", (const char *) i->hash.key); + debug(14, 3) ("ipcacheRelease: Releasing entry %x for '%s'\n", i, (const char *) i->hash.key); hash_remove_link(ip_table, (hash_link *) i); dlinkDelete(&i->lru, &lru_list); ipcacheFreeEntry(i); @@ -285,7 +285,7 @@ if (ipcount <= 0) { debug(14, 1) ("ipcacheParse: No addresses in response to '%s'\n", name); } else { - i->addrs.in_addrs = xcalloc(ipcount, sizeof(struct in_addr)); + i->addrs.in_addrs = xcalloc(ipcount, sizeof(struct sockaddr_storage)); i->addrs.bad_mask = xcalloc(ipcount, sizeof(unsigned char)); for (j = 0, k = 0; k < ipcount; k++) { if (safe_inet_addr(A[k], &i->addrs.in_addrs[j])) @@ -304,19 +304,23 @@ } #else static ipcache_entry * -ipcacheParse(ipcache_entry * i, rfc1035_rr * answers, int nr, const char *error_message) +ipcacheParse(ipcache_entry * i, rfc1035_rr * answers, int nrx, const char *error_message) { int k; int j; int na = 0; + int nr = 0; int ttl = 0; const char *name = (const char *) i->hash.key; - i->expires = squid_curtime + Config.negativeDnsTtl; - i->flags.negcached = 1; - safe_free(i->addrs.in_addrs); - safe_free(i->addrs.bad_mask); - safe_free(i->error_message); - i->addrs.count = 0; + + debug(14, 3) ("ipcacheParse: ipcache_entry %x\n", i); + nr = nrx; + if (nrx >= 5000) + nr = nrx - 10000; + if (!i->addrs.count) { + i->expires = squid_curtime + Config.negativeDnsTtl; + i->flags.negcached = 1; + } if (nr < 0) { debug(14, 3) ("ipcacheParse: Lookup failed '%s' for '%s'\n", error_message, (const char *) i->hash.key); @@ -324,47 +328,88 @@ return i; } if (nr == 0) { - debug(14, 3) ("ipcacheParse: No DNS records in response to '%s'\n", name); - i->error_message = xstrdup("No DNS records"); + if (!i->addrs.count && !nrx) { + debug(14, 3) ("ipcacheParse: No DNS records in response to '%s'\n", name); + i->error_message = xstrdup("No DNS records"); + } return i; } assert(answers); for (k = 0; k < nr; k++) { - if (answers[k].type != RFC1035_TYPE_A) + if ((answers[k].type != RFC1035_TYPE_A) && (answers[k].type != RFC1035_TYPE_AAAA)) continue; if (answers[k].class != RFC1035_CLASS_IN) continue; - if (answers[k].rdlength != 4) { + if ((answers[k].rdlength != 4) && (answers[k].rdlength != 16)) { debug(14, 1) ("ipcacheParse: Invalid IP address in response to '%s'\n", name); continue; } na++; } if (na == 0) { - debug(14, 1) ("ipcacheParse: No Address records in response to '%s'\n", name); - i->error_message = xstrdup("No Address records"); + if (!i->addrs.count && nrx < 10000) { + debug(14, 1) ("ipcacheParse: No Address records in response to '%s'\n", name); + i->error_message = xstrdup("No Address records"); + } return i; } i->flags.negcached = 0; - i->addrs.in_addrs = xcalloc(na, sizeof(struct in_addr)); - i->addrs.bad_mask = xcalloc(na, sizeof(unsigned char)); + if (i->addrs.count > 0) { + int total_cnt = i->addrs.count + na; + if (total_cnt > 255) total_cnt == 255; + i->addrs.in_addrs = xrealloc(i->addrs.in_addrs, total_cnt*sizeof(struct sockaddr_storage)); + i->addrs.bad_mask = xrealloc(i->addrs.bad_mask, total_cnt*sizeof(unsigned char)); + } + else { + i->addrs.in_addrs = xcalloc(na, sizeof(struct sockaddr_storage)); + i->addrs.bad_mask = xcalloc(na, sizeof(unsigned char)); + } for (j = 0, k = 0; k < nr; k++) { if (answers[k].class != RFC1035_CLASS_IN) continue; if (answers[k].type == RFC1035_TYPE_A) { + struct sockaddr_in *this_answer = (struct sockaddr_in *)&i->addrs.in_addrs[j+i->addrs.count]; if (answers[k].rdlength != 4) continue; - xmemcpy(&i->addrs.in_addrs[j++], answers[k].rdata, 4); + this_answer->sin_family = AF_INET; +#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + this_answer->sin_len = sizeof(struct sockaddr_in); +#endif + xmemcpy(&this_answer->sin_addr, answers[k].rdata, 4); + debug(14, 3) ("ipcacheParse: #%d %s\n", + j, + sockaddr_ntoa((struct sockaddr *)&i->addrs.in_addrs[j+i->addrs.count])); + j++; + } else if (answers[k].type == RFC1035_TYPE_AAAA) { + struct sockaddr_in6 *this_answer = (struct sockaddr_in6 *)&i->addrs.in_addrs[j+i->addrs.count]; + if (answers[k].rdlength != 16) + continue; + this_answer->sin6_family = AF_INET6; +#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + this_answer->sin6_len = sizeof(struct sockaddr_in6); +#endif + xmemcpy(&this_answer->sin6_addr, answers[k].rdata, 16); + i->addrs.bad_mask[j+i->addrs.count] = 0; + i->addrs.count6++; + if (IN6_IS_ADDR_V4MAPPED(&(this_answer->sin6_addr))) { + i->addrs.bad_mask[j+i->addrs.count] = TRUE; + i->addrs.badcount++; + i->addrs.badcount6++; + } debug(14, 3) ("ipcacheParse: #%d %s\n", - j - 1, - inet_ntoa(i->addrs.in_addrs[j - 1])); + j, + sockaddr_ntoa((struct sockaddr *)&i->addrs.in_addrs[j+i->addrs.count])); + j++; + i->addrs.cur = i->addrs.count; + if (i->addrs.cur) + i->addrs.cur--; } else if (answers[k].type != RFC1035_TYPE_CNAME) continue; if (ttl == 0 || ttl > answers[k].ttl) ttl = answers[k].ttl; } - if (na < 256) - i->addrs.count = (unsigned char) na; + if ((i->addrs.count + na) < 256) + i->addrs.count += (unsigned char) na; else i->addrs.count = 255; if (ttl == 0 || ttl > Config.positiveDnsTtl) @@ -384,10 +429,21 @@ ipcacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message) #endif { + int pairs = 0; generic_cbdata *c = data; ipcache_entry *i = c->data; - cbdataFree(c); - c = NULL; + +#if !USE_DNSSERVERS + if (na > 5000) { + pairs = 1; + } + if (!pairs) { +#endif + cbdataFree(c); + c = NULL; +#if !USE_DNSSERVERS + } +#endif IpcacheStats.replies++; statHistCount(&statCounter.dns.svc_time, tvSubMsec(i->request_time, current_time)); @@ -396,8 +452,15 @@ #else ipcacheParse(i, answers, na, error_message); #endif +#if !USE_DNSSERVERS + if (!pairs) + { +#endif ipcacheAddEntry(i); ipcacheCallback(i); +#if !USE_DNSSERVERS + } +#endif } void @@ -450,6 +513,7 @@ i->request_time = current_time; c = cbdataAlloc(generic_cbdata); c->data = i; + debug(14, 5) ("ipcache_nbgethostbyname: create ipcacheEntry %x'\n", (void *)i); #if USE_DNSSERVERS dnsSubmit(hashKeyStr(&i->hash), ipcacheHandleReply, c); #else @@ -474,7 +538,7 @@ debug(14, 1) ("Successful DNS name lookup tests...\n"); } memset(&static_addrs, '\0', sizeof(ipcache_addrs)); - static_addrs.in_addrs = xcalloc(1, sizeof(struct in_addr)); + static_addrs.in_addrs = xcalloc(1, sizeof(struct sockaddr_storage)); static_addrs.bad_mask = xcalloc(1, sizeof(unsigned char)); ipcache_high = (long) (((float) Config.ipcache.size * (float) Config.ipcache.high) / (float) 100); @@ -535,7 +599,7 @@ (int) i->addrs.count, (int) i->addrs.badcount); for (k = 0; k < (int) i->addrs.count; k++) { - storeAppendPrintf(sentry, " %15s-%3s", inet_ntoa(i->addrs.in_addrs[k]), + storeAppendPrintf(sentry, " %15s-%3s", sockaddr_ntoa(&i->addrs.in_addrs[k]), i->addrs.bad_mask[k] ? "BAD" : "OK "); } storeAppendPrintf(sentry, "\n"); @@ -606,15 +670,17 @@ ipcache_addrs * ipcacheCheckNumeric(const char *name) { - struct in_addr ip; + struct sockaddr_storage ip; /* check if it's already a IP address in text form. */ if (!safe_inet_addr(name, &ip)) return NULL; static_addrs.count = 1; + static_addrs.count6 = ip.ss_family == AF_INET6 ? 1 : 0; static_addrs.cur = 0; - static_addrs.in_addrs[0].s_addr = ip.s_addr; + xmemcpy(&static_addrs.in_addrs[0], &ip, sizeof(ip)); static_addrs.bad_mask[0] = FALSE; static_addrs.badcount = 0; + static_addrs.badcount6 = 0; return &static_addrs; } @@ -652,20 +718,21 @@ for (k = 0; k < ia->count; k++) { if (++ia->cur == ia->count) ia->cur = 0; + if (ia->badcount6 < ia->count6 && ia->in_addrs[ia->cur].ss_family == AF_INET) + continue; if (!ia->bad_mask[ia->cur]) break; } - if (k == ia->count) { + if (k == ia->count && ia->badcount6 == ia->count6) { /* All bad, reset to All good */ debug(14, 3) ("ipcacheCycleAddr: Changing ALL %s addrs from BAD to OK\n", name); for (k = 0; k < ia->count; k++) ia->bad_mask[k] = 0; ia->badcount = 0; + ia->badcount6 = 0; ia->cur = 0; } - debug(14, 3) ("ipcacheCycleAddr: %s now at %s\n", name, - inet_ntoa(ia->in_addrs[ia->cur])); } /* @@ -673,7 +740,7 @@ * advance the current pointer to the next OK address. */ void -ipcacheMarkBadAddr(const char *name, struct in_addr addr) +ipcacheMarkBadAddr(const char *name, struct sockaddr *addr) { ipcache_entry *i; ipcache_addrs *ia; @@ -682,7 +749,17 @@ return; ia = &i->addrs; for (k = 0; k < (int) ia->count; k++) { - if (ia->in_addrs[k].s_addr == addr.s_addr) + if (ia->in_addrs[k].ss_family != addr->sa_family) + continue; + if ((ia->in_addrs[k].ss_family == AF_INET) && + !memcmp(&((struct sockaddr_in *)&ia->in_addrs[k])->sin_addr, + &((struct sockaddr_in *)addr)->sin_addr, + sizeof(struct in_addr)) ) + break; + if ((ia->in_addrs[k].ss_family == AF_INET6) && + !memcmp(&((struct sockaddr_in6 *)&ia->in_addrs[k])->sin6_addr, + &((struct sockaddr_in6 *)addr)->sin6_addr, + sizeof(struct in6_addr)) ) break; } if (k == (int) ia->count) /* not found */ @@ -690,14 +767,15 @@ if (!ia->bad_mask[k]) { ia->bad_mask[k] = TRUE; ia->badcount++; - i->expires = XMIN(squid_curtime + XMAX(60, Config.negativeDnsTtl), i->expires); - debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name, inet_ntoa(addr)); + ia->badcount6 += ia->in_addrs[k].ss_family == AF_INET6? 1 : 0; + i->expires = XMIN(squid_curtime + XMAX(60, Config.negativeDnsTtl*(ia->count - ia->badcount)), i->expires); + debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name, sockaddr_ntoa(addr)); } ipcacheCycleAddr(name, ia); } void -ipcacheMarkGoodAddr(const char *name, struct in_addr addr) +ipcacheMarkGoodAddr(const char *name, struct sockaddr *addr) { ipcache_entry *i; ipcache_addrs *ia; @@ -706,7 +784,17 @@ return; ia = &i->addrs; for (k = 0; k < (int) ia->count; k++) { - if (ia->in_addrs[k].s_addr == addr.s_addr) + if (ia->in_addrs[k].ss_family != addr->sa_family) + continue; + if ((ia->in_addrs[k].ss_family == AF_INET) && + !memcmp(&((struct sockaddr_in *)&ia->in_addrs[k])->sin_addr, + &((struct sockaddr_in *)addr)->sin_addr, + sizeof(struct in_addr)) ) + break; + if ((ia->in_addrs[k].ss_family == AF_INET6) && + !memcmp(&((struct sockaddr_in6 *)&ia->in_addrs[k])->sin6_addr, + &((struct sockaddr_in6 *)addr)->sin6_addr, + sizeof(struct in6_addr)) ) break; } if (k == (int) ia->count) /* not found */ @@ -715,7 +803,8 @@ return; ia->bad_mask[k] = FALSE; ia->badcount--; - debug(14, 2) ("ipcacheMarkGoodAddr: %s [%s]\n", name, inet_ntoa(addr)); + ia->badcount6 -= ia->in_addrs[k].ss_family == AF_INET6? 1 : 0; + debug(14, 2) ("ipcacheMarkGoodAddr: %s [%s]\n", name, sockaddr_ntoa(addr)); } static void @@ -756,14 +845,18 @@ ipcacheAddEntryFromHosts(const char *name, const char *ipaddr) { ipcache_entry *i; - struct in_addr ip; + struct sockaddr_storage ip; if (!safe_inet_addr(ipaddr, &ip)) { +/* if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) { debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr); } else { +*/ debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n", ipaddr); +/* } +*/ return 1; } if ((i = ipcache_get(name))) { @@ -779,11 +872,13 @@ } i = ipcacheCreateEntry(name); i->addrs.count = 1; + i->addrs.count6 = ip.ss_family == AF_INET6 ? 1 : 0 ; i->addrs.cur = 0; i->addrs.badcount = 0; - i->addrs.in_addrs = xcalloc(1, sizeof(struct in_addr)); + i->addrs.badcount6 = 0; + i->addrs.in_addrs = xcalloc(1, sizeof(struct sockaddr_storage)); i->addrs.bad_mask = xcalloc(1, sizeof(unsigned char)); - i->addrs.in_addrs[0].s_addr = ip.s_addr; + xmemcpy(&i->addrs.in_addrs[0], &ip, sizeof(ip)); i->addrs.bad_mask[0] = FALSE; i->flags.fromhosts = 1; ipcacheAddEntry(i); Index: src/main.c =================================================================== RCS file: /cvsroot/squid/squid/src/main.c,v retrieving revision 1.393.2.2 diff -u -I\$Id -r1.393.2.2 main.c --- src/main.c 12 Mar 2007 22:25:40 -0000 1.393.2.2 +++ src/main.c 5 Jul 2008 09:37:35 -0000 @@ -662,6 +662,7 @@ { int errcount = 0; int loop_delay; + struct sockaddr_storage curaddr; #ifdef _SQUID_WIN32_ int WIN32_init_err; #endif @@ -694,11 +695,15 @@ #endif /* HAVE_MALLOPT */ memset(&local_addr, '\0', sizeof(struct in_addr)); - safe_inet_addr(localhost, &local_addr); + memset(&curaddr, '\0', sizeof(curaddr)); + safe_inet_addr(localhost, &curaddr); + local_addr.s_addr = ((struct sockaddr_in *)&curaddr)->sin_addr.s_addr; memset(&any_addr, '\0', sizeof(struct in_addr)); - safe_inet_addr("0.0.0.0", &any_addr); + safe_inet_addr("0.0.0.0", &curaddr); + any_addr.s_addr = ((struct sockaddr_in *)&curaddr)->sin_addr.s_addr; memset(&no_addr, '\0', sizeof(struct in_addr)); - safe_inet_addr("255.255.255.255", &no_addr); + safe_inet_addr("255.255.255.255", &curaddr); + no_addr.s_addr = ((struct sockaddr_in *)&curaddr)->sin_addr.s_addr; squid_srandom(time(NULL)); getCurrentTime(); Index: src/multicast.c =================================================================== RCS file: /cvsroot/squid/squid/src/multicast.c,v retrieving revision 1.9 diff -u -I\$Id -r1.9 multicast.c --- src/multicast.c 12 Jan 2001 00:37:19 -0000 1.9 +++ src/multicast.c 5 Jul 2008 09:37:35 -0000 @@ -40,9 +40,18 @@ { #ifdef IP_MULTICAST_TTL char ttl = (char) mcast_ttl; - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 1) < 0) - debug(50, 1) ("comm_set_mcast_ttl: FD %d, TTL: %d: %s\n", - fd, mcast_ttl, xstrerror()); + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + + getsockname(fd, (struct sockaddr *)&addr, &addrlen); + if (addr.ss_family == AF_INET6) + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, 1) < 0) + debug(50, 1) ("comm_set_mcast_ttl: FD %d, TTL: %d: %s\n", + fd, mcast_ttl, xstrerror()); + if (addr.ss_family == AF_INET) + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 1) < 0) + debug(50, 1) ("comm_set_mcast_ttl: FD %d, TTL: %d: %s\n", + fd, mcast_ttl, xstrerror()); #endif return 0; } @@ -52,9 +61,12 @@ { #ifdef IP_MULTICAST_TTL int fd = theInIcpConnection; + int fd6 = theInIcpConnection6; struct ip_mreq mr; + struct ipv6_mreq mr6; int i; int x; + int mcastTTL = 16; char c = 0; if (ia == NULL) { debug(7, 0) ("comm_join_mcast_groups: Unknown host\n"); @@ -62,17 +74,34 @@ } for (i = 0; i < (int) ia->count; i++) { debug(7, 10) ("Listening for ICP requests on %s\n", - inet_ntoa(*(ia->in_addrs + i))); - mr.imr_multiaddr.s_addr = (ia->in_addrs + i)->s_addr; - mr.imr_interface.s_addr = INADDR_ANY; - x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *) &mr, sizeof(struct ip_mreq)); - if (x < 0) - debug(7, 1) ("comm_join_mcast_groups: FD %d, [%s]\n", - fd, inet_ntoa(*(ia->in_addrs + i))); - x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1); - if (x < 0) - debug(7, 1) ("Can't disable multicast loopback: %s\n", xstrerror()); + sockaddr_ntoa((&ia->in_addrs + i))); + if (ia->in_addrs->ss_family == AF_INET6) { + memcpy(&mr6.ipv6mr_multiaddr, + &(((struct sockaddr_in6 *)ia->in_addrs)->sin6_addr), + sizeof(struct in6_addr)); + mr6.ipv6mr_interface = 0; + x = setsockopt(fd6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &c, 1); + if (x < 0) + debug(7, 1) ("Can't disable multicast loopback: %s\n", xstrerror()); + x = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mr6, sizeof(mr6)); + if (x < 0) + debug(7, 1) ("comm_join_mcast_groups: FD %d, [%s]\n", + fd6, sockaddr_ntoa((ia->in_addrs + i))); + + } + if (ia->in_addrs->ss_family == AF_INET) { + mr.imr_multiaddr.s_addr = ((struct sockaddr_in *)(ia->in_addrs + i))->sin_addr.s_addr; + mr.imr_interface.s_addr = INADDR_ANY; + x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *) &mr, sizeof(struct ip_mreq)); + if (x < 0) + debug(7, 1) ("comm_join_mcast_groups: FD %d, [%s]\n", + fd, sockaddr_ntoa((ia->in_addrs + i))); + x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1); + if (x < 0) + debug(7, 1) ("Can't disable multicast loopback: %s\n", xstrerror()); + } } #endif } Index: src/neighbors.c =================================================================== RCS file: /cvsroot/squid/squid/src/neighbors.c,v retrieving revision 1.313.2.1 diff -u -I\$Id -r1.313.2.1 neighbors.c --- src/neighbors.c 26 Feb 2007 22:45:24 -0000 1.313.2.1 +++ src/neighbors.c 5 Jul 2008 09:37:35 -0000 @@ -53,7 +53,7 @@ static void peerCountMcastPeersStart(void *data); static void peerCountMcastPeersSchedule(peer * p, time_t when); static IRCB peerCountHandleIcpReply; -static void neighborIgnoreNonPeer(const struct sockaddr_in *, icp_opcode); +static void neighborIgnoreNonPeer(const struct sockaddr *, icp_opcode); static OBJH neighborDumpPeers; static OBJH neighborDumpNonPeers; static void dump_peers(StoreEntry * sentry, peer * peers); @@ -78,17 +78,30 @@ peer * -whichPeer(const struct sockaddr_in * from) +whichPeer(const struct sockaddr * from) { int j; - u_short port = ntohs(from->sin_port); - struct in_addr ip = from->sin_addr; + u_short port; peer *p = NULL; - debug(15, 3) ("whichPeer: from %s port %d\n", inet_ntoa(ip), port); + char hbuf[80], sbuf[8]; + getnameinfo(from, SOCKLEN(from), hbuf, 80, sbuf, 8, + NI_NUMERICHOST|NI_NUMERICSERV); + debug(15, 3) ("whichPeer: from %s port %s\n", hbuf, sbuf); for (p = Config.peers; p; p = p->next) { for (j = 0; j < p->n_addresses; j++) { - if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) { - return p; + if (from->sa_family != p->addresses[j].ss_family) + continue; + switch (from->sa_family) { + case AF_INET6: + if ( IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)&p->addresses[j])->sin6_addr, &((struct sockaddr_in6 *)from)->sin6_addr) && + (p->icp.port == ntohs(((struct sockaddr_in6 *)from)->sin6_port))) + return p; + break; + case AF_INET: + if ( (((struct sockaddr_in *)&p->addresses[j])->sin_addr.s_addr == ((struct sockaddr_in *)from)->sin_addr.s_addr) && + (p->icp.port == ntohs(((struct sockaddr_in *)from)->sin_port))) + return p; + break; } } } @@ -145,9 +158,9 @@ if (p->access == NULL) return do_ping; memset(&checklist, '\0', sizeof(checklist)); - checklist.src_addr = request->client_addr; - checklist.my_addr = request->my_addr; - checklist.my_port = request->my_port; + xmemcpy(&checklist.src_addr, &request->client_addr, sizeof(struct sockaddr_storage)); + xmemcpy(&checklist.my_addr, &request->my_addr, sizeof(struct sockaddr_storage)); + xmemcpy(&checklist.my_port, &request->my_port, sizeof(struct sockaddr_storage)); checklist.request = request; #if 0 && USE_IDENT /* @@ -367,15 +380,15 @@ void neighbors_init(void) { - struct sockaddr_in name; - socklen_t len = sizeof(struct sockaddr_in); + struct sockaddr_storage name; + socklen_t len = sizeof(struct sockaddr_storage); struct servent *sep = NULL; const char *me = getMyHostname(); peer *this; peer *next; int fd = theInIcpConnection; if (fd >= 0) { - memset(&name, '\0', sizeof(struct sockaddr_in)); + memset(&name, '\0', sizeof(struct sockaddr_storage)); if (getsockname(fd, (struct sockaddr *) &name, &len) < 0) debug(15, 1) ("getsockname(%d,%p,%p) failed.\n", fd, &name, &len); for (this = Config.peers; this; this = next) { @@ -384,7 +397,9 @@ if (0 != strcmp(this->host, me)) continue; for (s = Config.Sockaddr.http; s; s = s->next) { - if (this->http_port != ntohs(s->s.sin_port)) + if (this->http_port != ((s->s.ss_family == AF_INET6) ? + ntohs(((struct sockaddr_in6 *)&s->s)->sin6_port) : + ntohs(((struct sockaddr_in *)&s->s)->sin_port)) ) continue; debug(15, 1) ("WARNING: Peer looks like this host\n"); debug(15, 1) (" Ignoring %s %s/%d/%d\n", @@ -402,7 +417,7 @@ echo_hdr.reqnum = 0; echo_hdr.flags = 0; echo_hdr.pad = 0; - echo_hdr.shostid = name.sin_addr.s_addr; + xmemcpy(&echo_hdr.shostid, &name, len); sep = getservbyname("echo", "udp"); echo_port = sep ? ntohs((u_short) sep->s_port) : 7; } @@ -457,7 +472,11 @@ debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n", p->host, url); if (p->type == PEER_MULTICAST) - mcastSetTtl(theOutIcpConnection, p->mcast.ttl); + if (p->in_addr.ss_family == AF_INET6) + mcastSetTtl(theOutIcpConnection6, p->mcast.ttl); + else + if (p->in_addr.ss_family == AF_INET) + mcastSetTtl(theOutIcpConnection, p->mcast.ttl); debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->hash.key)); debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum); @@ -471,22 +490,36 @@ debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n"); echo_hdr.reqnum = reqnum; query = icpCreateMessage(ICP_DECHO, 0, url, reqnum, 0); - icpUdpSend(theOutIcpConnection, - &p->in_addr, - query, - LOG_ICP_QUERY, - 0); + if (p->in_addr.ss_family == AF_INET6) + icpUdpSend(theOutIcpConnection6, + &p->in_addr, + query, + LOG_ICP_QUERY, + 0); + else + icpUdpSend(theOutIcpConnection, + &p->in_addr, + query, + LOG_ICP_QUERY, + 0); } else { flags = 0; if (Config.onoff.query_icmp) if (p->icp.version == ICP_VERSION_2) flags |= ICP_FLAG_SRC_RTT; query = icpCreateMessage(ICP_QUERY, flags, url, reqnum, 0); - icpUdpSend(theOutIcpConnection, - &p->in_addr, - query, - LOG_ICP_QUERY, - 0); + if (p->in_addr.ss_family == AF_INET6) + icpUdpSend(theOutIcpConnection6, + &p->in_addr, + query, + LOG_ICP_QUERY, + 0); + else + icpUdpSend(theOutIcpConnection, + &p->in_addr, + query, + LOG_ICP_QUERY, + 0); } queries_sent++; @@ -742,23 +775,31 @@ static peer *non_peers = NULL; static void -neighborIgnoreNonPeer(const struct sockaddr_in *from, icp_opcode opcode) +neighborIgnoreNonPeer(const struct sockaddr *from, icp_opcode opcode) { peer *np; for (np = non_peers; np; np = np->next) { - if (np->in_addr.sin_addr.s_addr != from->sin_addr.s_addr) + if (from->sa_family != np->in_addr.ss_family) continue; - if (np->in_addr.sin_port != from->sin_port) + if ((from->sa_family == AF_INET6) && + IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)&np->in_addr)->sin6_addr, &((struct sockaddr_in6 *)from)->sin6_addr) && + (((struct sockaddr_in6 *)&np->in_addr)->sin6_port == ntohs(((struct sockaddr_in6 *)from)->sin6_port))) + continue; + else + if ((from->sa_family == AF_INET) && + (((struct sockaddr_in *)&np->in_addr)->sin_addr.s_addr == ((struct sockaddr_in *)from)->sin_addr.s_addr) && + (((struct sockaddr_in *)&np->in_addr)->sin_port == ntohs(((struct sockaddr_in *)from)->sin_port))) continue; break; } if (np == NULL) { np = xcalloc(1, sizeof(peer)); - np->in_addr.sin_addr = from->sin_addr; - np->in_addr.sin_port = from->sin_port; - np->icp.port = ntohl(from->sin_port); + xmemcpy(&np->in_addr, &from, sizeof(struct sockaddr_storage)); + np->icp.port = ntohs( (from->sa_family == AF_INET6) ? + ((struct sockaddr_in6 *)from)->sin6_port : + ((struct sockaddr_in *)from)->sin_port ); np->type = PEER_NONE; - np->host = xstrdup(inet_ntoa(from->sin_addr)); + np->host = xstrdup(sockaddr_ntoa(from)); np->next = non_peers; non_peers = np; } @@ -793,7 +834,7 @@ * If a hit process is already started, then sobeit */ void -neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct sockaddr_in *from) +neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct sockaddr *from) { peer *p = NULL; StoreEntry *entry; @@ -883,7 +924,7 @@ mem->ping_reply_callback(NULL, ntype, PROTO_ICP, header, mem->ircb_data); #endif } else { - debug(15, 1) ("Unsolicited SECHO from %s\n", inet_ntoa(from->sin_addr)); + debug(15, 1) ("Unsolicited SECHO from %s\n", sockaddr_ntoa(from)); } } else if (opcode == ICP_DENIED) { if (p == NULL) { @@ -997,7 +1038,7 @@ peerDNSConfigure(const ipcache_addrs * ia, void *data) { peer *p = data; - struct sockaddr_in *ap; + struct sockaddr_storage *ap; int j; if (p->n_addresses == 0) { debug(15, 1) ("Configuring %s %s/%d/%d\n", neighborTypeStr(p), @@ -1016,15 +1057,17 @@ } p->tcp_up = PEER_TCP_MAGIC_COUNT; for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) { - p->addresses[j] = ia->in_addrs[j]; - debug(15, 2) ("--> IP address #%d: %s\n", j, inet_ntoa(p->addresses[j])); + xmemcpy(&p->addresses[j], &ia->in_addrs[j], sizeof(struct sockaddr_storage)); + debug(15, 2) ("--> IP address #%d: %s\n", j, sockaddr_ntoa(&p->addresses[j])); p->n_addresses++; } - ap = &p->in_addr; - memset(ap, '\0', sizeof(struct sockaddr_in)); - ap->sin_family = AF_INET; - ap->sin_addr = p->addresses[0]; - ap->sin_port = htons(p->icp.port); + ap = (struct sockaddr_storage *)&p->in_addr; + memset(ap, '\0', sizeof(struct sockaddr_storage)); + xmemcpy(ap, &p->addresses[0], sizeof(struct sockaddr_storage)); + if (ap->ss_family == AF_INET6) + ((struct sockaddr_in6 *)ap)->sin6_port = htons(p->icp.port); + else + ((struct sockaddr_in *)ap)->sin_port = htons(p->icp.port); if (p->type == PEER_MULTICAST) peerCountMcastPeersSchedule(p, 10); if (p->type != PEER_MULTICAST) @@ -1104,6 +1147,7 @@ peerProbeConnect(peer * p) { int fd; + struct sockaddr_storage outsock; time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout : Config.Timeout.peer_connect; int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10; @@ -1111,16 +1155,18 @@ return ret; /* probe already running */ if (squid_curtime - p->stats.last_connect_probe == 0) return ret; /* don't probe to often */ - fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL), - 0, COMM_NONBLOCKING, p->host); + memset(&outsock, '\0', sizeof(outsock)); + outsock.ss_family = p->in_addr.ss_family; + fd = comm_open(SOCK_STREAM, IPPROTO_TCP, &outsock, + COMM_NONBLOCKING, p->host); if (fd < 0) return ret; commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p); p->test_fd = fd; p->stats.last_connect_probe = squid_curtime; + p->ia_cur = -1; commConnectStart(p->test_fd, - p->host, - p->http_port, + p->host, p->http_port, peerProbeConnectDone, p); return ret; @@ -1161,10 +1207,14 @@ MemObject *mem; icp_common_t *query; int reqnum; + int is_ipv6 = 0; LOCAL_ARRAY(char, url, MAX_URL); assert(p->type == PEER_MULTICAST); p->mcast.flags.count_event_pending = 0; - snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr)); + if (p->in_addr.ss_family == AF_INET6) + is_ipv6 = 1; + snprintf(url, MAX_URL, "http://%s%s%s/", is_ipv6 ? "[" : "", + sockaddr_ntoa(&p->in_addr), is_ipv6 ? "]" : ""); fake = storeCreateEntry(url, url, null_request_flags, METHOD_GET); psstate = cbdataAlloc(ps_state); psstate->request = requestLink(urlParse(METHOD_GET, url)); @@ -1178,15 +1228,25 @@ mem->start_ping = current_time; mem->ping_reply_callback = peerCountHandleIcpReply; mem->ircb_data = psstate; - mcastSetTtl(theOutIcpConnection, p->mcast.ttl); + if (p->in_addr.ss_family == AF_INET6) + mcastSetTtl(theOutIcpConnection6, p->mcast.ttl); + else + mcastSetTtl(theOutIcpConnection, p->mcast.ttl); p->mcast.id = mem->id; reqnum = icpSetCacheKey(fake->hash.key); query = icpCreateMessage(ICP_QUERY, 0, url, reqnum, 0); - icpUdpSend(theOutIcpConnection, - &p->in_addr, - query, - LOG_ICP_QUERY, - 0); + if (p->in_addr.ss_family == AF_INET6) + icpUdpSend(theOutIcpConnection6, + &p->in_addr, + query, + LOG_ICP_QUERY, + 0); + else + icpUdpSend(theOutIcpConnection, + &p->in_addr, + query, + LOG_ICP_QUERY, + 0); fake->ping_status = PING_WAITING; eventAdd("peerCountMcastPeersDone", peerCountMcastPeersDone, @@ -1336,7 +1396,7 @@ dump_peer_options(sentry, e); for (i = 0; i < e->n_addresses; i++) { storeAppendPrintf(sentry, "Address[%d] : %s\n", i, - inet_ntoa(e->addresses[i])); + sockaddr_ntoa(&e->addresses[i])); } storeAppendPrintf(sentry, "Status : %s\n", neighborUp(e) ? "Up" : "Down"); @@ -1404,7 +1464,7 @@ #if USE_HTCP void -neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct sockaddr_in *from) +neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct sockaddr *from) { StoreEntry *e = storeGet(key); MemObject *mem = NULL; Index: src/net_db.c =================================================================== RCS file: /cvsroot/squid/squid/src/net_db.c,v retrieving revision 1.172 diff -u -I\$Id -r1.172 net_db.c --- src/net_db.c 5 Jun 2006 22:47:01 -0000 1.172 +++ src/net_db.c 5 Jul 2008 09:37:35 -0000 @@ -697,7 +697,7 @@ } void -netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt) +netdbHandlePingReply(const struct sockaddr *from, int hops, int rtt) { #if USE_ICMP netdbEntry *n; @@ -735,7 +735,7 @@ } int -netdbHops(struct in_addr addr) +netdbHops(struct sockaddr *addr) { #if USE_ICMP netdbEntry *n = netdbLookupAddr(addr); @@ -905,7 +905,7 @@ } void -netdbDeleteAddrNetwork(struct in_addr addr) +netdbDeleteAddrNetwork(struct sockaddr *addr) { #if USE_ICMP netdbEntry *n = netdbLookupAddr(addr); Index: src/pconn.c =================================================================== RCS file: /cvsroot/squid/squid/src/pconn.c,v retrieving revision 1.35 diff -u -I\$Id -r1.35 pconn.c --- src/pconn.c 22 May 2006 21:54:56 -0000 1.35 +++ src/pconn.c 5 Jul 2008 09:37:35 -0000 @@ -49,7 +49,7 @@ static PF pconnRead; static PF pconnTimeout; -static int pconnKey(char *buf, const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port); +static int pconnKey(char *buf, const char *host, u_short port, const char *domain, struct sockaddr *client_address); static hash_table *table = NULL; static struct _pconn *pconnNew(const char *key); static void pconnDelete(struct _pconn *p); @@ -62,16 +62,16 @@ static int pconnKey(char *buf, const char *host, u_short port, const char *domain, - struct in_addr *client_address, u_short client_port) + struct sockaddr *client_address) { if (domain && client_address) - return snprintf(buf, PCONN_KEYLEN, "%s.%d:%s.%d/%s", host, (int) port, - inet_ntoa(*client_address), (int) client_port, domain); + return snprintf(buf, PCONN_KEYLEN, "%s.%d:%s./%s", host, (int) port, + sockaddr_ntoa(client_address), domain); else if (domain && (!client_address)) return snprintf(buf, PCONN_KEYLEN, "%s.%d/%s", host, (int) port, domain); else if ((!domain) && client_address) - return snprintf(buf, PCONN_KEYLEN, "%s.%d:%s.%d", host, (int) port, - inet_ntoa(*client_address), (int) client_port); + return snprintf(buf, PCONN_KEYLEN, "%s.%d:%s.", host, (int) port, + sockaddr_ntoa(client_address)); else return snprintf(buf, PCONN_KEYLEN, "%s:%d", host, (int) port); } @@ -194,7 +194,7 @@ } void -pconnPush(int fd, const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port) +pconnPush(int fd, const char *host, u_short port, const char *domain, struct sockaddr *client_address) { struct _pconn *p; int *old; @@ -209,7 +209,7 @@ return; } assert(table != NULL); - pconnKey(key, host, port, domain, client_address, client_port); + pconnKey(key, host, port, domain, client_address); p = (struct _pconn *) hash_lookup(table, key); if (p == NULL) p = pconnNew(key); @@ -233,13 +233,13 @@ } int -pconnPop(const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port) +pconnPop(const char *host, u_short port, const char *domain, struct sockaddr *client_address) { struct _pconn *p; hash_link *hptr; int fd = -1; assert(table != NULL); - hptr = pconnLookup(host, port, domain, client_address, client_port); + hptr = pconnLookup(host, port, domain, client_address); if (hptr != NULL) { p = (struct _pconn *) hptr; assert(p->nfds > 0); @@ -252,11 +252,11 @@ } hash_link * -pconnLookup(const char *peer, u_short port, const char *domain, struct in_addr * client_address, u_short client_port) +pconnLookup(const char *peer, u_short port, const char *domain, struct sockaddr *client_address) { LOCAL_ARRAY(char, key, PCONN_KEYLEN); assert(table != NULL); - pconnKey(key, peer, port, domain, client_address, client_port); + pconnKey(key, peer, port, domain, client_address); return hash_lookup(table, key); } Index: src/peer_select.c =================================================================== RCS file: /cvsroot/squid/squid/src/peer_select.c,v retrieving revision 1.131 diff -u -I\$Id -r1.131 peer_select.c --- src/peer_select.c 10 Dec 2006 05:24:52 -0000 1.131 +++ src/peer_select.c 5 Jul 2008 09:37:35 -0000 @@ -425,10 +425,20 @@ code = SOURCE_FASTEST; } else #endif - if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) { + if ((ps->closest_parent_miss.ss_family == AF_INET6) && + !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&ps->closest_parent_miss)->sin6_addr)) { p = whichPeer(&ps->closest_parent_miss); code = CLOSEST_PARENT_MISS; - } else if (ps->first_parent_miss.sin_addr.s_addr != any_addr.s_addr) { + } else if ((ps->closest_parent_miss.ss_family == AF_INET) && + (((struct sockaddr_in *)&ps->closest_parent_miss)->sin_addr.s_addr != any_addr.s_addr)) { + p = whichPeer(&ps->closest_parent_miss); + code = CLOSEST_PARENT_MISS; + } else if ((ps->first_parent_miss.ss_family == AF_INET6) && + !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&ps->first_parent_miss)->sin6_addr)) { + p = whichPeer(&ps->first_parent_miss); + code = FIRST_PARENT_MISS; + } else if ((ps->first_parent_miss.ss_family == AF_INET) && + (((struct sockaddr_in *)&ps->first_parent_miss)->sin_addr.s_addr != any_addr.s_addr)) { p = whichPeer(&ps->first_parent_miss); code = FIRST_PARENT_MISS; } @@ -525,6 +535,11 @@ { ps_state *psstate = data; StoreEntry *entry = psstate->entry; + if (!psstate->request) { + debug(44, 3) ("peerPingTimeout: null request\n"); + peerSelectStateFree(psstate); + return; + } if (entry) debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry)); if (!cbdataValid(psstate->callback_data)) { @@ -567,12 +582,21 @@ if (p->options.closest_only) return; /* set FIRST_MISS if there is no CLOSEST parent */ - if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) + if ((ps->closest_parent_miss.ss_family == AF_INET6) && + !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&ps->closest_parent_miss)->sin6_addr)) + return; + else if ((ps->closest_parent_miss.ss_family == AF_INET) && + (((struct sockaddr_in *)&ps->closest_parent_miss)->sin_addr.s_addr != any_addr.s_addr)) return; rtt = tvSubMsec(ps->ping.start, current_time) / p->weight; - if (ps->first_parent_miss.sin_addr.s_addr == any_addr.s_addr || - rtt < ps->ping.w_rtt) { - ps->first_parent_miss = p->in_addr; + if (( + ((ps->first_parent_miss.ss_family == AF_INET6) && + IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&ps->first_parent_miss)->sin6_addr)) || + ((ps->first_parent_miss.ss_family == AF_INET) && + (((struct sockaddr_in *)&ps->first_parent_miss)->sin_addr.s_addr != any_addr.s_addr)) + ) + || rtt < ps->ping.w_rtt) { + xmemcpy(&ps->first_parent_miss, &p->in_addr, sizeof(&p->in_addr)); ps->ping.w_rtt = rtt; } } @@ -655,11 +679,20 @@ if (p->options.closest_only) return; /* set FIRST_MISS if there is no CLOSEST parent */ - if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) - return; + if ((ps->closest_parent_miss.ss_family == AF_INET6) && + !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&ps->closest_parent_miss)->sin6_addr)) + return; + else if ((ps->closest_parent_miss.ss_family == AF_INET) && + (((struct sockaddr_in *)&ps->closest_parent_miss)->sin_addr.s_addr != any_addr.s_addr)) + return; rtt = tvSubMsec(ps->ping.start, current_time) / p->weight; - if (ps->first_parent_miss.sin_addr.s_addr == any_addr.s_addr || - rtt < ps->ping.w_rtt) { + if (( + ((ps->first_parent_miss.ss_family == AF_INET6) && + IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)&ps->first_parent_miss)->sin6_addr)) || + ((ps->first_parent_miss.ss_family == AF_INET) && + (((struct sockaddr_in *)&ps->first_parent_miss)->sin_addr.s_addr != any_addr.s_addr)) + ) + || rtt < ps->ping.w_rtt) { ps->first_parent_miss = p->in_addr; ps->ping.w_rtt = rtt; } Index: src/peer_sourcehash.c =================================================================== RCS file: /cvsroot/squid/squid/src/peer_sourcehash.c,v retrieving revision 1.2 diff -u -I\$Id -r1.2 peer_sourcehash.c --- src/peer_sourcehash.c 16 May 2006 04:52:26 -0000 1.2 +++ src/peer_sourcehash.c 5 Jul 2008 09:37:35 -0000 @@ -136,7 +136,7 @@ double high_score = 0; char *key = NULL; - key = inet_ntoa(request->client_addr); + key = sockaddr_ntoa(&request->client_addr); /* calculate hash key */ debug(39, 2) ("peerSourceHashSelectParent: Calculating hash for %s\n", key); Index: src/protos.h =================================================================== RCS file: /cvsroot/squid/squid/src/protos.h,v retrieving revision 1.520.2.1 diff -u -I\$Id -r1.520.2.1 protos.h --- src/protos.h 26 Mar 2007 23:14:09 -0000 1.520.2.1 +++ src/protos.h 5 Jul 2008 09:37:35 -0000 @@ -107,7 +107,7 @@ extern void parse_time_t(time_t * var); extern void parse_cachedir_options(SwapDir * sd, struct cache_dir_option *options, int reconfiguring); extern void dump_cachedir_options(StoreEntry * e, struct cache_dir_option *options, SwapDir * sd); -extern void parse_sockaddr_in_list_token(sockaddr_in_list **, char *); +extern void parse_sockaddr_storage_list_token(sockaddr_storage_list **, char *); /* @@ -131,11 +131,11 @@ extern int cbdataLocked(const void *p); extern void clientdbInit(void); -extern void clientdbUpdate(struct in_addr, log_type, protocol_t, squid_off_t); -extern int clientdbCutoffDenied(struct in_addr); +extern void clientdbUpdate(struct sockaddr *, log_type, protocol_t, squid_off_t); +extern int clientdbCutoffDenied(struct sockaddr *); extern void clientdbDump(StoreEntry *); extern void clientdbFreeMemory(void); -extern int clientdbEstablished(struct in_addr, int); +extern int clientdbEstablished(struct sockaddr *, int); extern char *clientConstructTraceEcho(clientHttpRequest *); extern int checkNegativeHit(StoreEntry *); @@ -149,18 +149,18 @@ extern int commSetNonBlocking(int fd); extern int commUnsetNonBlocking(int fd); extern void commSetCloseOnExec(int fd); -extern int comm_accept(int fd, struct sockaddr_in *, struct sockaddr_in *); +extern int comm_accept(int fd, struct sockaddr *, struct sockaddr *); extern void comm_close(int fd); extern void comm_reset_close(int fd); #if LINGERING_CLOSE extern void comm_lingering_close(int fd); #endif extern void commConnectStart(int fd, const char *, u_short, CNCB *, void *); -extern int comm_connect_addr(int sock, const struct sockaddr_in *); +extern int comm_connect_addr(int sock, const struct sockaddr *); extern void comm_init(void); extern int comm_listen(int sock); -extern int comm_open(int, int, struct in_addr, u_short port, int, const char *note); -extern int comm_openex(int, int, struct in_addr, u_short, int, unsigned char TOS, const char *); +extern int comm_open(int, int, struct sockaddr *, int, const char *note); +extern int comm_openex(int, int, struct sockaddr *, int, unsigned char TOS, const char *); extern u_short comm_local_port(int fd); extern void commDeferFD(int fd); @@ -169,7 +169,7 @@ extern void commRemoveSlow(int fd); extern void comm_add_close_handler(int fd, PF *, void *); extern void comm_remove_close_handler(int fd, PF *, void *); -extern int comm_udp_sendto(int, const struct sockaddr_in *, int, const void *, int); +extern int comm_udp_sendto(int, const struct sockaddr *, int, const void *, int); extern void comm_write(int fd, const char *buf, int size, @@ -247,7 +247,7 @@ extern void idnsInit(void); extern void idnsShutdown(void); extern void idnsALookup(const char *, IDNSCB *, void *); -extern void idnsPTRLookup(const struct in_addr, IDNSCB *, void *); +extern void idnsPTRLookup(const struct sockaddr *, IDNSCB *, void *); extern void eventAdd(const char *name, EVH * func, void *arg, double when, int); extern void eventAddIsh(const char *name, EVH * func, void *arg, double delta_ish, int); @@ -278,12 +278,12 @@ extern void filemapFreeMemory(fileMap *); -extern void fqdncache_nbgethostbyaddr(struct in_addr, FQDNH *, void *); -extern const char *fqdncache_gethostbyaddr(struct in_addr, int flags); +extern void fqdncache_nbgethostbyaddr(struct sockaddr *, FQDNH *, void *); +extern const char *fqdncache_gethostbyaddr(struct sockaddr *, int flags); extern void fqdncache_init(void); extern void fqdnStats(StoreEntry *); extern void fqdncacheReleaseInvalid(const char *); -extern const char *fqdnFromAddr(struct in_addr); +extern const char *fqdnFromAddr(struct sockaddr *); extern int fqdncacheQueueDrain(void); extern void fqdncacheFreeMemory(void); extern void fqdncache_restart(void); @@ -529,7 +529,7 @@ const char *url, int reqnum, int pad); -extern int icpUdpSend(int, const struct sockaddr_in *, icp_common_t *, log_type, int); +extern int icpUdpSend(int, const struct sockaddr *, icp_common_t *, log_type, int); extern PF icpHandleUdp; extern PF icpUdpSendQueue; extern PF httpAccept; @@ -573,7 +573,7 @@ extern void wccp2ConnectionClose(void); #endif /* USE_WCCPv2 */ -extern void icpHandleIcpV3(int, struct sockaddr_in, char *, int); +extern void icpHandleIcpV3(int, struct sockaddr *, char *, int); extern int icpCheckUdpHit(StoreEntry *, request_t * request); extern void icpConnectionsOpen(void); extern void icpConnectionShutdown(void); @@ -591,8 +591,8 @@ extern void ipcache_init(void); extern void stat_ipcache_get(StoreEntry *); extern void ipcacheCycleAddr(const char *name, ipcache_addrs *); -extern void ipcacheMarkBadAddr(const char *name, struct in_addr); -extern void ipcacheMarkGoodAddr(const char *name, struct in_addr); +extern void ipcacheMarkBadAddr(const char *name, struct sockaddr *); +extern void ipcacheMarkGoodAddr(const char *name, struct sockaddr *); extern void ipcacheFreeMemory(void); extern ipcache_addrs *ipcacheCheckNumeric(const char *name); extern void ipcache_restart(void); @@ -659,7 +659,7 @@ int *exprep, int *timeout); extern void neighborAddAcl(const char *, const char *); -extern void neighborsUdpAck(const cache_key *, icp_common_t *, const struct sockaddr_in *); +extern void neighborsUdpAck(const cache_key *, icp_common_t *, const struct sockaddr *); extern void neighborAdd(const char *, const char *, int, int, int, int, int); extern void neighbors_init(void); extern peer *peerFindByName(const char *); @@ -680,23 +680,23 @@ extern void peerConnectSucceded(peer *); extern void dump_peer_options(StoreEntry *, peer *); extern int peerHTTPOkay(const peer *, request_t *); -extern peer *whichPeer(const struct sockaddr_in *from); +extern peer *whichPeer(const struct sockaddr *from); #if USE_HTCP -extern void neighborsHtcpReply(const cache_key *, htcpReplyData *, const struct sockaddr_in *); +extern void neighborsHtcpReply(const cache_key *, htcpReplyData *, const struct sockaddr *); #endif extern void peerAddFwdServer(FwdServer ** FS, peer * p, hier_code code); extern int peerAllowedToUse(const peer *, request_t *); extern void netdbInit(void); -extern void netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt); +extern void netdbHandlePingReply(const struct sockaddr *from, int hops, int rtt); extern void netdbPingSite(const char *hostname); extern void netdbDump(StoreEntry *); -extern int netdbHops(struct in_addr); +extern int netdbHops(struct sockaddr *); extern void netdbFreeMemory(void); extern int netdbHostHops(const char *host); extern int netdbHostRtt(const char *host); extern void netdbUpdatePeer(request_t *, peer * e, int rtt, int hops); -extern void netdbDeleteAddrNetwork(struct in_addr addr); +extern void netdbDeleteAddrNetwork(struct sockaddr *addr); extern void netdbBinaryExchange(StoreEntry *); extern EVH netdbExchangeStart; extern void netdbExchangeUpdatePeer(struct in_addr, peer *, double, double); @@ -731,7 +731,7 @@ extern void fwdLogRotate(void); extern void fwdStatus(FwdState *, http_status); #endif -struct in_addr getOutgoingAddr(request_t * request); +struct sockaddr_storage *getOutgoingAddr(request_t * request); unsigned long getOutgoingTOS(request_t * request); extern void urnStart(request_t *, StoreEntry *); @@ -758,14 +758,14 @@ extern void authenticateShutdown(void); extern void authenticateFixHeader(HttpReply *, auth_user_request_t *, request_t *, int, int); extern void authenticateAddTrailer(HttpReply *, auth_user_request_t *, request_t *, int); -extern auth_acl_t authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct in_addr); +extern auth_acl_t authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct sockaddr *); extern void authenticateAuthUserUnlock(auth_user_t * auth_user); extern void authenticateAuthUserLock(auth_user_t * auth_user); extern void authenticateAuthUserRequestUnlock(auth_user_request_t *); extern void authenticateAuthUserRequestLock(auth_user_request_t *); extern char *authenticateAuthUserRequestMessage(auth_user_request_t *); extern int authenticateAuthUserInuse(auth_user_t * auth_user); -extern void authenticateAuthUserRequestRemoveIp(auth_user_request_t *, struct in_addr); +extern void authenticateAuthUserRequestRemoveIp(auth_user_request_t *, struct sockaddr *); extern void authenticateAuthUserRequestClearIp(auth_user_request_t *); extern int authenticateAuthUserRequestIPCount(auth_user_request_t *); extern int authenticateDirection(auth_user_request_t *); @@ -808,7 +808,7 @@ /* ident.c */ #if USE_IDENT -extern void identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, +extern void identStart(struct sockaddr *me, struct sockaddr *my_peer, IDCB * callback, void *cbdata); extern void identInit(void); #endif @@ -1163,12 +1163,12 @@ extern ErrorState *errorCon(err_type type, http_status, request_t * request); extern int errorPageId(const char *page_name); -extern void pconnPush(int, const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port); -extern int pconnPop(const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port); -extern hash_link *pconnLookup(const char *peer, u_short port, const char *domain, struct in_addr *client_address, u_short client_port); +extern void pconnPush(int, const char *host, u_short port, const char *domain, struct sockaddr *client_address); +extern int pconnPop(const char *host, u_short port, const char *domain, struct sockaddr *client_address); +extern hash_link *pconnLookup(const char *peer, u_short port, const char *domain, struct sockaddr *client_address); extern void pconnInit(void); -extern int asnMatchIp(void *, struct in_addr); +extern int asnMatchIp(void *, struct sockaddr *); extern void asnInit(void); extern void asnFreeMemory(void); @@ -1199,6 +1199,8 @@ int xusleep(unsigned int usec); void keepCapabilities(void); +extern char *sockaddr_ntoa(struct sockaddr *); + #if USE_HTCP extern void htcpInit(void); extern void htcpQuery(StoreEntry * e, request_t * req, peer * p); Index: src/redirect.c =================================================================== RCS file: /cvsroot/squid/squid/src/redirect.c,v retrieving revision 1.96 diff -u -I\$Id -r1.96 redirect.c --- src/redirect.c 8 Jul 2006 16:01:12 -0000 1.96 +++ src/redirect.c 5 Jul 2008 09:37:35 -0000 @@ -38,7 +38,7 @@ typedef struct { void *data; char *orig_url; - struct in_addr client_addr; + struct sockaddr_storage client_addr; const char *client_ident; const char *method_s; RH *handler; @@ -109,7 +109,7 @@ } r = cbdataAlloc(redirectStateData); r->orig_url = xstrdup(http->uri); - r->client_addr = conn->log_addr; + xmemcpy(&r->client_addr, &conn->log_addr, sizeof(struct sockaddr_storage)); r->client_ident = NULL; if (http->request->auth_user_request) r->client_ident = authenticateUserRequestUsername(http->request->auth_user_request); @@ -128,11 +128,11 @@ r->handler = handler; r->data = data; cbdataLock(r->data); - if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL) + if ((fqdn = fqdncache_gethostbyaddr(&r->client_addr, 0)) == NULL) fqdn = dash_str; snprintf(buf, 8192, "%s %s/%s %s %s %s\n", r->orig_url, - inet_ntoa(r->client_addr), + sockaddr_ntoa(&r->client_addr), fqdn, r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str, r->method_s, Index: src/send-announce.c =================================================================== RCS file: /cvsroot/squid/squid/src/send-announce.c,v retrieving revision 1.65 diff -u -I\$Id -r1.65 send-announce.c --- src/send-announce.c 25 May 2006 03:36:56 -0000 1.65 +++ src/send-announce.c 5 Jul 2008 09:37:35 -0000 @@ -53,7 +53,7 @@ { LOCAL_ARRAY(char, tbuf, 256); LOCAL_ARRAY(char, sndbuf, BUFSIZ); - struct sockaddr_in S; + struct sockaddr_storage S; char *host = Config.Announce.host; char *file = NULL; u_short port = Config.Announce.port; @@ -96,9 +96,11 @@ } } memset(&S, '\0', sizeof(S)); - S.sin_family = AF_INET; - S.sin_port = htons(port); - S.sin_addr = ia->in_addrs[0]; + xmemcpy(&S, &ia->in_addrs[0], sizeof(S)); + if (S.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&S)->sin6_port = htons(port); + if (S.ss_family == AF_INET) + ((struct sockaddr_in *)&S)->sin_port = htons(port); assert(theOutIcpConnection > 0); x = comm_udp_sendto(theOutIcpConnection, &S, sizeof(S), Index: src/snmp_agent.c =================================================================== RCS file: /cvsroot/squid/squid/src/snmp_agent.c,v retrieving revision 1.89 diff -u -I\$Id -r1.89 snmp_agent.c --- src/snmp_agent.c 9 Nov 2006 16:35:07 -0000 1.89 +++ src/snmp_agent.c 5 Jul 2008 09:37:35 -0000 @@ -164,7 +164,7 @@ laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]); for (p = Config.peers; p != NULL; p = p->next, cnt++) { index++; - if (p->in_addr.sin_addr.s_addr == laddr->s_addr) + if (((struct sockaddr_in *)&p->in_addr)->sin_addr.s_addr == laddr->s_addr) break; } break; @@ -201,7 +201,7 @@ break; case MESH_PTBL_IP: Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) p->in_addr.sin_addr.s_addr, + (snint) ((struct sockaddr_in *)&p->in_addr)->sin_addr.s_addr, SMI_IPADDRESS); break; case MESH_PTBL_HTTP: Index: src/snmp_core.c =================================================================== RCS file: /cvsroot/squid/squid/src/snmp_core.c,v retrieving revision 1.63 diff -u -I\$Id -r1.63 snmp_core.c --- src/snmp_core.c 28 Nov 2006 23:16:48 -0000 1.63 +++ src/snmp_core.c 5 Jul 2008 09:37:35 -0000 @@ -390,17 +390,21 @@ snmpConnectionOpen(void) { u_short port; - struct sockaddr_in xaddr; + struct sockaddr_storage xaddr; socklen_t len; int x; debug(49, 5) ("snmpConnectionOpen: Called\n"); if ((port = Config.Port.snmp) > (u_short) 0) { enter_suid(); + + if (Config.Addrs.snmp_incoming.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&Config.Addrs.snmp_incoming)->sin6_port = ntohs(port); + else + ((struct sockaddr_in *)&Config.Addrs.snmp_incoming)->sin_port = ntohs(port); theInSnmpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.snmp_incoming, - port, + &Config.Addrs.snmp_incoming, COMM_NONBLOCKING, "SNMP Port"); leave_suid(); @@ -409,12 +413,18 @@ commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n", (int) port, theInSnmpConnection); - if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) { + if ((Config.Addrs.snmp_outgoing.ss_family == AF_INET6 && + !IN6_IS_ADDR_ALLF(&(((struct sockaddr_in6 *)&Config.Addrs.snmp_outgoing)->sin6_addr))) || + (Config.Addrs.snmp_outgoing.ss_family == AF_INET && + ((struct sockaddr_in *)&Config.Addrs.snmp_outgoing)->sin_addr.s_addr != no_addr.s_addr)) { enter_suid(); + if (Config.Addrs.snmp_outgoing.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&Config.Addrs.snmp_outgoing)->sin6_port = ntohs(port); + else + ((struct sockaddr_in *)&Config.Addrs.snmp_outgoing)->sin_port = ntohs(port); theOutSnmpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.snmp_outgoing, - port, + &Config.Addrs.snmp_outgoing, COMM_NONBLOCKING, "SNMP Port"); leave_suid(); @@ -431,8 +441,8 @@ } else { theOutSnmpConnection = theInSnmpConnection; } - memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr)); - len = sizeof(struct sockaddr_in); + memset(&theOutSNMPAddr, '\0', sizeof(struct sockaddr_storage)); + len = sizeof(struct sockaddr_storage); memset(&xaddr, '\0', len); x = getsockname(theOutSnmpConnection, (struct sockaddr *) &xaddr, &len); @@ -440,7 +450,7 @@ debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n", theOutSnmpConnection, xstrerror()); else - theOutSNMPAddr = xaddr.sin_addr; + xmemcpy(&theOutSNMPAddr, &xaddr, sizeof(xaddr)); } } @@ -490,7 +500,7 @@ snmpHandleUdp(int sock, void *not_used) { LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE); - struct sockaddr_in from; + struct sockaddr_storage from; socklen_t from_len; snmp_request_t *snmp_rq; int len; @@ -498,7 +508,7 @@ debug(49, 5) ("snmpHandleUdp: Called.\n"); commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); - from_len = sizeof(struct sockaddr_in); + from_len = sizeof(struct sockaddr_storage); memset(&from, '\0', from_len); memset(buf, '\0', SNMP_REQUEST_SIZE); @@ -516,14 +526,14 @@ debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n", sock, len, - inet_ntoa(from.sin_addr)); + sockaddr_ntoa(&from)); snmp_rq = xcalloc(1, sizeof(snmp_request_t)); snmp_rq->buf = (u_char *) buf; snmp_rq->len = len; snmp_rq->sock = sock; snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE); - xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in)); + xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_storage)); snmpDecodePacket(snmp_rq); xfree(snmp_rq->outbuf); xfree(snmp_rq); @@ -551,7 +561,7 @@ rq->session.Version = SNMP_VERSION_1; Community = snmp_parse(&rq->session, PDU, buf, len); memset(&checklist, '\0', sizeof(checklist)); - checklist.src_addr = rq->from.sin_addr; + xmemcpy(&checklist.src_addr, &rq->from, SOCKLEN(&rq->from)); checklist.snmp_community = (char *) Community; if (Community) @@ -563,7 +573,7 @@ snmpConstructReponse(rq); } else { debug(49, 1) ("Failed SNMP agent query from : %s.\n", - inet_ntoa(rq->from.sin_addr)); + sockaddr_ntoa(&rq->from)); snmp_free_pdu(PDU); } if (Community) @@ -583,7 +593,7 @@ snmp_free_pdu(rq->PDU); if (RespPDU != NULL) { snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen); - comm_udp_sendto(rq->sock, &rq->from, sizeof(rq->from), rq->outbuf, rq->outlen); + comm_udp_sendto(rq->sock, &rq->from, SOCKLEN(&rq->from), rq->outbuf, rq->outlen); snmp_free_pdu(RespPDU); } } @@ -817,24 +827,46 @@ if (peerptr == NULL) { /* Do nothing */ } else if (*len <= current->len) { - instance = xmalloc(sizeof(name) * (*len + 4)); + if (peerptr->in_addr.ss_family == AF_INET6) + instance = xmalloc(sizeof(name) * (*len + 16)); + else + instance = xmalloc(sizeof(name) * (*len + 4)); xmemcpy(instance, name, (sizeof(name) * *len)); - cp = (u_char *) & (peerptr->in_addr.sin_addr.s_addr); + if (peerptr->in_addr.ss_family == AF_INET6) + cp = (u_char *) & (((struct sockaddr_in6 *)&peerptr->in_addr)->sin6_addr.s6_addr); + else + cp = (u_char *) & (((struct sockaddr_in *)&peerptr->in_addr)->sin_addr.s_addr); instance[*len] = *cp++; instance[*len + 1] = *cp++; instance[*len + 2] = *cp++; instance[*len + 3] = *cp++; - *len += 4; + if (peerptr->in_addr.ss_family == AF_INET6) { + instance[*len + 4] = *cp++; + instance[*len + 5] = *cp++; + instance[*len + 6] = *cp++; + instance[*len + 7] = *cp++; + instance[*len + 8] = *cp++; + instance[*len + 9] = *cp++; + instance[*len + 10] = *cp++; + instance[*len + 11] = *cp++; + instance[*len + 12] = *cp++; + instance[*len + 13] = *cp++; + instance[*len + 14] = *cp++; + instance[*len + 15] = *cp++; + *len += 16; + } + else + *len += 4; } else { laddr = oid2addr(&name[*len - 4]); host_addr = inet_ntoa(*laddr); last_addr = xstrdup(host_addr); skip_duplicate: - current_addr = inet_ntoa(peerptr->in_addr.sin_addr); + current_addr = sockaddr_ntoa(&peerptr->in_addr); while (peerptr && strcmp(last_addr, current_addr) != 0) { peerptr = peerptr->next; if (peerptr) - current_addr = inet_ntoa(peerptr->in_addr.sin_addr); + current_addr = sockaddr_ntoa(&peerptr->in_addr); } /* Find the next peer */ @@ -843,7 +875,7 @@ /* watch out for duplicate addresses */ for (peerptr2 = Config.peers; peerptr && peerptr2 != peerptr; peerptr2 = peerptr2->next) { - if (peerptr2->in_addr.sin_addr.s_addr == peerptr->in_addr.sin_addr.s_addr) { + if (memcmp(&peerptr2->in_addr, &peerptr->in_addr, SOCKLEN(&peerptr->in_addr))) { /* ouch.. there are more than one peer on this IP. Skip the second one */ peerptr = peerptr->next; if (peerptr) @@ -856,7 +888,23 @@ if (peerptr) { instance = xmalloc(sizeof(name) * (*len)); xmemcpy(instance, name, (sizeof(name) * *len)); - cp = (u_char *) & (peerptr->in_addr.sin_addr.s_addr); + if (peerptr->in_addr.ss_family == AF_INET6) { + cp = (u_char *) & (((struct sockaddr_in6 *)&peerptr->in_addr)->sin6_addr.s6_addr); + instance[*len - 16] = *cp++; + instance[*len - 15] = *cp++; + instance[*len - 14] = *cp++; + instance[*len - 13] = *cp++; + instance[*len - 12] = *cp++; + instance[*len - 11] = *cp++; + instance[*len - 10] = *cp++; + instance[*len - 9] = *cp++; + instance[*len - 8] = *cp++; + instance[*len - 7] = *cp++; + instance[*len - 6] = *cp++; + instance[*len - 5] = *cp++; + } + else + cp = (u_char *) & (((struct sockaddr_in *)&peerptr->in_addr)->sin_addr.s_addr); instance[*len - 4] = *cp++; instance[*len - 3] = *cp++; instance[*len - 2] = *cp++; Index: src/ssl.c =================================================================== RCS file: /cvsroot/squid/squid/src/ssl.c,v retrieving revision 1.134.2.1 diff -u -I\$Id -r1.134.2.1 ssl.c --- src/ssl.c 3 Feb 2007 21:53:38 -0000 1.134.2.1 +++ src/ssl.c 5 Jul 2008 09:37:36 -0000 @@ -36,6 +36,8 @@ #include "squid.h" typedef struct { + hash_link hash; /* dummy, must be first */ + int ia_cur; char *url; char *host; /* either request->host or proxy host */ u_short port; @@ -407,6 +409,30 @@ static void +sslConnectTimeout(int fd, void *data) +{ + SslStateData *sslState = data; + request_t *request = sslState->request; + ErrorState *err = NULL; + if (sslState->servers->peer) + hierarchyNote(&sslState->request->hier, sslState->servers->code, + sslState->servers->peer->name); + else if (Config.onoff.log_ip_on_direct) + hierarchyNote(&sslState->request->hier, sslState->servers->code, + fd_table[sslState->server.fd].ipaddr); + else + hierarchyNote(&sslState->request->hier, sslState->servers->code, + sslState->host); + comm_close(fd); + err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); + *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; + err->xerrno = ETIMEDOUT; + err->callback = sslErrorComplete; + err->callback_data = sslState; + errorSend(sslState->client.fd, err); +} + +static void sslConnectDone(int fd, int status, void *data) { SslStateData *sslState = data; @@ -430,6 +456,49 @@ err->callback = sslErrorComplete; err->callback_data = sslState; errorSend(sslState->client.fd, err); + } else if (status == COMM_ERR_INV_ARGS) { + int newsock; + struct sockaddr_storage cursockaddr, newsockaddr; + socklen_t cursocklen = sizeof(cursockaddr); + + getsockname(fd, (struct sockaddr *)&cursockaddr, &cursocklen); + memset(&newsockaddr, '\0', sizeof(newsockaddr)); + if (cursockaddr.ss_family == AF_INET6) + newsockaddr.ss_family = AF_INET; + else + newsockaddr.ss_family = AF_INET6; + newsock = comm_openex(SOCK_STREAM, + IPPROTO_TCP, + &newsockaddr, + COMM_NONBLOCKING, + 0, + sslState->url); + if (newsock == COMM_ERROR) { + debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); + err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request); + err->xerrno = errno; + err->callback = sslErrorComplete; + err->callback_data = sslState; + errorSend(sslState->client.fd, err); + return; + } + comm_remove_close_handler(sslState->server.fd, + sslServerClosed, + sslState); + comm_close(sslState->server.fd); + sslState->server.fd = newsock; + comm_add_close_handler(sslState->server.fd, + sslServerClosed, + sslState); + sslSetSelect(sslState); + commSetTimeout(sslState->server.fd, + Config.Timeout.connect, + sslConnectTimeout, + sslState); + commConnectStart(sslState->server.fd, + sslState->host, sslState->port, + sslConnectDone, + sslState); } else if (status != COMM_OK) { comm_close(fd); err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); @@ -454,30 +523,6 @@ } } -static void -sslConnectTimeout(int fd, void *data) -{ - SslStateData *sslState = data; - request_t *request = sslState->request; - ErrorState *err = NULL; - if (sslState->servers->peer) - hierarchyNote(&sslState->request->hier, sslState->servers->code, - sslState->servers->peer->name); - else if (Config.onoff.log_ip_on_direct) - hierarchyNote(&sslState->request->hier, sslState->servers->code, - fd_table[sslState->server.fd].ipaddr); - else - hierarchyNote(&sslState->request->hier, sslState->servers->code, - sslState->host); - comm_close(fd); - err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); - *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; - err->xerrno = ETIMEDOUT; - err->callback = sslErrorComplete; - err->callback_data = sslState; - errorSend(sslState->client.fd, err); -} - CBDATA_TYPE(SslStateData); void sslStart(clientHttpRequest * http, squid_off_t * size_ptr, int *status_ptr) @@ -491,18 +536,22 @@ int fd = http->conn->fd; request_t *request = http->request; char *url = http->uri; + struct sockaddr_storage addr; /* * client_addr == no_addr indicates this is an "internal" request * from peer_digest.c, asn.c, netdb.c, etc and should always * be allowed. yuck, I know. */ - if (request->client_addr.s_addr != no_addr.s_addr) { + if ( ((request->client_addr.ss_family == AF_INET6) && + !IN6_IS_ADDR_ALLF(&((struct sockaddr_in6 *)&request->client_addr)->sin6_addr)) || + ((request->client_addr.ss_family == AF_INET) && + (((struct sockaddr_in *)&request->client_addr)->sin_addr.s_addr != no_addr.s_addr))) { /* * Check if this host is allowed to fetch MISSES from us (miss_access) */ memset(&ch, '\0', sizeof(aclCheck_t)); - ch.src_addr = request->client_addr; - ch.my_addr = request->my_addr; + xmemcpy(&ch.src_addr, &request->client_addr, sizeof(ch.src_addr)); + xmemcpy(&ch.my_addr, &request->my_addr, sizeof(ch.my_addr)); ch.my_port = request->my_port; ch.request = request; answer = aclCheckFast(Config.accessList.miss, &ch); @@ -518,12 +567,13 @@ statCounter.server.all.requests++; statCounter.server.other.requests++; /* Create socket. */ + memset(&addr, '\0', sizeof(addr)); + addr.ss_family = AF_INET; sock = comm_openex(SOCK_STREAM, IPPROTO_TCP, - getOutgoingAddr(request), - 0, + &addr, COMM_NONBLOCKING, - getOutgoingTOS(request), + 0, url); if (sock == COMM_ERROR) { debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); @@ -549,6 +599,7 @@ sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF); /* Copy any pending data from the client connection */ sslState->client.len = http->conn->in.offset; + sslState->ia_cur = -1; if (sslState->client.len > 0) { if (sslState->client.len > SQUID_TCP_SO_RCVBUF) { safe_free(sslState->client.buf); @@ -607,9 +658,13 @@ static void sslPeerSelectComplete(FwdServer * fs, void *data) { + struct sockaddr_storage sslsock, cursockaddr; + ErrorState *err = NULL; + int newsock = -1; SslStateData *sslState = data; request_t *request = sslState->request; peer *g = NULL; + socklen_t cursocklen = sizeof(cursockaddr); if (fs == NULL) { ErrorState *err; err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, sslState->request); @@ -621,6 +676,13 @@ } sslState->servers = fs; sslState->host = fs->peer ? fs->peer->host : request->host; + if (fs->peer) + xmemcpy(&sslsock, &fs->peer->in_addr, sizeof(struct sockaddr_storage)); + else + memset(&sslsock, '\0', sizeof(struct sockaddr_storage)); +/* + xmemcpy(&sslsock, &request->client_addr, sizeof(struct sockaddr_storage)); +*/ if (fs->peer == NULL) { sslState->port = request->port; } else if (fs->peer->http_port != 0) { @@ -644,13 +706,44 @@ sslState->delay_id = 0; } #endif + if (sslsock.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&sslsock)->sin6_port = sslState->port; + else + ((struct sockaddr_in *)&sslsock)->sin_port = sslState->port; + getsockname(sslState->server.fd, (struct sockaddr *)&cursockaddr, &cursocklen); + if (!sslState->host && cursockaddr.ss_family != sslsock.ss_family) { + memset(&cursockaddr, '\0', sizeof(cursockaddr)); + cursockaddr.ss_family = sslsock.ss_family; + newsock = comm_openex(SOCK_STREAM, + IPPROTO_TCP, + &cursockaddr, + COMM_NONBLOCKING, + 0, + sslState->url); + if (newsock == COMM_ERROR) { + debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); + err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request); + err->xerrno = errno; + errorSend(sslState->client.fd, err); + return; + } + comm_remove_close_handler(sslState->server.fd, + sslServerClosed, + sslState); + comm_close(sslState->server.fd); + + sslState->server.fd = newsock; + comm_add_close_handler(sslState->server.fd, + sslServerClosed, + sslState); + sslSetSelect(sslState); + } commSetTimeout(sslState->server.fd, Config.Timeout.connect, sslConnectTimeout, sslState); commConnectStart(sslState->server.fd, - sslState->host, - sslState->port, + sslState->host, sslState->port, sslConnectDone, sslState); } Index: src/stat.c =================================================================== RCS file: /cvsroot/squid/squid/src/stat.c,v retrieving revision 1.377 diff -u -I\$Id -r1.377 stat.c --- src/stat.c 1 Nov 2006 20:58:52 -0000 1.377 +++ src/stat.c 5 Jul 2008 09:37:36 -0000 @@ -1469,6 +1469,7 @@ ConnStateData *conn; StoreEntry *e; int fd; + char host[100], port[8]; for (i = ClientActiveRequests.head; i; i = i->next) { const char *p = NULL; http = i->data; @@ -1482,12 +1483,12 @@ storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc); storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n", conn->in.buf, (long int) conn->in.offset, (long int) conn->in.size); - storeAppendPrintf(s, "\tpeer: %s:%d\n", - inet_ntoa(conn->peer.sin_addr), - ntohs(conn->peer.sin_port)); - storeAppendPrintf(s, "\tme: %s:%d\n", - inet_ntoa(conn->me.sin_addr), - ntohs(conn->me.sin_port)); + getnameinfo(&conn->peer, sizeof(struct sockaddr_storage), + host, 100, port, 8, NI_NUMERICHOST|NI_NUMERICSERV); + storeAppendPrintf(s, "\tpeer: %s:%s\n", host, port); + getnameinfo(&conn->me, sizeof(struct sockaddr_storage), + host, 100, port, 8, NI_NUMERICHOST|NI_NUMERICSERV); + storeAppendPrintf(s, "\tme: %s:%s\n", host, port); storeAppendPrintf(s, "\tnrequests: %d\n", conn->nrequests); storeAppendPrintf(s, "\tdefer: n %d, until %ld\n", Index: src/structs.h =================================================================== RCS file: /cvsroot/squid/squid/src/structs.h,v retrieving revision 1.507.2.5 diff -u -I\$Id -r1.507.2.5 structs.h --- src/structs.h 26 Apr 2007 23:11:51 -0000 1.507.2.5 +++ src/structs.h 5 Jul 2008 09:37:36 -0000 @@ -72,9 +72,9 @@ }; struct _acl_ip_data { - struct in_addr addr1; /* if addr2 non-zero then its a range */ - struct in_addr addr2; - struct in_addr mask; + struct sockaddr_storage addr1; /* if addr2 non-zero then its a range */ + struct sockaddr_storage addr2; + int masklen; acl_ip_data *next; /* used for parsing, not for storing */ }; @@ -114,7 +114,7 @@ struct _auth_user_ip_t { dlink_node node; /* IP addr this user authenticated from */ - struct in_addr ipaddr; + struct sockaddr_storage ipaddr; time_t ip_expiretime; }; @@ -254,7 +254,7 @@ int sock; long reqid; int outlen; - struct sockaddr_in from; + struct in_addr from; struct snmp_pdu *PDU; aclCheck_t *acl_checklist; u_char *community; @@ -287,7 +287,7 @@ struct _acl_address { acl_address *next; acl_list *acl_list; - struct in_addr addr; + struct sockaddr_storage addr; }; struct _acl_tos { @@ -298,9 +298,9 @@ struct _aclCheck_t { const acl_access *access_list; - struct in_addr src_addr; - struct in_addr dst_addr; - struct in_addr my_addr; + struct sockaddr_storage src_addr; + struct sockaddr_storage dst_addr; + struct sockaddr_storage my_addr; unsigned short my_port; request_t *request; /* for acls that look at reply data */ @@ -351,14 +351,14 @@ unsigned int internal:1; }; -struct _sockaddr_in_list { - struct sockaddr_in s; - sockaddr_in_list *next; +struct _sockaddr_storage_list { + struct sockaddr_storage s; + sockaddr_storage_list *next; }; struct _http_port_list { http_port_list *next; - struct sockaddr_in s; + struct sockaddr_storage s; char *protocol; /* protocol name */ char *name; /* visible name */ char *defaultsite; /* default web site */ @@ -496,15 +496,15 @@ #endif #if USE_WCCP struct { - struct in_addr router; - struct in_addr address; + struct sockaddr_storage router; + struct sockaddr_storage address; int version; } Wccp; #endif #if USE_WCCPv2 struct { - sockaddr_in_list *router; - struct in_addr address; + sockaddr_storage_list *router; + struct sockaddr_storage address; int forwarding_method; int return_method; int assignment_method; @@ -585,13 +585,17 @@ u_short port; } Announce; struct { - struct in_addr udp_incoming; - struct in_addr udp_outgoing; + struct sockaddr_storage udp_incoming; + struct sockaddr_storage udp_outgoing; #if SQUID_SNMP - struct in_addr snmp_incoming; - struct in_addr snmp_outgoing; + struct sockaddr_storage snmp_incoming; + struct sockaddr_storage snmp_outgoing; #endif - struct in_addr client_netmask; + struct sockaddr_storage client_netmask; + struct sockaddr_storage udp6_incoming; + struct sockaddr_storage udp6_outgoing; + int client_masklen; + int client6_masklen; } Addrs; squid_off_t tcpRcvBufsz; squid_off_t udpMaxHitObjsz; @@ -760,7 +764,7 @@ squid_off_t rangeOffsetLimit; #if MULTICAST_MISS_STREAM struct { - struct in_addr addr; + struct sockaddr_storage addr; int ttl; unsigned short port; char *encode_key; @@ -869,9 +873,9 @@ unsigned int type; u_short local_port; u_short remote_port; - struct in_addr local_addr; + struct sockaddr_storage local_addr; unsigned char tos; - char ipaddr[16]; /* dotted decimal address of peer */ + char ipaddr[80]; /* dotted decimal address of peer */ char desc[FD_DESC_SZ]; struct { unsigned int open:1; @@ -1115,7 +1119,7 @@ }; struct _icpUdpData { - struct sockaddr_in address; + struct sockaddr_storage address; void *msg; size_t len; icpUdpData *next; @@ -1162,7 +1166,7 @@ icp_opcode opcode; } icp; struct { - struct in_addr caddr; + struct sockaddr_storage caddr; squid_off_t size; size_t rq_size; log_type code; @@ -1260,9 +1264,9 @@ /* the user details for connection based authentication */ auth_user_request_t *auth_user_request; dlink_list reqs; - struct sockaddr_in peer; - struct sockaddr_in me; - struct in_addr log_addr; + struct sockaddr_storage peer; + struct sockaddr_storage me; + struct sockaddr_storage log_addr; char rfc931[USER_IDENT_SZ]; int nrequests; struct { @@ -1282,11 +1286,13 @@ }; struct _ipcache_addrs { - struct in_addr *in_addrs; + struct sockaddr_storage *in_addrs; unsigned char *bad_mask; unsigned char count; + unsigned char count6; unsigned char cur; unsigned char badcount; + unsigned char badcount6; }; struct _domain_ping { @@ -1382,10 +1388,12 @@ #endif struct _peer { + hash_link hash; /* dummy, must be first */ + int ia_cur; char *name; char *host; peer_t type; - struct sockaddr_in in_addr; + struct sockaddr_storage in_addr; struct { int pings_sent; int pings_acked; @@ -1459,7 +1467,7 @@ char *digest_url; #endif int tcp_up; /* 0 if a connect() fails */ - struct in_addr addresses[10]; + struct sockaddr_storage addresses[10]; int n_addresses; int rr_count; int rr_lastcount; @@ -1553,14 +1561,14 @@ void *callback_data; FwdServer *servers; /* - * Why are these struct sockaddr_in instead of peer *? Because a + * Why are these struct sockaddr_storage instead of peer *? Because a * peer structure can become invalid during the peer selection * phase, specifically after a reconfigure. Thus we need to lookup * the peer * based on the address when we are finally ready to * reference the peer structure. */ - struct sockaddr_in first_parent_miss; - struct sockaddr_in closest_parent_miss; + struct sockaddr_storage first_parent_miss; + struct sockaddr_storage closest_parent_miss; /* * ->hit and ->secho can be peer* because they should only be * accessed during the thread when they are set @@ -1576,14 +1584,14 @@ #if USE_ICMP struct _pingerEchoData { - struct in_addr to; + struct sockaddr_storage to; unsigned char opcode; int psize; char payload[PINGER_PAYLOAD_SZ]; }; struct _pingerReplyData { - struct in_addr from; + struct sockaddr_storage from; unsigned char opcode; int rtt; int hops; @@ -1600,7 +1608,7 @@ u_num32 reqnum; /* req number (req'd for UDP) */ u_num32 flags; u_num32 pad; - u_num32 shostid; /* sender host id */ + struct sockaddr_storage shostid; /* sender host id */ }; struct _iostats { @@ -1885,11 +1893,11 @@ int max_forwards; /* these in_addr's could probably be sockaddr_in's */ unsigned short client_port; - struct in_addr client_addr; + struct sockaddr_storage client_addr; #if FOLLOW_X_FORWARDED_FOR - struct in_addr indirect_client_addr; /* after following X-Forwarded-For */ + struct sockaddr_storage indirect_client_addr; /* after following X-Forwarded-For */ #endif /* FOLLOW_X_FORWARDED_FOR */ - struct in_addr my_addr; + struct sockaddr_storage my_addr; unsigned short my_port; HttpHeader header; squid_off_t content_length; @@ -1956,7 +1964,7 @@ int xerrno; char *dnsserver_msg; time_t ttl; - struct in_addr src_addr; + struct sockaddr_storage src_addr; char *redirect_url; ERCB *callback; void *callback_data; @@ -2197,7 +2205,7 @@ struct _ClientInfo { hash_link hash; /* must be first */ - struct in_addr addr; + struct sockaddr_storage addr; struct { int result_hist[LOG_TYPE_MAX]; int n_requests; @@ -2231,11 +2239,15 @@ }; struct _FwdState { + hash_link hash; /* dummy, must be first */ + int ia_cur; int client_fd; /* XXX unnecessary */ StoreEntry *entry; request_t *request; FwdServer *servers; int server_fd; + int server_fd_was_v6; + int server_fd_was_inv_args; ErrorState *err; time_t start; int n_tries; @@ -2248,7 +2260,7 @@ unsigned int ftp_pasv_failed:1; } flags; #if LINUX_NETFILTER - struct sockaddr_in src; + struct sockaddr_storage src; #endif }; Index: src/tools.c =================================================================== RCS file: /cvsroot/squid/squid/src/tools.c,v retrieving revision 1.250 diff -u -I\$Id -r1.250 tools.c --- src/tools.c 4 Nov 2006 17:09:45 -0000 1.250 +++ src/tools.c 5 Jul 2008 09:37:36 -0000 @@ -499,10 +499,10 @@ host[0] = '\0'; memcpy(&sa, &any_addr, sizeof(sa)); if (Config.Sockaddr.http && sa.s_addr == any_addr.s_addr) - memcpy(&sa, &Config.Sockaddr.http->s.sin_addr, sizeof(sa)); + memcpy(&sa, &((struct sockaddr_in *)&Config.Sockaddr.http->s)->sin_addr, sizeof(sa)); #if USE_SSL if (Config.Sockaddr.https && sa.s_addr == any_addr.s_addr) - memcpy(&sa, &Config.Sockaddr.https->http.s.sin_addr, sizeof(sa)); + memcpy(&sa, &((struct sockaddr_in *)&Config.Sockaddr.https->http.s)->sin_addr, sizeof(sa)); #endif /* * If the first http_port address has a specific address, try a @@ -1296,10 +1296,10 @@ getMyPort(void) { if (Config.Sockaddr.http) - return ntohs(Config.Sockaddr.http->s.sin_port); + return ntohs(((struct sockaddr_in *)&Config.Sockaddr.http->s)->sin_port); #if USE_SSL if (Config.Sockaddr.https) - return ntohs(Config.Sockaddr.https->http.s.sin_port); + return ntohs(((struct sockaddr_in *)&Config.Sockaddr.https->http.s)->sin_port); #endif fatal("No port defined"); return 0; /* NOT REACHED */ @@ -1346,3 +1346,15 @@ } #endif } + +char * +sockaddr_ntoa(struct sockaddr *addr) +{ + static char host[100]; + char *stopchar; + memset(host, '\0', 100); + getnameinfo(addr, SOCKLEN(addr), host, 100, NULL, 0, NI_NUMERICHOST); + if ((stopchar = strchr(host, '%'))) + *stopchar = '\0'; + return host; +} Index: src/typedefs.h =================================================================== RCS file: /cvsroot/squid/squid/src/typedefs.h,v retrieving revision 1.151 diff -u -I\$Id -r1.151 typedefs.h --- src/typedefs.h 2 Sep 2006 14:08:42 -0000 1.151 +++ src/typedefs.h 5 Jul 2008 09:37:36 -0000 @@ -108,7 +108,7 @@ typedef struct _intrange intrange; typedef struct _ushortlist ushortlist; typedef struct _relist relist; -typedef struct _sockaddr_in_list sockaddr_in_list; +typedef struct _sockaddr_storage_list sockaddr_storage_list; typedef struct _http_port_list http_port_list; typedef struct _https_port_list https_port_list; typedef struct _SquidConfig SquidConfig; Index: src/url.c =================================================================== RCS file: /cvsroot/squid/squid/src/url.c,v retrieving revision 1.144.2.1 diff -u -I\$Id -r1.144.2.1 url.c --- src/url.c 3 Mar 2007 18:34:13 -0000 1.144.2.1 +++ src/url.c 5 Jul 2008 09:37:36 -0000 @@ -110,6 +110,8 @@ }; static request_t *urnParse(method_t method, char *urn); +static const char valid_ipv6_addr_chars[] = +"ABCDEFabcdef0123456789:"; static const char valid_hostname_chars_u[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" @@ -287,7 +289,10 @@ *t = 0; strcpy((char *) host, t + 1); } - if ((t = strrchr(host, ':'))) { + q = host; + if (strchr(host, '[') && strchr(host, ']')) + q = strchr(host, ']'); + if ((t = strrchr(q, ':'))) { *t++ = '\0'; if (*t != '\0') port = atoi(t); @@ -306,12 +311,20 @@ *q = '\0'; } } - if (Config.onoff.check_hostnames && strspn(host, Config.onoff.allow_underscore ? valid_hostname_chars_u : valid_hostname_chars) != strlen(host)) { - debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host); - return NULL; + if (host == strrchr(host, '[') && + (host + strlen(host)-1) == strchr(host, ']')) { + if (strspn(host+1, valid_ipv6_addr_chars) != strlen(host)-2) { /* IPv6 address */ + debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host); + return NULL; + } + } else { + if (Config.onoff.check_hostnames && strspn(host, Config.onoff.allow_underscore ? valid_hostname_chars_u : valid_hostname_chars) != strlen(host)) { + debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host); + return NULL; + } + if (Config.appendDomain && !strchr(host, '.')) + strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(host) - 1); } - if (Config.appendDomain && !strchr(host, '.')) - strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(host) - 1); /* remove trailing dots from hostnames */ while ((l = strlen(host)) > 0 && host[--l] == '.') host[l] = '\0'; @@ -358,7 +371,12 @@ } } request = requestCreate(method, protocol, urlpath); - xstrncpy(request->host, host, SQUIDHOSTNAMELEN); + if (strchr(host, '[')) { + xstrncpy(request->host, host+1, SQUIDHOSTNAMELEN); + request->host[strlen(host)-2] = '\0'; + } + else + xstrncpy(request->host, host, SQUIDHOSTNAMELEN); xstrncpy(request->login, login, MAX_LOGIN_SZ); request->port = (u_short) port; return request; @@ -405,6 +423,7 @@ char * urlCanonicalClean(const request_t * request) { + LOCAL_ARRAY(char, hostbuf, MAX_URL); LOCAL_ARRAY(char, buf, MAX_URL); LOCAL_ARRAY(char, portbuf, 32); LOCAL_ARRAY(char, loginbuf, MAX_LOGIN_SZ + 1); @@ -414,7 +433,11 @@ } else { switch (request->method) { case METHOD_CONNECT: - snprintf(buf, MAX_URL, "%s:%d", request->host, request->port); + if (strchr(request->host, ':')) + snprintf(hostbuf, MAX_URL, "[%s]", request->host); + else + snprintf(hostbuf, MAX_URL, "%s", request->host); + snprintf(buf, MAX_URL, "%s:%d", hostbuf, request->port); break; default: portbuf[0] = '\0'; @@ -427,10 +450,14 @@ *t = '\0'; strcat(loginbuf, "@"); } + if (strchr(request->host, ':')) + snprintf(hostbuf, MAX_URL, "[%s]", request->host); + else + snprintf(hostbuf, MAX_URL, "%s", request->host); snprintf(buf, MAX_URL, "%s://%s%s%s%s", ProtocolStr[request->protocol], loginbuf, - request->host, + hostbuf, portbuf, strBuf(request->urlpath)); /* Index: src/wccp.c =================================================================== RCS file: /cvsroot/squid/squid/src/wccp.c,v retrieving revision 1.31 diff -u -I\$Id -r1.31 wccp.c --- src/wccp.c 26 Jun 2006 15:01:59 -0000 1.31 +++ src/wccp.c 5 Jul 2008 09:37:36 -0000 @@ -112,7 +112,7 @@ last_id = 0; last_assign_buckets_change = 0; number_caches = 0; - if (Config.Wccp.router.s_addr != any_addr.s_addr) + if (((struct sockaddr_in *)&Config.Wccp.router)->sin_addr.s_addr != any_addr.s_addr) if (!eventFind(wccpHereIam, NULL)) eventAdd("wccpHereIam", wccpHereIam, NULL, 5.0, 1); } @@ -124,14 +124,17 @@ struct sockaddr_in router, local; socklen_t local_len, router_len; debug(80, 5) ("wccpConnectionOpen: Called\n"); - if (Config.Wccp.router.s_addr == any_addr.s_addr) { + if (((struct sockaddr_in *)&Config.Wccp.router)->sin_addr.s_addr == any_addr.s_addr) { debug(1, 1) ("WCCP Disabled.\n"); return; } + if (Config.Wccp.address.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&Config.Wccp.address)->sin6_port = ntohs(port); + else + ((struct sockaddr_in *)&Config.Wccp.address)->sin_port = ntohs(port); theWccpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Wccp.address, - port, + &Config.Wccp.address, COMM_NONBLOCKING, "WCCP Socket"); if (theWccpConnection < 0) @@ -147,7 +150,7 @@ memset(&router, '\0', router_len); router.sin_family = AF_INET; router.sin_port = htons(port); - router.sin_addr = Config.Wccp.router; + router.sin_addr = ((struct sockaddr_in *)&Config.Wccp.router)->sin_addr; if (connect(theWccpConnection, (struct sockaddr *) &router, router_len)) fatal("Unable to connect WCCP out socket"); local_len = sizeof(local); @@ -206,7 +209,7 @@ (unsigned) ntohl(wccp_i_see_you.number)); if (len < 0) return; - if (Config.Wccp.router.s_addr != from.sin_addr.s_addr) + if (((struct sockaddr_in *)&Config.Wccp.router)->sin_addr.s_addr != from.sin_addr.s_addr) return; if (ntohl(wccp_i_see_you.version) != Config.Wccp.version) return; Index: src/wccp2.c =================================================================== RCS file: /cvsroot/squid/squid/src/wccp2.c,v retrieving revision 1.30.2.1 diff -u -I\$Id -r1.30.2.1 wccp2.c --- src/wccp2.c 17 Apr 2007 09:40:59 -0000 1.30.2.1 +++ src/wccp2.c 5 Jul 2008 09:37:36 -0000 @@ -523,7 +523,7 @@ void wccp2Init(void) { - sockaddr_in_list *s; + sockaddr_storage_list *s; char *ptr; uint32_t service_flags; struct wccp2_service_list_t *service_list_ptr; @@ -537,7 +537,7 @@ /* Calculate the number of routers configured in the config file */ for (s = Config.Wccp2.router; s; s = s->next) { - if (s->s.sin_addr.s_addr != any_addr.s_addr) { + if (((struct sockaddr_in *)&s->s)->sin_addr.s_addr != any_addr.s_addr) { /* Increment the counter */ wccp2_numrouters++; } @@ -670,15 +670,15 @@ /* Add each router. Keep this functionality here to make sure the received_id can be updated in the packet */ for (s = Config.Wccp2.router; s; s = s->next) { - if (s->s.sin_addr.s_addr != any_addr.s_addr) { + if (((struct sockaddr_in *)&s->s)->sin_addr.s_addr != any_addr.s_addr) { wccp2_here_i_am_header.length += sizeof(struct wccp2_router_id_element_t); assert(wccp2_here_i_am_header.length <= WCCP_RESPONSE_SIZE); /* Add a pointer to the router list for this router */ router_list_ptr->info = (struct wccp2_router_id_element_t *) ptr; - router_list_ptr->info->router_address = s->s.sin_addr; + router_list_ptr->info->router_address = ((struct sockaddr_in *)&s->s)->sin_addr; router_list_ptr->info->received_id = htonl(0); - router_list_ptr->router_sendto_address = s->s.sin_addr; + router_list_ptr->router_sendto_address = ((struct sockaddr_in *)&s->s)->sin_addr; router_list_ptr->member_change = htonl(0); /* Build the next struct */ @@ -764,10 +764,13 @@ debug(80, 2) ("WCCPv2 Disabled.\n"); return; } + if (Config.Wccp2.address.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&Config.Wccp2.address)->sin6_port = ntohs(port); + else + ((struct sockaddr_in *)&Config.Wccp2.address)->sin_port = ntohs(port); theWccp2Connection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Wccp2.address, - port, + &Config.Wccp2.address, COMM_NONBLOCKING, "WCCPv2 Socket"); if (theWccp2Connection < 0) Index: src/auth/digest/auth_digest.c =================================================================== RCS file: /cvsroot/squid/squid/src/auth/digest/auth_digest.c,v retrieving revision 1.21 diff -u -I\$Id -r1.21 auth_digest.c --- src/auth/digest/auth_digest.c 30 Jul 2006 23:27:04 -0000 1.21 +++ src/auth/digest/auth_digest.c 5 Jul 2008 09:37:35 -0000 @@ -727,16 +727,17 @@ return; } else { const char *useragent = httpHeaderGetStr(&request->header, HDR_USER_AGENT); - static struct in_addr last_broken_addr; + static struct sockaddr_storage last_broken_addr; static int seen_broken_client = 0; if (!seen_broken_client) { - last_broken_addr = no_addr; + memset(&last_broken_addr, '\0', sizeof(last_broken_addr)); seen_broken_client = 1; } if (memcmp(&last_broken_addr, &request->client_addr, sizeof(last_broken_addr)) != 0) { - debug(29, 1) ("\nDigest POST bug detected from %s using '%s'. Please upgrade browser. See Bug #630 for details.\n", inet_ntoa(request->client_addr), useragent ? useragent : "-"); - last_broken_addr = request->client_addr; + debug(29, 1) ("\nDigest POST bug detected from %s using '%s'. Please upgrade browser. See Bug #630 for details.\n", sockaddr_ntoa(&request->client_addr), useragent ? useragent : "-"); + xmemcpy(&last_broken_addr, &request->client_addr, + SOCKLEN(&request->client_addr)); } } } else {