diff -r -u squid-2.6.STABLE13/configure new-STABLE13/configure
--- squid-2.6.STABLE13/configure	Fri May 11 08:59:36 2007
+++ new-STABLE13/configure	Sun May 13 00:59:36 2007
@@ -1,7 +1,7 @@
 #! /bin/sh
-# From configure.in Revision: 1.416.2.10 .
+# From configure.in Revision: 1.3 .
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for Squid Web Proxy 2.6.STABLE13.
+# Generated by GNU Autoconf 2.59 for Squid Web Proxy 2.6.STABLE13.v6patch20070512.
 #
 # Report bugs to <http://www.squid-cache.org/bugs/>.
 #
@@ -270,8 +270,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='2.6.STABLE13'
-PACKAGE_STRING='Squid Web Proxy 2.6.STABLE13'
+PACKAGE_VERSION='2.6.STABLE13.v6patch20070512'
+PACKAGE_STRING='Squid Web Proxy 2.6.STABLE13.v6patch20070512'
 PACKAGE_BUGREPORT='http://www.squid-cache.org/bugs/'
 
 ac_default_prefix=/usr/local/squid
@@ -781,7 +781,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Squid Web Proxy 2.6.STABLE13 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 2.6.STABLE13.v6patch20070512 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -847,7 +847,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 2.6.STABLE13:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 2.6.STABLE13.v6patch20070512:";;
    esac
   cat <<\_ACEOF
 
@@ -1158,7 +1158,7 @@
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 2.6.STABLE13
+Squid Web Proxy configure 2.6.STABLE13.v6patch20070512
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1172,7 +1172,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Squid Web Proxy $as_me 2.6.STABLE13, which was
+It was created by Squid Web Proxy $as_me 2.6.STABLE13.v6patch20070512, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1818,7 +1818,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='2.6.STABLE13'
+ VERSION='2.6.STABLE13.v6patch20070512'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -18614,7 +18614,7 @@
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by Squid Web Proxy $as_me 2.6.STABLE13, which was
+This file was extended by Squid Web Proxy $as_me 2.6.STABLE13.v6patch20070512, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -18677,7 +18677,7 @@
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-Squid Web Proxy config.status 2.6.STABLE13
+Squid Web Proxy config.status 2.6.STABLE13.v6patch20070512
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

diff -r -u squid-2.6.STABLE13/configure.in new-STABLE13/configure.in
--- squid-2.6.STABLE13/configure.in     Fri May 11 08:59:36 2007
+++ new-STABLE13/configure.in   Sun May 13 00:59:36 2007
@@ -5,7 +5,7 @@
 dnl
 dnl
 dnl
-AC_INIT(Squid Web Proxy, 2.HEAD-CVS, http://www.squid-cache.org/bugs/, squid)
+AC_INIT(Squid Web Proxy, 2.6STABLE13.v6patch.20070512, http://www.squid-cache.org/bugs/, squid)
 AC_PREREQ(2.52)
 AM_CONFIG_HEADER(include/autoconf.h)
 AC_CONFIG_AUX_DIR(cfgaux) 
diff -r -u squid-2.6.STABLE13/include/rfc1035.h new-STABLE13/include/rfc1035.h
--- squid-2.6.STABLE13/include/rfc1035.h	Fri Apr 28 19:17:18 2006
+++ new-STABLE13/include/rfc1035.h	Sun May 13 00:59:36 2007
@@ -38,6 +38,9 @@
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #if HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #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
diff -r -u squid-2.6.STABLE13/include/util.h new-STABLE13/include/util.h
--- squid-2.6.STABLE13/include/util.h	Sun Dec 10 22:36:23 2006
+++ new-STABLE13/include/util.h	Sun May 13 00:59:36 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/lib/rfc1035.c new-STABLE13/lib/rfc1035.c
--- squid-2.6.STABLE13/lib/rfc1035.c	Wed May 18 01:56:36 2005
+++ new-STABLE13/lib/rfc1035.c	Sun May 13 00:59:36 2007
@@ -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;
diff -r -u squid-2.6.STABLE13/lib/safe_inet_addr.c new-STABLE13/lib/safe_inet_addr.c
--- squid-2.6.STABLE13/lib/safe_inet_addr.c	Thu Feb  8 03:56:51 2001
+++ new-STABLE13/lib/safe_inet_addr.c	Sun May 13 00:59:36 2007
@@ -24,6 +24,9 @@
 #if HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
 #if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #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 <mijosxi@ike.tottori-u.ac.jp> 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;
+
 }
diff -r -u squid-2.6.STABLE13/src/HttpRequest.c new-STABLE13/src/HttpRequest.c
--- squid-2.6.STABLE13/src/HttpRequest.c	Mon Jul 17 11:31:59 2006
+++ new-STABLE13/src/HttpRequest.c	Sun May 13 00:59:36 2007
@@ -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");
diff -r -u squid-2.6.STABLE13/src/access_log.c new-STABLE13/src/access_log.c
--- squid-2.6.STABLE13/src/access_log.c	Sun Feb  4 06:59:24 2007
+++ new-STABLE13/src/access_log.c	Sun May 13 00:59:36 2007
@@ -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",
diff -r -u squid-2.6.STABLE13/src/acl.c new-STABLE13/src/acl.c
--- squid-2.6.STABLE13/src/acl.c	Sun Jan  7 02:22:45 2007
+++ new-STABLE13/src/acl.c	Sun May 13 00:59:36 2007
@@ -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;
+    }
+    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;
+	    }
+	}
     }
