[tor-commits] [tor/master] Use the appropriate call to getsockopt for IPv6 sockets

nickm at torproject.org nickm at torproject.org
Tue Dec 23 15:59:58 UTC 2014


commit 39e71d8fa54afd906fdcaf2cd496c300362ebb9a
Author: Francisco Blas Izquierdo Riera (klondike) <klondike at gentoo.org>
Date:   Tue Dec 23 10:51:33 2014 -0500

    Use the appropriate call to getsockopt for IPv6 sockets
    
    The original call to getsockopt to know the original address on transparently
    proxyed sockets using REDIRECT in iptables failed with IPv6 addresses because
    it assumed all sockets used IPv4.
    
    This patch fixes this by using the appropriate options and adding the headers
    containing the needed definitions for these.
    
    This patch is released under the same license as the original file as
    long as the author iscredited.
    
    Signed-off-by: Francisco Blas Izquierdo Riera (klondike) <klondike at gentoo.org>
---
 configure.ac             |   35 +++++++++++++++++++++++++++++++++++
 src/or/connection_edge.c |   33 +++++++++++++++++++++++++++++++--
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index e7560b2..88b4da0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -937,6 +937,14 @@ AC_CHECK_HEADERS(net/pfvar.h, net_pfvar_found=1, net_pfvar_found=0,
 #ifdef HAVE_NET_IF_H
 #include <net/if.h>
 #endif])
+
+AC_CHECK_HEADERS(linux/if.h,[],[],
+[
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+])
+
 AC_CHECK_HEADERS(linux/netfilter_ipv4.h,
         linux_netfilter_ipv4=1, linux_netfilter_ipv4=0,
 [#ifdef HAVE_SYS_TYPES_H
@@ -958,6 +966,30 @@ AC_CHECK_HEADERS(linux/netfilter_ipv4.h,
 #include <netinet/in.h>
 #endif])
 
+AC_CHECK_HEADERS(linux/netfilter_ipv6/ip6_tables.h,
+        linux_netfilter_ipv6_ip6_tables=1, linux_netfilter_ipv6_ip6_tables=0,
+[#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_LINUX_IF_H
+#include <linux/if.h>
+#endif])
+
 if test x$transparent = xtrue ; then
    transparent_ok=0
    if test x$net_if_found = x1 && test x$net_pfvar_found = x1 ; then
@@ -966,6 +998,9 @@ if test x$transparent = xtrue ; then
    if test x$linux_netfilter_ipv4 = x1 ; then
      transparent_ok=1
    fi
+   if test x$linux_netfilter_ipv6_ip6_tables = x1 ; then
+     transparent_ok=1
+   fi
    if test x$transparent_ok = x1 ; then
      AC_DEFINE(USE_TRANSPARENT, 1, "Define to enable transparent proxy support")
      case $host in
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index a90ca00..09645d0 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -46,8 +46,20 @@
 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
 #include <linux/netfilter_ipv4.h>
 #define TRANS_NETFILTER
+#define TRANS_NETFILTER_IPV4
 #endif
 
+#ifdef HAVE_LINUX_IF_H
+#include <linux/if.h>
+#endif
+
+#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#define TRANS_NETFILTER
+#define TRANS_NETFILTER_IPV6
+#endif
+
+
 #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
 #include <net/if.h>
 #include <net/pfvar.h>
@@ -1401,10 +1413,27 @@ destination_from_socket(entry_connection_t *conn, socks_request_t *req)
   struct sockaddr_storage orig_dst;
   socklen_t orig_dst_len = sizeof(orig_dst);
   tor_addr_t addr;
+  int rv;
 
 #ifdef TRANS_NETFILTER
-  if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
-                 (struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
+  switch (ENTRY_TO_CONN(conn)->socket_family) {
+#ifdef TRANS_NETFILTER_IPV4
+    case AF_INET:
+      rv = getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
+                  (struct sockaddr*)&orig_dst, &orig_dst_len);
+      break;
+#endif
+#ifdef TRANS_NETFILTER_IPV6
+    case AF_INET6:
+      rv = getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IPV6, IP6T_SO_ORIGINAL_DST,
+                  (struct sockaddr*)&orig_dst, &orig_dst_len);
+      break;
+#endif
+    default:
+      log_warn(LD_BUG, "Received transparent data from an unsuported socket family.");
+      return -1;
+  }
+  if (rv < 0) {
     int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
     log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
     return -1;





More information about the tor-commits mailing list