Bläddra i källkod

r15703@catbus: nickm | 2007-10-11 17:30:34 -0400
Fix for the reported case of bug 438: check families as well as identities in circuit_find_to_cannibalize(). Code audit still pending. ;)


svn:r11886

Nick Mathewson 16 år sedan
förälder
incheckning
3100712c34
3 ändrade filer med 50 tillägg och 4 borttagningar
  1. 6 1
      src/or/circuitlist.c
  2. 1 0
      src/or/or.h
  3. 43 3
      src/or/routerlist.c

+ 6 - 1
src/or/circuitlist.c

@@ -801,7 +801,6 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
 {
   circuit_t *_circ;
   origin_circuit_t *best=NULL;
-//  or_options_t *options = get_options();
 
   log_debug(LD_CIRC,
             "Hunting for a circ to cannibalize: purpose %d, uptime %d, "
@@ -829,10 +828,16 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
         if (info) {
           /* need to make sure we don't duplicate hops */
           crypt_path_t *hop = circ->cpath;
+          routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
           do {
+            routerinfo_t *ri2;
             if (!memcmp(hop->extend_info->identity_digest,
                         info->identity_digest, DIGEST_LEN))
               goto next;
+            if (ri1 &&
+                (ri2 = router_get_by_digest(hop->extend_info->identity_digest))
+                && routers_in_same_family(ri1, ri2))
+              goto next;
             hop=hop->next;
           } while (hop!=circ->cpath);
         }

+ 1 - 0
src/or/or.h

@@ -3546,6 +3546,7 @@ routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
                                              int retry_if_no_servers);
 void router_reset_status_download_failures(void);
 void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
+int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2);
 void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
                                     int must_be_running);
 int router_nickname_is_in_list(routerinfo_t *router, const char *list);

+ 43 - 3
src/or/routerlist.c

@@ -1009,6 +1009,13 @@ router_reset_status_download_failures(void)
   mark_all_trusteddirservers_up();
 }
 
+/** Return true iff router1 and router2 have the same /16 network. */
+static INLINE int
+routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2)
+{
+  return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000);
+}
+
 /** Look through the routerlist and identify routers that
  * advertise the same /16 network address as <b>router</b>.
  * Add each of them to <b>sl</b>.
@@ -1018,8 +1025,7 @@ routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router)
 {
   SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
   {
-    if (router != r &&
-        (router->addr & 0xffff0000) == (r->addr & 0xffff0000))
+    if (router != r && routers_in_same_network_family(router, r))
       smartlist_add(sl, r);
   });
 }
@@ -1056,13 +1062,47 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
   }
 
   /* If the user declared any families locally, honor those too. */
-  for (cl = get_options()->NodeFamilies; cl; cl = cl->next) {
+  for (cl = options->NodeFamilies; cl; cl = cl->next) {
     if (router_nickname_is_in_list(router, cl->value)) {
       add_nickname_list_to_smartlist(sl, cl->value, 0);
     }
   }
 }
 
+/** Return true iff r is named by some nickname in <b>lst</b>. */
+static INLINE int
+router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r)
+{
+  if (!lst) return 0;
+  SMARTLIST_FOREACH(lst, const char *, name,
+    if (router_nickname_matches(r, name))
+      return 1;);
+  return 0;
+}
+
+/** Return true iff r1 and r2 are in the same family, but not the same
+ * router. */
+int
+routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2)
+{
+  or_options_t *options = get_options();
+  config_line_t *cl;
+
+  if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2))
+    return 1;
+
+  if (router_in_nickname_smartlist(r1->declared_family, r2) &&
+      router_in_nickname_smartlist(r2->declared_family, r1))
+    return 1;
+
+  for (cl = options->NodeFamilies; cl; cl = cl->next) {
+    if (router_nickname_is_in_list(r1, cl->value) &&
+        router_nickname_is_in_list(r2, cl->value))
+      return 1;
+  }
+  return 0;
+}
+
 /** Given a (possibly NULL) comma-and-whitespace separated list of nicknames,
  * see which nicknames in <b>list</b> name routers in our routerlist, and add
  * the routerinfos for those routers to <b>sl</b>.  If <b>must_be_running</b>,