Browse Source

Add a new ipv6=address:orport flag to DirAuthority and FallbackDir

Resolves # 6027
Nick Mathewson 12 years ago
parent
commit
85003f4c80
7 changed files with 70 additions and 7 deletions
  1. 4 0
      changes/bug6027
  2. 6 3
      doc/tor.1.txt
  3. 31 1
      src/or/config.c
  4. 2 0
      src/or/or.h
  5. 1 0
      src/or/router.c
  6. 24 3
      src/or/routerlist.c
  7. 2 0
      src/or/routerlist.h

+ 4 - 0
changes/bug6027

@@ -0,0 +1,4 @@
+  o Minor features:
+    - Allow users to configure directory authorities and fallback
+      directory servers with IPv6 addresses and ORPorts.  Resolves
+      ticket 6027.

+ 6 - 3
doc/tor.1.txt

@@ -358,7 +358,7 @@ GENERAL OPTIONS
     DataDirectory. If the option is set to 1, make the DataDirectory readable
     DataDirectory. If the option is set to 1, make the DataDirectory readable
     by the default GID. (Default: 0)
     by the default GID. (Default: 0)
 
 
-[[FallbackDir]] **FallbackDir** __address__:__port__ orport=__port__ id=__fingerprint__ [weight=__num__]::
+[[FallbackDir]] **FallbackDir** __address__:__port__ orport=__port__ id=__fingerprint__ [weight=__num__] [ipv6=__address__:__orport__]::
     When we're unable to connect to any directory cache for directory info
     When we're unable to connect to any directory cache for directory info
     (usually because we don't know about any yet) we try a FallbackDir.
     (usually because we don't know about any yet) we try a FallbackDir.
     By default, the directory authorities are also FallbackDirs.
     By default, the directory authorities are also FallbackDirs.
@@ -374,9 +374,12 @@ GENERAL OPTIONS
     "bridge" flag is set. If a flag "orport=**port**" is given, Tor will use the
     "bridge" flag is set. If a flag "orport=**port**" is given, Tor will use the
     given port when opening encrypted tunnels to the dirserver. If a flag
     given port when opening encrypted tunnels to the dirserver. If a flag
     "weight=**num**" is given, then the directory server is chosen randomly
     "weight=**num**" is given, then the directory server is chosen randomly
-    with probability proportional to that weight (default 1.0). Lastly, if a
+    with probability proportional to that weight (default 1.0). If a
     flag "v3ident=**fp**" is given, the dirserver is a v3 directory authority
     flag "v3ident=**fp**" is given, the dirserver is a v3 directory authority
-    whose v3 long-term signing key has the fingerprint **fp**. +
+    whose v3 long-term signing key has the fingerprint **fp**. Lastly,
+    if an "ipv6=__address__:__orport__" flag is present, then the directory
+    authority is listening for IPv6 connections on the indicated IPv6 address
+    and OR Port. +
  +
  +
     If no **DirAuthority** line is given, Tor will use the default directory
     If no **DirAuthority** line is given, Tor will use the default directory
     authorities. NOTE: this option is intended for setting up a private Tor
     authorities. NOTE: this option is intended for setting up a private Tor

+ 31 - 1
src/or/config.c

@@ -5538,6 +5538,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
   smartlist_t *items = NULL;
   smartlist_t *items = NULL;
   int r;
   int r;
   char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
   char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
+  tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL;
   uint16_t dir_port = 0, or_port = 0;
   uint16_t dir_port = 0, or_port = 0;
   char digest[DIGEST_LEN];
   char digest[DIGEST_LEN];
   char v3_digest[DIGEST_LEN];
   char v3_digest[DIGEST_LEN];
@@ -5594,6 +5595,19 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
       } else {
       } else {
         type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
         type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
       }
       }
