Browse Source

Switch to a StrictNodes config option.

This is step one of handling ExcludedNodes better. This first
step is just to make EntryNodes and ExitNodes do what they did
before.
Roger Dingledine 14 years ago
parent
commit
580066f2f6
5 changed files with 51 additions and 66 deletions
  1. 15 19
      src/or/circuitbuild.c
  2. 21 7
      src/or/config.c
  3. 9 12
      src/or/or.h
  4. 1 1
      src/or/rendservice.c
  5. 5 27
      src/or/routerlist.c

+ 15 - 19
src/or/circuitbuild.c

@@ -2174,7 +2174,8 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
 
     routersets_get_disjunction(use, supporting, options->ExitNodes,
                                options->_ExcludeExitNodesUnion, 1);
-    if (smartlist_len(use) == 0 && !options->StrictExitNodes) {
+    if (smartlist_len(use) == 0 && options->ExitNodes &&
+        !options->StrictNodes) { /* give up on exitnodes and try again */
       routersets_get_disjunction(use, supporting, NULL,
                                  options->_ExcludeExitNodesUnion, 1);
     }
@@ -2220,12 +2221,14 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
 
       routersets_get_disjunction(use, supporting, options->ExitNodes,
                                  options->_ExcludeExitNodesUnion, 1);
-      if (smartlist_len(use) == 0 && !options->StrictExitNodes) {
+      if (smartlist_len(use) == 0 && options->ExitNodes &&
+          !options->StrictNodes) { /* give up on exitnodes and try again */
         routersets_get_disjunction(use, supporting, NULL,
                                    options->_ExcludeExitNodesUnion, 1);
       }
-      /* XXX sometimes the above results in null, when the requested
-       * exit node is down. we should pick it anyway. */
+      /* FFF sometimes the above results in null, when the requested
+       * exit node is considered down by the consensus. we should pick
+       * it anyway, since the user asked for it. */
       router = routerlist_sl_choose_by_bandwidth(use, WEIGHT_FOR_EXIT);
       if (router)
         break;
@@ -2243,10 +2246,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
     log_info(LD_CIRC, "Chose exit server '%s'", router->nickname);
     return router;
   }
-  if (options->StrictExitNodes) {
+  if (options->ExitNodes && options->StrictNodes) {
     log_warn(LD_CIRC,
              "No specified exit routers seem to be running, and "
-             "StrictExitNodes is set: can't choose an exit.");
+             "StrictNodes is set: can't choose an exit.");
   }
   return NULL;
 }
@@ -2277,15 +2280,13 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
       if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE)
         flags |= CRN_ALLOW_INVALID;
       if (is_internal) /* pick it like a middle hop */
-        return router_choose_random_node(NULL, NULL,
-                                         options->ExcludeNodes, flags);
+        return router_choose_random_node(NULL, options->ExcludeNodes, flags);
       else
         return choose_good_exit_server_general(dir,need_uptime,need_capacity);
     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
       if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS)
         flags |= CRN_ALLOW_INVALID;
-      return router_choose_random_node(NULL, NULL,
-                                       options->ExcludeNodes, flags);
+      return router_choose_random_node(NULL, options->ExcludeNodes, flags);
   }
   log_warn(LD_BUG,"Unhandled purpose %d", purpose);
   tor_fragile_assert();
@@ -2527,8 +2528,7 @@ choose_good_middle_server(uint8_t purpose,
     flags |= CRN_NEED_CAPACITY;
   if (options->_AllowInvalid & ALLOW_INVALID_MIDDLE)
     flags |= CRN_ALLOW_INVALID;
-  choice = router_choose_random_node(NULL,
-                                     excluded, options->ExcludeNodes, flags);
+  choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
   smartlist_free(excluded);
   return choice;
 }
@@ -2593,11 +2593,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
   if (options->_AllowInvalid & ALLOW_INVALID_ENTRY)
     flags |= CRN_ALLOW_INVALID;
 
-  choice = router_choose_random_node(
-           NULL,
-           excluded,
-           options->ExcludeNodes,
-           flags);
+  choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
   smartlist_free(excluded);
   return choice;
 }
@@ -3378,7 +3374,7 @@ entry_guards_prepend_from_config(void)
     add_an_entry_guard(ri, 0);
   });
   /* Finally, the remaining EntryNodes, unless we're strict */