-    return rc;
+    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 */
diff -r -u squid-2.6.STABLE13/src/asn.c new-STABLE13/src/asn.c
--- squid-2.6.STABLE13/src/asn.c	Tue Jun  6 07:47:01 2006
+++ new-STABLE13/src/asn.c	Sun May 13 00:59:36 2007
@@ -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));
 
diff -r -u squid-2.6.STABLE13/src/auth/digest/auth_digest.c new-STABLE13/src/auth/digest/auth_digest.c
--- squid-2.6.STABLE13/src/auth/digest/auth_digest.c	Mon Jul 31 08:27:04 2006
+++ new-STABLE13/src/auth/digest/auth_digest.c	Sun May 13 00:59:37 2007
@@ -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 {
diff -r -u squid-2.6.STABLE13/src/authenticate.c new-STABLE13/src/authenticate.c
--- squid-2.6.STABLE13/src/authenticate.c	Tue Jan  2 07:44:58 2007
+++ new-STABLE13/src/authenticate.c	Sun May 13 00:59:36 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/cache_cf.c new-STABLE13/src/cache_cf.c
--- squid-2.6.STABLE13/src/cache_cf.c	Tue Feb 27 07:45:24 2007
+++ new-STABLE13/src/cache_cf.c	Sun May 13 00:59:36 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/cf.data.pre new-STABLE13/src/cf.data.pre
--- squid-2.6.STABLE13/src/cf.data.pre	Wed Apr 25 06:30:03 2007
+++ new-STABLE13/src/cf.data.pre	Sun May 13 00:59:36 2007
@@ -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
diff -r -u squid-2.6.STABLE13/src/cf_gen.c new-STABLE13/src/cf_gen.c
--- squid-2.6.STABLE13/src/cf_gen.c	Tue May 23 03:55:23 2006
+++ new-STABLE13/src/cf_gen.c	Sun May 13 00:59:36 2007
@@ -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");
diff -r -u squid-2.6.STABLE13/src/client_db.c new-STABLE13/src/client_db.c
--- squid-2.6.STABLE13/src/client_db.c	Mon Oct 24 00:20:54 2005
+++ new-STABLE13/src/client_db.c	Sun May 13 00:59:36 2007
@@ -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:
diff -r -u squid-2.6.STABLE13/src/client_side.c new-STABLE13/src/client_side.c
--- squid-2.6.STABLE13/src/client_side.c	Wed Mar 21 06:26:34 2007
+++ new-STABLE13/src/client_side.c	Sun May 13 00:59:36 2007
@@ -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;
     }
diff -r -u squid-2.6.STABLE13/src/comm.c new-STABLE13/src/comm.c
--- squid-2.6.STABLE13/src/comm.c	Tue Apr 17 18:39:56 2007
+++ new-STABLE13/src/comm.c	Sun May 13 00:59:36 2007
@@ -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 <matusita@ics.es.osaka-u.ac.jp> */
-	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;
     }
