=== 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 #endif +#include #include +#include #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;