=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2013-06-18 06:22:13 +0000
+++ src/cache_cf.cc	2013-06-19 14:18:38 +0000
@@ -3625,14 +3625,6 @@
         /* Log information regarding the port modes under interception. */
         debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
         debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)");
-
-        /* INET6: until transparent REDIRECT works on IPv6 SOCKET, force wildcard to IPv4 */
-        if (Ip::EnableIpv6)
-            debugs(3, DBG_IMPORTANT, "Disabling IPv6 on port " << s->s << " (interception enabled)");
-        if ( !s->s.setIPv4() ) {
-            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: IPv6 addresses cannot NAT intercept (protocol does not provide NAT)" << s->s );
-            self_destruct();
-        }
     } else if (strcmp(token, "tproxy") == 0) {
         if (s->flags.natIntercept || s->flags.accelSurrogate) {
             debugs(3,DBG_CRITICAL, "FATAL: http(s)_port: TPROXY option requires its own interception port. It cannot be shared with other modes.");

=== modified file 'src/ip/Intercept.cc'
--- src/ip/Intercept.cc	2013-06-03 14:05:16 +0000
+++ src/ip/Intercept.cc	2013-06-19 14:20:49 +0000
@@ -96,7 +96,9 @@
 /* must be before including netfilter_ipv4.h */
 #include <limits.h>
 #endif
+#include <linux/if.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #endif /* LINUX_NETFILTER required headers */
 
 // single global instance for access by other components.
@@ -124,22 +126,46 @@
 Ip::Intercept::NetfilterInterception(const Comm::ConnectionPointer &newConn, int silent)
 {
 #if LINUX_NETFILTER
-    struct sockaddr_in lookup;
-    socklen_t len = sizeof(struct sockaddr_in);
-    newConn->local.getSockAddr(lookup);
+    void* lookupptr;
+    socklen_t len = 0;
+
+    if (newConn->local.isIPv6()) {
+        len = sizeof(struct sockaddr_in6);
+        lookupptr = alloca(len);
+
+        newConn->local.getSockAddr(*((struct sockaddr_in6*)lookupptr));
+    } else {
+        len = sizeof(struct sockaddr_in);
+        lookupptr = alloca(len);
+
+        newConn->local.getSockAddr(*((struct sockaddr_in*)lookupptr));
+    }
 
     /** \par
      * Try NAT lookup for REDIRECT or DNAT targets. */
-    if ( getsockopt(newConn->fd, IPPROTO_IP, SO_ORIGINAL_DST, &lookup, &len) != 0) {
+    if ( getsockopt(newConn->fd,
+                newConn->local.isIPv6() ? IPPROTO_IPV6 : IPPROTO_IP,
+                newConn->local.isIPv6() ? IP6T_SO_ORIGINAL_DST : SO_ORIGINAL_DST,
+                lookupptr,
+                &len) != 0) {
         if (!silent) {
-            debugs(89, DBG_IMPORTANT, HERE << " NF getsockopt(SO_ORIGINAL_DST) failed on " << newConn << ": " << xstrerror());
+            if (newConn->local.isIPv6())
+                debugs(89, DBG_IMPORTANT, HERE << " NF getsockopt(IP6T_SO_ORIGINAL_DST) failed on " << newConn << ": " << xstrerror());
+            else
+                debugs(89, DBG_IMPORTANT, HERE << " NF getsockopt(SO_ORIGINAL_DST) failed on " << newConn << ": " << xstrerror());
             lastReported_ = squid_curtime;
         }
         debugs(89, 9, HERE << "address: " << newConn);
+
         return false;
     } else {
-        newConn->local = lookup;
+        if (newConn->local.isIPv6()) {
+            newConn->local = *((struct sockaddr_in6*)lookupptr);
+        } else {
+            newConn->local = *((struct sockaddr_in*)lookupptr);
+        }
         debugs(89, 5, HERE << "address NAT: " << newConn);
+
         return true;
     }
 #endif
@@ -359,10 +385,6 @@
         if (TproxyTransparent(newConn, silent)) return true;
     }
 
-    /* NAT is only available in IPv4 */
-    if ( !newConn->local.isIPv4()  ) return false;
-    if ( !newConn->remote.isIPv4() ) return false;
-
     if (interceptActive_ && listenConn->flags&COMM_INTERCEPTION) {
         /* NAT methods that use sock-opts to return client address */
         if (NetfilterInterception(newConn, silent)) return true;