diff -r -u squid-2.6.STABLE13/src/comm_generic.c new-STABLE13/src/comm_generic.c
--- squid-2.6.STABLE13/src/comm_generic.c	Wed Nov  1 03:25:15 2006
+++ new-STABLE13/src/comm_generic.c	Sun May 13 00:59:36 2007
@@ -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
diff -r -u squid-2.6.STABLE13/src/defines.h new-STABLE13/src/defines.h
--- squid-2.6.STABLE13/src/defines.h	Sun Feb  4 07:58:20 2007
+++ new-STABLE13/src/defines.h	Sun May 13 00:59:36 2007
@@ -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 */
diff -r -u squid-2.6.STABLE13/src/delay_pools.c new-STABLE13/src/delay_pools.c
--- squid-2.6.STABLE13/src/delay_pools.c	Mon Oct 23 20:22:21 2006
+++ new-STABLE13/src/delay_pools.c	Sun May 13 00:59:36 2007
@@ -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) {
diff -r -u squid-2.6.STABLE13/src/dns_internal.c new-STABLE13/src/dns_internal.c
--- squid-2.6.STABLE13/src/dns_internal.c	Sun Dec 17 19:51:44 2006
+++ new-STABLE13/src/dns_internal.c	Sun May 13 00:59:36 2007
@@ -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();
diff -r -u squid-2.6.STABLE13/src/errorpage.c new-STABLE13/src/errorpage.c
--- squid-2.6.STABLE13/src/errorpage.c	Fri Jan 19 09:21:01 2007
+++ new-STABLE13/src/errorpage.c	Sun May 13 00:59:36 2007
@@ -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) {
diff -r -u squid-2.6.STABLE13/src/external_acl.c new-STABLE13/src/external_acl.c
--- squid-2.6.STABLE13/src/external_acl.c	Tue Jan  2 08:32:13 2007
+++ new-STABLE13/src/external_acl.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/forward.c new-STABLE13/src/forward.c
--- squid-2.6.STABLE13/src/forward.c	Tue Apr 17 18:35:17 2007
+++ new-STABLE13/src/forward.c	Sun May 13 00:59:37 2007
@@ -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;
diff -r -u squid-2.6.STABLE13/src/fqdncache.c new-STABLE13/src/fqdncache.c
--- squid-2.6.STABLE13/src/fqdncache.c	Tue May 30 09:56:11 2006
+++ new-STABLE13/src/fqdncache.c	Sun May 13 00:59:37 2007
@@ -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;
 }
 
diff -r -u squid-2.6.STABLE13/src/ftp.c new-STABLE13/src/ftp.c
--- squid-2.6.STABLE13/src/ftp.c	Tue Mar 27 08:41:43 2007
+++ new-STABLE13/src/ftp.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/globals.h new-STABLE13/src/globals.h
--- squid-2.6.STABLE13/src/globals.h	Fri Jan 19 09:19:26 2007
+++ new-STABLE13/src/globals.h	Sun May 13 00:59:37 2007
@@ -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;
diff -r -u squid-2.6.STABLE13/src/htcp.c new-STABLE13/src/htcp.c
--- squid-2.6.STABLE13/src/htcp.c	Sat Nov  4 23:14:07 2006
+++ new-STABLE13/src/htcp.c	Sun May 13 00:59:37 2007
@@ -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
@@ -1243,5 +1312,10 @@
 	debug(12, 1) ("FD %d Closing HTCP socket\n", htcpOutSocket);
 	comm_close(htcpOutSocket);
 	htcpOutSocket = -1;
+    }
+    if (htcpOutSocket6 > -1) {
+	debug(12, 1) ("FD %d Closing HTCP socket v6\n", htcpOutSocket6);
+	comm_close(htcpOutSocket6);
+	htcpOutSocket6 = -1;
     }
 }
diff -r -u squid-2.6.STABLE13/src/http.c new-STABLE13/src/http.c
--- squid-2.6.STABLE13/src/http.c	Tue Mar 27 08:08:00 2007
+++ new-STABLE13/src/http.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/icp_v2.c new-STABLE13/src/icp_v2.c
--- squid-2.6.STABLE13/src/icp_v2.c	Mon Jun 26 00:53:14 2006
+++ new-STABLE13/src/icp_v2.c	Sun May 13 00:59:37 2007
@@ -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
@@ -502,6 +571,11 @@
 	debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection);
 	comm_close(theOutIcpConnection);
 	theOutIcpConnection = -1;