+    } else if (!strcasecmpstart(flag, "ipv6=")) {
+      if (ipv6_addrport_ptr) {
+        log_warn(LD_CONFIG, "Redundant ipv6 addr/port on DirAuthority line");
+      } else {
+        if (tor_addr_port_parse(LOG_WARN, flag+strlen("ipv6="),
+                                &ipv6_addrport.addr, &ipv6_addrport.port) < 0
+            || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) {
+          log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on DirAuthority line",
+                   escaped(flag));
+          goto err;
+        }
+        ipv6_addrport_ptr = &ipv6_addrport;
+      }
     } else {
     } else {
       log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirAuthority line",
       log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirAuthority line",
                flag);
                flag);
@@ -5636,6 +5650,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
     log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type,
     log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type,
               address, (int)dir_port, (char*)smartlist_get(items,0));
               address, (int)dir_port, (char*)smartlist_get(items,0));
     if (!(ds = trusted_dir_server_new(nickname, address, dir_port, or_port,
     if (!(ds = trusted_dir_server_new(nickname, address, dir_port, or_port,
+                                      ipv6_addrport_ptr,
                                       digest, v3_digest, type, weight)))
                                       digest, v3_digest, type, weight)))
       goto err;
       goto err;
     dir_server_add(ds);
     dir_server_add(ds);
