ソースを参照

Initial support for simplest use of prop186 or-address lines

This lets a routerinfo_t have a single IPv6 or-address, and adds
support for formatting and parsing those lines.
Nick Mathewson 13 年 前
コミット
11d5a9f63d
4 ファイル変更64 行追加0 行削除
  1. 7 0
      src/or/or.h
  2. 16 0
      src/or/router.c
  3. 38 0
      src/or/routerparse.c
  4. 3 0
      src/test/test_dir.c

+ 7 - 0
src/or/or.h

@@ -1722,6 +1722,13 @@ typedef struct {
   uint16_t or_port; /**< Port for TLS connections. */
   uint16_t dir_port; /**< Port for HTTP directory connections. */
 
+  /* DOCDOC */
+  /* XXXXX187 Actually these should probably be part of a list of addresses,
+   * not just a special case.  Use abstractions to access these; don't do it
+   * directly. */
+  tor_addr_t ipv6_addr;
+  uint16_t ipv6_orport;
+
   crypto_pk_env_t *onion_pkey; /**< Public RSA key for onions. */
   crypto_pk_env_t *identity_pkey;  /**< Public RSA key for signing. */
 

+ 16 - 0
src/or/router.c

@@ -1903,6 +1903,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
   int result=0;
   addr_policy_t *tmpe;
   char *family_line;
+  char *extra_or_address = NULL;
   const or_options_t *options = get_options();
 
   /* Make sure the identity key matches the one in the routerinfo. */
@@ -1955,9 +1956,22 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
                   router->cache_info.extra_info_digest, DIGEST_LEN);
   }
 
+  if (router->ipv6_orport &&
+      tor_addr_family(&router->ipv6_addr) == AF_INET6) {
+    char addr[TOR_ADDR_BUF_LEN];
+    const char *a;
+    a = tor_addr_to_str(addr, &router->ipv6_addr, sizeof(addr), 1);
+    if (a) {
+      tor_asprintf(&extra_or_address,
+                   "or-address %s:%d\n", a, router->ipv6_orport);
+      log_notice(LD_OR, "My line is <%s>", extra_or_address);
+    }
+  }
+
   /* Generate the easy portion of the router descriptor. */
   result = tor_snprintf(s, maxlen,
                     "router %s %s %d 0 %d\n"
+                    "%s"
                     "platform %s\n"
                     "opt protocols Link 1 2 Circuit 1\n"
                     "published %s\n"
@@ -1972,6 +1986,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
     router->address,
     router->or_port,
     decide_to_advertise_dirport(options, router->dir_port),
+    extra_or_address ? extra_or_address : "",
     router->platform,
     published,
     fingerprint,
@@ -1992,6 +2007,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
   tor_free(family_line);
   tor_free(onion_pkey);
   tor_free(identity_pkey);
+  tor_free(extra_or_address);
 
   if (result < 0) {
     log_warn(LD_BUG,"descriptor snprintf #1 ran out of room!");

+ 38 - 0
src/or/routerparse.c

@@ -64,6 +64,7 @@ typedef enum {
   K_DIR_OPTIONS,
   K_CLIENT_VERSIONS,
   K_SERVER_VERSIONS,
+  K_OR_ADDRESS,
   K_P,
   K_R,
   K_S,
@@ -286,6 +287,7 @@ static token_rule_t routerdesc_token_table[] = {
 
   T01("family",              K_FAMILY,              ARGS,    NO_OBJ ),
   T01("caches-extra-info",   K_CACHES_EXTRA_INFO,   NO_ARGS, NO_OBJ ),
+  T0N("or-address",          K_OR_ADDRESS,          GE(1),   NO_OBJ ),
 
   T0N("opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK ),
   T1( "bandwidth",           K_BANDWIDTH,           GE(3),   NO_OBJ ),
@@ -541,6 +543,7 @@ static int router_get_hashes_impl(const char *s, size_t s_len,
                                   const char *start_str, const char *end_str,
                                   char end_char);
 static void token_clear(directory_token_t *tok);
+static smartlist_t *find_all_by_keyword(smartlist_t *s, directory_keyword k);
 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
 static directory_token_t *_find_by_keyword(smartlist_t *s,
                                            directory_keyword keyword,
@@ -1506,6 +1509,27 @@ router_parse_entry_from_string(const char *s, const char *end,
              "older Tors.");
     goto err;
   }
+  {
+    smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
+    if (or_addresses) {
+      SMARTLIST_FOREACH_BEGIN(or_addresses, directory_token_t *, t) {
+        tor_addr_t a;
+        maskbits_t bits;
+        uint16_t port_min, port_max;
+        /* XXXX Prop186 the full spec allows much more than this. */
+        if (tor_addr_parse_mask_ports(t->args[0], &a, &bits, &port_min,
+                                      &port_max) == AF_INET6 &&
+            bits == 128 &&
+            port_min == port_max) {
+          /* Okay, this is one we can understand. */
+          tor_addr_copy(&router->ipv6_addr, &a);
+          router->ipv6_orport = port_min;
+          break;
+        }
+      } SMARTLIST_FOREACH_END(t);
+      smartlist_free(or_addresses);
+    }
+  }
   exit_policy_tokens = find_all_exitpolicy(tokens);
   if (!smartlist_len(exit_policy_tokens)) {
     log_warn(LD_DIR, "No exit policy tokens in descriptor.");
@@ -4134,6 +4158,20 @@ _find_by_keyword(smartlist_t *s, directory_keyword keyword,
   return tok;
 }
 
+/** DOCDOC */
+static smartlist_t *
+find_all_by_keyword(smartlist_t *s, directory_keyword k)
+{
+  smartlist_t *out = NULL;
+  SMARTLIST_FOREACH(s, directory_token_t *, t,
+                    if (t->tp == k) {
+                      if (!out)
+                        out = smartlist_create();
+                      smartlist_add(out, t);
+                    });
+  return out;
+}
+
 /** Return a newly allocated smartlist of all accept or reject tokens in
  * <b>s</b>.
  */

+ 3 - 0
src/test/test_dir.c

@@ -96,6 +96,8 @@ test_dir_formats(void)
   r1->cache_info.published_on = 0;
   r1->or_port = 9000;
   r1->dir_port = 9003;
+  tor_addr_parse(&r1->ipv6_addr, "1:2:3:4::");
+  r1->ipv6_orport = 9999;
   r1->onion_pkey = crypto_pk_dup_key(pk1);
   r1->identity_pkey = crypto_pk_dup_key(pk2);
   r1->bandwidthrate = 1000;
@@ -141,6 +143,7 @@ test_dir_formats(void)
   test_assert(router_dump_router_to_string(buf, 2048, r1, pk2)>0);
 
   strlcpy(buf2, "router Magri 18.244.0.1 9000 0 9003\n"
+          "or-address [1:2:3:4::]:9999\n"
           "platform Tor "VERSION" on ", sizeof(buf2));
   strlcat(buf2, get_uname(), sizeof(buf2));
   strlcat(buf2, "\n"