+    }
+    if (theOutIcpConnection6 > -1) {
+	debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection6);
+	comm_close(theOutIcpConnection6);
+	theOutIcpConnection6 = -1;
     }
 }
 
diff -r -u squid-2.6.STABLE13/src/icp_v3.c new-STABLE13/src/icp_v3.c
--- squid-2.6.STABLE13/src/icp_v3.c	Wed May 18 01:56:38 2005
+++ new-STABLE13/src/icp_v3.c	Sun May 13 00:59:37 2007
@@ -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)
diff -r -u squid-2.6.STABLE13/src/ident.c new-STABLE13/src/ident.c
--- squid-2.6.STABLE13/src/ident.c	Sat May 13 07:08:37 2006
+++ new-STABLE13/src/ident.c	Sun May 13 00:59:37 2007
@@ -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);
 }
diff -r -u squid-2.6.STABLE13/src/internal.c new-STABLE13/src/internal.c
--- squid-2.6.STABLE13/src/internal.c	Fri Aug 25 21:26:07 2006
+++ new-STABLE13/src/internal.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/ipc.c new-STABLE13/src/ipc.c
--- squid-2.6.STABLE13/src/ipc.c	Sat Sep  9 04:41:24 2006
+++ new-STABLE13/src/ipc.c	Sun May 13 00:59:37 2007
@@ -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) {
diff -r -u squid-2.6.STABLE13/src/ipcache.c new-STABLE13/src/ipcache.c
--- squid-2.6.STABLE13/src/ipcache.c	Wed Aug 16 09:27:20 2006
+++ new-STABLE13/src/ipcache.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/main.c new-STABLE13/src/main.c
--- squid-2.6.STABLE13/src/main.c	Tue Mar 13 07:25:40 2007
+++ new-STABLE13/src/main.c	Sun May 13 00:59:37 2007
@@ -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();
diff -r -u squid-2.6.STABLE13/src/multicast.c new-STABLE13/src/multicast.c
--- squid-2.6.STABLE13/src/multicast.c	Fri Jan 12 09:37:19 2001
+++ new-STABLE13/src/multicast.c	Sun May 13 00:59:37 2007
@@ -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
 }
diff -r -u squid-2.6.STABLE13/src/neighbors.c new-STABLE13/src/neighbors.c
--- squid-2.6.STABLE13/src/neighbors.c	Tue Feb 27 07:45:24 2007
+++ new-STABLE13/src/neighbors.c	Sun May 13 00:59:37 2007
@@ -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;
diff -r -u squid-2.6.STABLE13/src/net_db.c new-STABLE13/src/net_db.c
--- squid-2.6.STABLE13/src/net_db.c	Tue Jun  6 07:47:01 2006
+++ new-STABLE13/src/net_db.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/pconn.c new-STABLE13/src/pconn.c
--- squid-2.6.STABLE13/src/pconn.c	Tue May 23 06:54:56 2006
+++ new-STABLE13/src/pconn.c	Sun May 13 00:59:37 2007
@@ -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);
 }
 
diff -r -u squid-2.6.STABLE13/src/peer_select.c new-STABLE13/src/peer_select.c
--- squid-2.6.STABLE13/src/peer_select.c	Sun Dec 10 14:24:52 2006
+++ new-STABLE13/src/peer_select.c	Sun May 13 00:59:37 2007
@@ -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;
     }
diff -r -u squid-2.6.STABLE13/src/peer_sourcehash.c new-STABLE13/src/peer_sourcehash.c
--- squid-2.6.STABLE13/src/peer_sourcehash.c	Tue May 16 13:52:26 2006
+++ new-STABLE13/src/peer_sourcehash.c	Sun May 13 00:59:37 2007
@@ -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);
diff -r -u squid-2.6.STABLE13/src/protos.h new-STABLE13/src/protos.h
--- squid-2.6.STABLE13/src/protos.h	Tue Mar 27 08:14:09 2007
+++ new-STABLE13/src/protos.h	Sun May 13 00:59:37 2007
@@ -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);
 