@@ -5673,6 +5688,7 @@ parse_dir_fallback_line(const char *line,
   int ok;
   int ok;
   char id[DIGEST_LEN];
   char id[DIGEST_LEN];
   char *address=NULL;
   char *address=NULL;
+  tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL;
   double weight=1.0;
   double weight=1.0;
 
 
   memset(id, 0, sizeof(id));
   memset(id, 0, sizeof(id));
@@ -5691,6 +5707,19 @@ parse_dir_fallback_line(const char *line,
     } else if (!strcmpstart(cp, "id=")) {
     } else if (!strcmpstart(cp, "id=")) {
       ok = !base16_decode(id, DIGEST_LEN,
       ok = !base16_decode(id, DIGEST_LEN,
                           cp+strlen("id="), strlen(cp)-strlen("id="));
                           cp+strlen("id="), strlen(cp)-strlen("id="));
+    } else if (!strcasecmpstart(cp, "ipv6=")) {
+      if (ipv6_addrport_ptr) {
+        log_warn(LD_CONFIG, "Redundant ipv6 addr/port on FallbackDir line");
+      } else {
+        if (tor_addr_port_parse(LOG_WARN, cp+strlen("ipv6="),
+                                &ipv6_addrport.addr, &ipv6_addrport.port) < 0
+            || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) {
+          log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on FallbackDir line",
+                   escaped(cp));
+          goto end;
+        }
+        ipv6_addrport_ptr = &ipv6_addrport;
+      }
     } else if (!strcmpstart(cp, "weight=")) {
     } else if (!strcmpstart(cp, "weight=")) {
       int ok;
       int ok;
       const char *wstring = cp + strlen("weight=");
       const char *wstring = cp + strlen("weight=");
@@ -5732,7 +5761,8 @@ parse_dir_fallback_line(const char *line,
 
 
   if (!validate_only) {
   if (!validate_only) {
     dir_server_t *ds;
     dir_server_t *ds;
-    ds = fallback_dir_server_new(&addr, dirport, orport, id, weight);
+    ds = fallback_dir_server_new(&addr, dirport, orport, ipv6_addrport_ptr,
+                                 id, weight);
     if (!ds) {
     if (!ds) {
       log_warn(LD_CONFIG, "Couldn't create FallbackDir %s", escaped(line));
       log_warn(LD_CONFIG, "Couldn't create FallbackDir %s", escaped(line));
       goto end;
       goto end;

+ 2 - 0
src/or/or.h

@@ -5009,9 +5009,11 @@ typedef struct dir_server_t {
   char *description;
   char *description;
   char *nickname;
   char *nickname;
   char *address; /**< Hostname. */
   char *address; /**< Hostname. */
+  tor_addr_t ipv6_addr; /**< IPv6 address if present; AF_UNSPEC if not */
   uint32_t addr; /**< IPv4 address. */
   uint32_t addr; /**< IPv4 address. */
   uint16_t dir_port; /**< Directory port. */
   uint16_t dir_port; /**< Directory port. */
   uint16_t or_port; /**< OR port: Used for tunneling connections. */
   uint16_t or_port; /**< OR port: Used for tunneling connections. */
+  uint16_t ipv6_orport; /**< OR port corresponding to ipv6_addr. */
   double weight; /** Weight used when selecting this node at random */
   double weight; /** Weight used when selecting this node at random */
   char digest[DIGEST_LEN]; /**< Digest of identity key. */
   char digest[DIGEST_LEN]; /**< Digest of identity key. */
   char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only,
   char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only,

+ 1 - 0
src/or/router.c

@@ -1026,6 +1026,7 @@ init_keys(void)
     ds = trusted_dir_server_new(options->Nickname, NULL,
     ds = trusted_dir_server_new(options->Nickname, NULL,
                                 router_get_advertised_dir_port(options, 0),
                                 router_get_advertised_dir_port(options, 0),
                                 router_get_advertised_or_port(options),
                                 router_get_advertised_or_port(options),
+                                NULL,
                                 digest,
                                 digest,
                                 v3_digest,
                                 v3_digest,
                                 type, 0.0);
                                 type, 0.0);

+ 24 - 3
src/or/routerlist.c

@@ -4043,6 +4043,7 @@ dir_server_new(int is_authority,
                const tor_addr_t *addr,
                const tor_addr_t *addr,
                const char *hostname,
                const char *hostname,
                uint16_t dir_port, uint16_t or_port,
                uint16_t dir_port, uint16_t or_port,
+               const tor_addr_port_t *addrport_ipv6,
                const char *digest, const char *v3_auth_digest,
                const char *digest, const char *v3_auth_digest,
                dirinfo_type_t type,
                dirinfo_type_t type,
                double weight)
                double weight)
@@ -4059,7 +4060,7 @@ dir_server_new(int is_authority,
   if (tor_addr_family(addr) == AF_INET)
   if (tor_addr_family(addr) == AF_INET)
     a = tor_addr_to_ipv4h(addr);
     a = tor_addr_to_ipv4h(addr);
   else
   else
-    return NULL; /*XXXX Support IPv6 */
+    return NULL;
 
 
   if (!hostname)
   if (!hostname)
     hostname_ = tor_dup_addr(addr);
     hostname_ = tor_dup_addr(addr);
@@ -4076,6 +4077,18 @@ dir_server_new(int is_authority,
   ent->is_authority = is_authority;
   ent->is_authority = is_authority;
   ent->type = type;
   ent->type = type;
   ent->weight = weight;
   ent->weight = weight;
+  if (addrport_ipv6) {
+    if (tor_addr_family(&addrport_ipv6->addr) != AF_INET6) {
+      log_warn(LD_BUG, "Hey, I got a non-ipv6 addr as addrport_ipv6.");
+      tor_addr_make_unspec(&ent->ipv6_addr);
+    } else {
+      tor_addr_copy(&ent->ipv6_addr, &addrport_ipv6->addr);
+      ent->ipv6_orport = addrport_ipv6->port;
+    }
+  } else {
+    tor_addr_make_unspec(&ent->ipv6_addr);
+  }
+
   memcpy(ent->digest, digest, DIGEST_LEN);
   memcpy(ent->digest, digest, DIGEST_LEN);
   if (v3_auth_digest && (type & V3_DIRINFO))
   if (v3_auth_digest && (type & V3_DIRINFO))
     memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
     memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
@@ -4088,6 +4101,7 @@ dir_server_new(int is_authority,
                  hostname, (int)dir_port);
                  hostname, (int)dir_port);
 
 
   ent->fake_status.addr = ent->addr;
   ent->fake_status.addr = ent->addr;
+  tor_addr_copy(&ent->fake_status.ipv6_addr, &ent->ipv6_addr);
   memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN);
   memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN);
   if (nickname)
   if (nickname)
     strlcpy(ent->fake_status.nickname, nickname,
     strlcpy(ent->fake_status.nickname, nickname,
@@ -4096,6 +4110,7 @@ dir_server_new(int is_authority,
     ent->fake_status.nickname[0] = '\0';
     ent->fake_status.nickname[0] = '\0';
   ent->fake_status.dir_port = ent->dir_port;
   ent->fake_status.dir_port = ent->dir_port;
   ent->fake_status.or_port = ent->or_port;
   ent->fake_status.or_port = ent->or_port;
+  ent->fake_status.ipv6_orport = ent->ipv6_orport;
 
 
   return ent;
   return ent;
 }
 }
@@ -4107,6 +4122,7 @@ dir_server_new(int is_authority,
 dir_server_t *
 dir_server_t *
 trusted_dir_server_new(const char *nickname, const char *address,
 trusted_dir_server_new(const char *nickname, const char *address,
                        uint16_t dir_port, uint16_t or_port,
                        uint16_t dir_port, uint16_t or_port,
+                       const tor_addr_port_t *ipv6_addrport,
                        const char *digest, const char *v3_auth_digest,
                        const char *digest, const char *v3_auth_digest,
                        dirinfo_type_t type, double weight)
                        dirinfo_type_t type, double weight)
 {
 {
@@ -4137,7 +4153,9 @@ trusted_dir_server_new(const char *nickname, const char *address,
   tor_addr_from_ipv4h(&addr, a);
   tor_addr_from_ipv4h(&addr, a);
 
 
   result = dir_server_new(1, nickname, &addr, hostname,
   result = dir_server_new(1, nickname, &addr, hostname,
-                          dir_port, or_port, digest,
+                          dir_port, or_port,
+                          ipv6_addrport,
+                          digest,
                           v3_auth_digest, type, weight);
                           v3_auth_digest, type, weight);
   tor_free(hostname);
   tor_free(hostname);
   return result;
   return result;
@@ -4149,9 +4167,12 @@ trusted_dir_server_new(const char *nickname, const char *address,
 dir_server_t *
 dir_server_t *
 fallback_dir_server_new(const tor_addr_t *addr,
 fallback_dir_server_new(const tor_addr_t *addr,
                         uint16_t dir_port, uint16_t or_port,
                         uint16_t dir_port, uint16_t or_port,
+                        const tor_addr_port_t *addrport_ipv6,
                         const char *id_digest, double weight)
                         const char *id_digest, double weight)
 {
 {
-  return dir_server_new(0, NULL, addr, NULL, dir_port, or_port, id_digest,
+  return dir_server_new(0, NULL, addr, NULL, dir_port, or_port,
+                        addrport_ipv6,
+                        id_digest,
                         NULL, ALL_DIRINFO, weight);
                         NULL, ALL_DIRINFO, weight);
 }
 }
 
 

+ 2 - 0
src/or/routerlist.h

@@ -170,10 +170,12 @@ int router_exit_policy_rejects_all(const routerinfo_t *router);
 
 
 dir_server_t *trusted_dir_server_new(const char *nickname, const char *address,
 dir_server_t *trusted_dir_server_new(const char *nickname, const char *address,
                        uint16_t dir_port, uint16_t or_port,
                        uint16_t dir_port, uint16_t or_port,
+                       const tor_addr_port_t *addrport_ipv6,
                        const char *digest, const char *v3_auth_digest,
                        const char *digest, const char *v3_auth_digest,
                        dirinfo_type_t type, double weight);
                        dirinfo_type_t type, double weight);
 dir_server_t *fallback_dir_server_new(const tor_addr_t *addr,
 dir_server_t *fallback_dir_server_new(const tor_addr_t *addr,
                                       uint16_t dir_port, uint16_t or_port,
                                       uint16_t dir_port, uint16_t or_port,
+                                      const tor_addr_port_t *addrport_ipv6,
                                       const char *id_digest, double weight);
                                       const char *id_digest, double weight);
 void dir_server_add(dir_server_t *ent);
 void dir_server_add(dir_server_t *ent);