-  if (options->StrictEntryNodes) {
+  if (options->EntryNodes && options->StrictNodes) {
     SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
                       entry_guard_free(e));
   } else {
@@ -3397,7 +3393,7 @@ entry_guards_prepend_from_config(void)
 int
 entry_list_can_grow(or_options_t *options)
 {
-  if (options->StrictEntryNodes)
+  if (options->EntryNodes && options->StrictNodes)
     return 0;
   if (options->UseBridges)
     return 0;

+ 21 - 7
src/or/config.c

@@ -66,6 +66,7 @@ static config_abbrev_t _option_abbrevs[] = {
   PLURAL(RendExcludeNode),
   PLURAL(StrictEntryNode),
   PLURAL(StrictExitNode),
+  PLURAL(StrictNode),
   { "l", "Log", 1, 0},
   { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
   { "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0},
@@ -83,10 +84,12 @@ static config_abbrev_t _option_abbrevs[] = {
   { "NumEntryNodes", "NumEntryGuards", 0, 0},
   { "ResolvConf", "ServerDNSResolvConfFile", 0, 1},
   { "SearchDomains", "ServerDNSSearchDomains", 0, 1},
-  { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0 },
+  { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0},
   { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0},
   { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0},
   { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0},
+  { "StrictEntryNodes", "StrictNodes", 0, 1},
+  { "StrictExitNodes", "StrictNodes", 0, 1},
   { NULL, NULL, 0, 0},
 };
 
@@ -320,8 +323,7 @@ static config_var_t _option_vars[] = {
   V(SocksPort,                   UINT,     "9050"),
   V(SocksTimeout,                INTERVAL, "2 minutes"),
   OBSOLETE("StatusFetchPeriod"),
-  V(StrictEntryNodes,            BOOL,     "0"),
-  V(StrictExitNodes,             BOOL,     "0"),
+  V(StrictNodes,                 BOOL,     "0"),
   OBSOLETE("SysLog"),
   V(TestSocks,                   BOOL,     "0"),
   OBSOLETE("TestVia"),
@@ -517,6 +519,9 @@ static config_var_description_t options_description[] = {
   { "ExitNodes", "A list of preferred nodes to use for the last hop in "
     "circuits, when possible." },
   { "ExcludeNodes", "A list of nodes never to use when building a circuit." },
+  { "ExcludeExitNodes", "A list of nodes never to use for the last when "
+    "building a circuit for exit. Other circuits can still end at these "
+    "nodes." },
   { "FascistFirewall", "If set, Tor will only create outgoing connections to "
     "servers running on the ports listed in FirewallPorts." },
   { "FirewallPorts", "A list of ports that we can connect to.  Only used "
@@ -545,10 +550,9 @@ static config_var_description_t options_description[] = {
   { "SOCKSPolicy", "Set an entry policy to limit which addresses can connect "
     "to the SOCKSPort." },
   /* SocksTimeout */
-  { "StrictExitNodes", "If set, Tor will fail to operate when none of the "
-    "configured ExitNodes can be used." },
-  { "StrictEntryNodes", "If set, Tor will fail to operate when none of the "
-    "configured EntryNodes can be used." },
+  { "StrictNodes", "If set, Tor will fail to operate when none of the "
+    "configured EntryNodes, ExitNodes, ExcludeNodes, or ExcludeExitNodes "
+    "can be used." },
   /* TestSocks */
   { "TrackHostsExit", "Hosts and domains which should, if possible, be "
     "accessed from the same exit node each time we connect to them." },
@@ -3194,6 +3198,15 @@ options_validate(or_options_t *old_options, or_options_t *options,
     routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
   }
 
+  if (options->ExcludeNodes && options->StrictNodes) {
+    COMPLAIN("You have asked to exclude certain relays from all positions "
+             "in your circuits. Expect hidden services and other Tor "
+             "features to be broken in unpredictable ways.");
+  }
+
+#if 0 /* for now, it's ok to set StrictNodes without setting any actual
+       * preferences. It won't hurt anything. Eventually, either figure
+       * out the logic for the right case to complain, or just delete. -RD */
   if (options->StrictExitNodes &&
       (!options->ExitNodes) &&
       (!old_options ||
@@ -3207,6 +3220,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
        (old_options->StrictEntryNodes != options->StrictEntryNodes) ||
        (!routerset_equal(old_options->EntryNodes,options->EntryNodes))))
     COMPLAIN("StrictEntryNodes set, but no EntryNodes listed.");
+#endif
 
   if (options->EntryNodes && !routerset_is_list(options->EntryNodes)) {
     /* XXXX fix this; see entry_guards_prepend_from_config(). */

+ 9 - 12
src/or/or.h

@@ -2326,16 +2326,13 @@ typedef struct {
   routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
                            * country codes and IP address patterns of ORs to
                            * consider as entry points. */
-  int StrictExitNodes; /**< Boolean: When none of our ExitNodes are up, do we
-                        * stop building circuits? */
-  int StrictEntryNodes; /**< Boolean: When none of our EntryNodes are up, do we
-                         * stop building circuits? */
-  int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
-                               * process for all current and future memory. */
-
+  int StrictNodes; /**< Boolean: When none of our EntryNodes or ExitNodes
+                    * are up, or we need to access a node in ExcludeNodes,
+                    * do we just fail instead? */
   routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests,
                              * country codes and IP address patterns of ORs
-                             * not to use in circuits. */
+                             * not to use in circuits. But see StrictNodes
+                             * above. */
   routerset_t *ExcludeExitNodes;/**< Structure containing nicknames, digests,
                                  * country codes and IP address patterns of
                                  * ORs not to consider as exits. */
@@ -2343,6 +2340,9 @@ typedef struct {
   /** Union of ExcludeNodes and ExcludeExitNodes */
   struct routerset_t *_ExcludeExitNodesUnion;
 
+  int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
+                               * process for all current and future memory. */
+
   /** List of "entry", "middle", "exit", "introduction", "rendezvous". */
   smartlist_t *AllowInvalidNodes;
   /** Bitmask; derived from AllowInvalidNodes. */
@@ -4949,13 +4949,10 @@ typedef enum {
   CRN_NEED_GUARD = 1<<2,
   CRN_ALLOW_INVALID = 1<<3,
   /* XXXX not used, apparently. */
-  CRN_STRICT_PREFERRED = 1<<4,
-  /* XXXX not used, apparently. */
   CRN_WEIGHT_AS_EXIT = 1<<5
 } router_crn_flags_t;
 
-routerinfo_t *router_choose_random_node(const char *preferred,
-                                        smartlist_t *excludedsmartlist,
+routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
                                         struct routerset_t *excludedset,
                                         router_crn_flags_t flags);
 

+ 1 - 1
src/or/rendservice.c

@@ -1825,7 +1825,7 @@ rend_services_introduce(void)
       router_crn_flags_t flags = CRN_NEED_UPTIME;
       if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
         flags |= CRN_ALLOW_INVALID;
-      router = router_choose_random_node(NULL, intro_routers,
+      router = router_choose_random_node(intro_routers,
                                          options->ExcludeNodes, flags);
       if (!router) {
         log_warn(LD_REND,

+ 5 - 27
src/or/routerlist.c

@@ -1827,8 +1827,7 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl)
  * node (that is, possibly discounting exit nodes).
  */
 routerinfo_t *
-router_choose_random_node(const char *preferred,
-                          smartlist_t *excludedsmartlist,
+router_choose_random_node(smartlist_t *excludedsmartlist,
                           routerset_t *excludedset,
                           router_crn_flags_t flags)
 {
@@ -1836,7 +1835,6 @@ router_choose_random_node(const char *preferred,
   const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
   const int need_guard = (flags & CRN_NEED_GUARD) != 0;
   const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
-  const int strict = (flags & CRN_STRICT_PREFERRED) != 0;
   const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
 
   smartlist_t *sl, *excludednodes;
@@ -1864,22 +1862,7 @@ router_choose_random_node(const char *preferred,
     routerlist_add_family(excludednodes, r);
   }
 
-  /* Try the preferred nodes first. Ignore need_uptime and need_capacity
-   * and need_guard, since the user explicitly asked for these nodes. */
-  if (preferred) {
-    sl = smartlist_create();
-    add_nickname_list_to_smartlist(sl,preferred,1);
-    smartlist_subtract(sl,excludednodes);
-    if (excludedsmartlist)
-      smartlist_subtract(sl,excludedsmartlist);
-    if (excludedset)
-      routerset_subtract_routers(sl,excludedset);
-    choice = smartlist_choose(sl);
-    smartlist_free(sl);
-  }
-  if (!choice && !strict) {
-    /* Then give up on our preferred choices: any node
-     * will do that has the required attributes. */
+  { /* XXX021 reformat */
     sl = smartlist_create();
     router_add_running_routers_to_smartlist(sl, allow_invalid,
                                             need_uptime, need_capacity,
@@ -1906,18 +1889,13 @@ router_choose_random_node(const char *preferred,
                need_guard?", guard":"");
       flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD);
       choice = router_choose_random_node(
-                       NULL, excludedsmartlist, excludedset, flags);
+                       excludedsmartlist, excludedset, flags);
     }
   }
   smartlist_free(excludednodes);
   if (!choice) {
-    if (strict) {
-      log_warn(LD_CIRC, "All preferred nodes were down when trying to choose "
-               "node, and the Strict[...]Nodes option is set. Failing.");
-    } else {
-      log_warn(LD_CIRC,
-               "No available nodes when trying to choose node. Failing.");
-    }
+    log_warn(LD_CIRC,
+             "No available nodes when trying to choose node. Failing.");
   }
   return choice;
 }