@@ -1198,6 +1198,8 @@
 void setUmask(mode_t mask);
 int xusleep(unsigned int usec);
 void keepCapabilities(void);
+
+extern char *sockaddr_ntoa(struct sockaddr *);
 
 #if USE_HTCP
 extern void htcpInit(void);
diff -r -u squid-2.6.STABLE13/src/redirect.c new-STABLE13/src/redirect.c
--- squid-2.6.STABLE13/src/redirect.c	Sun Jul  9 01:01:12 2006
+++ new-STABLE13/src/redirect.c	Sun May 13 00:59:37 2007
@@ -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,
diff -r -u squid-2.6.STABLE13/src/send-announce.c new-STABLE13/src/send-announce.c
--- squid-2.6.STABLE13/src/send-announce.c	Thu May 25 12:36:56 2006
+++ new-STABLE13/src/send-announce.c	Sun May 13 00:59:37 2007
@@ -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),
diff -r -u squid-2.6.STABLE13/src/snmp_agent.c new-STABLE13/src/snmp_agent.c
--- squid-2.6.STABLE13/src/snmp_agent.c	Fri Nov 10 01:35:07 2006
+++ new-STABLE13/src/snmp_agent.c	Sun May 13 00:59:37 2007
@@ -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:
diff -r -u squid-2.6.STABLE13/src/snmp_core.c new-STABLE13/src/snmp_core.c
--- squid-2.6.STABLE13/src/snmp_core.c	Wed Nov 29 08:16:48 2006
+++ new-STABLE13/src/snmp_core.c	Sun May 13 00:59:37 2007
@@ -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++;
diff -r -u squid-2.6.STABLE13/src/ssl.c new-STABLE13/src/ssl.c
--- squid-2.6.STABLE13/src/ssl.c	Sun Feb  4 06:53:38 2007
+++ new-STABLE13/src/ssl.c	Sun May 13 00:59:37 2007
@@ -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);
 }
diff -r -u squid-2.6.STABLE13/src/stat.c new-STABLE13/src/stat.c
--- squid-2.6.STABLE13/src/stat.c	Thu Nov  2 05:58:52 2006
+++ new-STABLE13/src/stat.c	Sun May 13 00:59:37 2007
@@ -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",
diff -r -u squid-2.6.STABLE13/src/structs.h new-STABLE13/src/structs.h
--- squid-2.6.STABLE13/src/structs.h	Fri Apr 27 08:11:51 2007
+++ new-STABLE13/src/structs.h	Sun May 13 00:59:37 2007
@@ -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
 };
 
diff -r -u squid-2.6.STABLE13/src/tools.c new-STABLE13/src/tools.c
--- squid-2.6.STABLE13/src/tools.c	Sun Nov  5 02:09:45 2006
+++ new-STABLE13/src/tools.c	Sun May 13 00:59:37 2007
@@ -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 */
@@ -1345,4 +1345,16 @@
 	}
     }
 #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;
 }
diff -r -u squid-2.6.STABLE13/src/typedefs.h new-STABLE13/src/typedefs.h
--- squid-2.6.STABLE13/src/typedefs.h	Sat Sep  2 23:08:42 2006
+++ new-STABLE13/src/typedefs.h	Sun May 13 00:59:37 2007
@@ -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;
diff -r -u squid-2.6.STABLE13/src/url.c new-STABLE13/src/url.c
--- squid-2.6.STABLE13/src/url.c	Sun Mar  4 03:34:13 2007
+++ new-STABLE13/src/url.c	Sun May 13 00:59:37 2007
@@ -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));
 	    /*
diff -r -u squid-2.6.STABLE13/src/wccp.c new-STABLE13/src/wccp.c
--- squid-2.6.STABLE13/src/wccp.c	Tue Jun 27 00:01:59 2006
+++ new-STABLE13/src/wccp.c	Sun May 13 00:59:37 2007
@@ -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;
diff -r -u squid-2.6.STABLE13/src/wccp2.c new-STABLE13/src/wccp2.c
--- squid-2.6.STABLE13/src/wccp2.c	Tue Apr 17 18:40:59 2007
+++ new-STABLE13/src/wccp2.c	Sun May 13 00:59:37 2007
@@ -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)
