Parcourir la source

Simplest version of server-side IPv6 support (no dns)

This is a relatively simple set of changes: we mostly need to
remove a few "but not for IPv6" changes.  We also needed to tweak
the handling of DNS code to generate RESOLVED cells that could get
an IPv6 answer in return.
Nick Mathewson il y a 11 ans
Parent
commit
c3faa0ebd5
3 fichiers modifiés avec 36 ajouts et 9 suppressions
  1. 3 0
      src/or/connection_edge.c
  2. 31 7
      src/or/dns.c
  3. 2 2
      src/or/router.c

+ 3 - 0
src/or/connection_edge.c

@@ -2408,6 +2408,9 @@ connection_exit_connect(edge_connection_t *edge_conn)
   addr = &conn->addr;
   port = conn->port;
 
+  if (tor_addr_family(addr) == AF_INET6)
+    conn->socket_family = AF_INET6;
+
   log_debug(LD_EXIT,"about to try connecting");
   switch (connection_connect(conn, conn->address, addr, port, &socket_error)) {
     case -1: {

+ 31 - 7
src/or/dns.c

@@ -160,7 +160,8 @@ typedef struct cached_resolve_t {
 
 static void purge_expired_resolves(time_t now);
 static void dns_found_answer(const char *address, uint8_t is_reverse,
-                             uint32_t addr, const char *hostname, char outcome,
+                             uint32_t addr,
+                             const char *hostname, char outcome,
                              uint32_t ttl);
 static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type);
 static int launch_resolve(edge_connection_t *exitconn);
@@ -490,9 +491,13 @@ purge_expired_resolves(time_t now)
   assert_cache_ok();
 }
 
+/* argument for send_resolved_cell only, meaning "let the answer type be ipv4
+ * or ipv6 depending on the connection's address". */
+#define RESOLVED_TYPE_AUTO 0xff
+
 /** Send a response to the RESOLVE request of a connection.
  * <b>answer_type</b> must be one of
- * RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT).
+ * RESOLVED_TYPE_(IPV4|IPV6|ERROR|ERROR_TRANSIENT|AUTO).
  *
  * If <b>circ</b> is provided, and we have a cached answer, send the
  * answer back along circ; otherwise, send the answer back along
@@ -505,6 +510,16 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
   size_t buflen;
   uint32_t ttl;
 
+  if (answer_type == RESOLVED_TYPE_AUTO) {
+    sa_family_t family = tor_addr_family(&conn->base_.addr);
+    if (family == AF_INET)
+      answer_type = RESOLVED_TYPE_IPV4;
+    else if (family == AF_INET6)
+      answer_type = RESOLVED_TYPE_IPV6;
+    else
+      answer_type = RESOLVED_TYPE_ERROR_TRANSIENT;
+  }
+
   buf[0] = answer_type;
   ttl = dns_clip_ttl(conn->address_ttl);
 
@@ -516,7 +531,15 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
       set_uint32(buf+6, htonl(ttl));
       buflen = 10;
       break;
-    /*XXXX IP6 need ipv6 implementation */
+    case RESOLVED_TYPE_IPV6:
+      {
+        const uint8_t *bytes = tor_addr_to_in6_addr8(&conn->base_.addr);
+        buf[1] = 16;
+        memcpy(buf+2, bytes, 16);
+        set_uint32(buf+18, htonl(ttl));
+        buflen = 22;
+      }
+      break;
     case RESOLVED_TYPE_ERROR_TRANSIENT:
     case RESOLVED_TYPE_ERROR:
       {
@@ -614,7 +637,7 @@ dns_resolve(edge_connection_t *exitconn)
         if (hostname)
           send_resolved_hostname_cell(exitconn, hostname);
         else
-          send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
+          send_resolved_cell(exitconn, RESOLVED_TYPE_AUTO);
         exitconn->on_circuit = NULL;
       } else {
         /* Add to the n_streams list; the calling function will send back a
@@ -693,12 +716,13 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
   /* first check if exitconn->base_.address is an IP. If so, we already
    * know the answer. */
   if (tor_addr_parse(&addr, exitconn->base_.address) >= 0) {
-    if (tor_addr_family(&addr) == AF_INET) {
+    if (tor_addr_family(&addr) == AF_INET ||
+        tor_addr_family(&addr) == AF_INET6) {
       tor_addr_copy(&exitconn->base_.addr, &addr);
       exitconn->address_ttl = DEFAULT_DNS_TTL;
       return 1;
     } else {
-      /* XXXX IPv6 */
+      /* XXXX unspec? Bogus? */
       return -1;
     }
   }
@@ -1140,7 +1164,7 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr,
         if (is_reverse)
           send_resolved_hostname_cell(pendconn, hostname);
         else
-          send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
+          send_resolved_cell(pendconn, RESOLVED_TYPE_AUTO);
         circ = circuit_get_by_edge_conn(pendconn);
         tor_assert(circ);
         circuit_detach_stream(circ, pendconn);

+ 2 - 2
src/or/router.c

@@ -1380,8 +1380,8 @@ router_compare_to_my_exit_policy(edge_connection_t *conn)
   if (tor_addr_is_null(&conn->base_.addr))
     return -1;
 
-  /* XXXX IPv6 */
-  if (tor_addr_family(&conn->base_.addr) != AF_INET)
+  if (tor_addr_family(&conn->base_.addr) != AF_INET &&
+      tor_addr_family(&conn->base_.addr) != AF_INET6)
     return -1;
 
   return compare_tor_addr_to_addr_policy(&conn->base_.addr, conn->base_.port,