Browse Source

Implement strict{entry|exit}nodes config options

svn:r2236
Nick Mathewson 20 years ago
parent
commit
416653271a
5 changed files with 42 additions and 12 deletions
  1. 8 0
      doc/tor.1.in
  2. 9 6
      src/or/circuitbuild.c
  3. 11 0
      src/or/config.c
  4. 6 1
      src/or/or.h
  5. 8 5
      src/or/routerlist.c

+ 8 - 0
doc/tor.1.in

@@ -72,6 +72,14 @@ A list of preferred nodes to use for the last hop in the circuit, if possible.
 \fBexcludenodes \fR\fInickname,nickname,...\fP
 A list of nodes to never use when building a circuit.
 .TP
+\fBstrictexitnodes \fR\fI0|1\fP
+If 1, Tor will never use any nodes besides those listed in "exitnodes" for
+the last hop of a circuit.
+.TP
+\fBstrictentrynodes \fR\fI0|1\fP
+If 1, Tor will never use any nodes besides those listed in "entrynodes" for
+the first hop of a circuit.
+.TP
 \fBnewcircuitperiod \fR\fINUM\fP
 Every NUM seconds consider whether to build a new circuit. (Default: 60)
 .TP

+ 9 - 6
src/or/circuitbuild.c

@@ -897,7 +897,7 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
         smartlist_add(sl, smartlist_get(dir->routers, i));
 
     smartlist_subtract(sl,excludedexits);
-    if (smartlist_overlap(sl,preferredexits))
+    if (options.StrictExitNodes || smartlist_overlap(sl,preferredexits))
       smartlist_intersect(sl,preferredexits);
     router = smartlist_choose(sl);
   } else {
@@ -911,7 +911,7 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
         smartlist_add(sl, smartlist_get(dir->routers, i));
 
     smartlist_subtract(sl,excludedexits);
-    if (smartlist_overlap(sl,preferredexits))
+    if (options.StrictExitNodes || smartlist_overlap(sl,preferredexits))
       smartlist_intersect(sl,preferredexits);
     router = smartlist_choose(sl);
   }
@@ -924,7 +924,9 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
     log_fn(LOG_INFO, "Chose exit server '%s'", router->nickname);
     return router;
   }
-  log_fn(LOG_WARN, "No exit routers seem to be running; can't choose an exit.");
+  if (options.StrictExitNodes)
+    log_fn(LOG_WARN, "No exit routers seem to be running; can't choose an exit.");
+  
   return NULL;
 }
 
@@ -946,7 +948,7 @@ static routerinfo_t *choose_good_exit_server(uint8_t purpose, routerlist_t *dir)
     case CIRCUIT_PURPOSE_C_GENERAL:
       return choose_good_exit_server_general(dir);
     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
-      r = router_choose_random_node(options.RendNodes, options.RendExcludeNodes, NULL, 0, 1);
+      r = router_choose_random_node(options.RendNodes, options.RendExcludeNodes, NULL, 0, 1, 0);
       return r;
     default:
       log_fn(LOG_WARN,"unhandled purpose %d", purpose);
@@ -1101,7 +1103,7 @@ static routerinfo_t *choose_good_middle_server(cpath_build_state_t *state,
     tor_assert(r);
     smartlist_add(excluded, r);
   }
-  choice = router_choose_random_node("", options.ExcludeNodes, excluded, 0, 1);
+  choice = router_choose_random_node("", options.ExcludeNodes, excluded, 0, 1, 0);
   smartlist_free(excluded);
   return choice;
 }
@@ -1131,7 +1133,8 @@ static routerinfo_t *choose_good_entry_server(cpath_build_state_t *state)
     }
   }
   choice = router_choose_random_node(options.EntryNodes,
-                                     options.ExcludeNodes, excluded, 0, 1);
+                                     options.ExcludeNodes, excluded, 0, 1,
+                                     options.StrictEntryNodes);
   smartlist_free(excluded);
   return choice;
 }

+ 11 - 0
src/or/config.c

@@ -204,6 +204,8 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
 
     config_compare(list, "ExitNodes",      CONFIG_TYPE_STRING, &options->ExitNodes) ||
     config_compare(list, "EntryNodes",     CONFIG_TYPE_STRING, &options->EntryNodes) ||
+    config_compare(list, "StrictExitNodes", CONFIG_TYPE_BOOL, &options->StrictExitNodes) ||
+    config_compare(list, "StrictEntryNodes", CONFIG_TYPE_BOOL, &options->StrictEntryNodes) ||
     config_compare(list, "ExitPolicy",     CONFIG_TYPE_LINELIST, &options->ExitPolicy) ||
     config_compare(list, "ExcludeNodes",   CONFIG_TYPE_STRING, &options->ExcludeNodes) ||
 
@@ -529,6 +531,7 @@ static void init_options(or_options_t *options) {
   options->LogOptions = NULL;
   options->ExitNodes = tor_strdup("");
   options->EntryNodes = tor_strdup("");
+  options->StrictEntryNodes = options->StrictExitNodes = 0;
   options->ExcludeNodes = tor_strdup("");
   options->RendNodes = tor_strdup("");
   options->RendExcludeNodes = tor_strdup("");
@@ -713,6 +716,14 @@ int getconfig(int argc, char **argv, or_options_t *options) {
     result = -1;
   }
 
+  if(options->StrictExitNodes && !strlen(options->ExitNodes)) {
+    log(LOG_WARN,"StrictExitNodes set, but no ExitNodes listed.");
+  }
+
+  if(options->StrictEntryNodes && !strlen(options->EntryNodes)) {
+    log(LOG_WARN,"StrictEntryNodes set, but no EntryNodes listed.");
+  }
+
   if(options->AuthoritativeDir && options->RecommendedVersions == NULL) {
     log(LOG_WARN,"Directory servers must configure RecommendedVersions.");
     result = -1;

+ 6 - 1
src/or/or.h

@@ -824,6 +824,10 @@ typedef struct {
                     * as exits. */
   char *EntryNodes; /**< Comma-separated list of nicknames 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? */
   char *ExcludeNodes; /**< Comma-separated list of nicknames of ORs not to
                        * use in circuits. */
 
@@ -1381,7 +1385,8 @@ void router_add_running_routers_to_smartlist(struct smartlist_t *sl);
 int router_nickname_matches(routerinfo_t *router, const char *nickname);
 routerinfo_t *router_choose_random_node(char *preferred, char *excluded,
                                         struct smartlist_t *excludedsmartlist,
-                                        int preferuptime, int preferbandwidth);
+                                        int preferuptime, int preferbandwidth,
+                                        int strict);
 routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
 routerinfo_t *router_get_by_nickname(const char *nickname);
 routerinfo_t *router_get_by_hexdigest(const char *hexdigest);

+ 8 - 5
src/or/routerlist.c

@@ -275,13 +275,16 @@ routerlist_sl_choose_by_bandwidth(smartlist_t *sl)
 }
 
 /** Return a random running router from the routerlist.  If any node
- * named in <b>preferred</b> is available, pick one of those.  Never pick a
- * node named in <b>excluded</b>, or whose routerinfo is in
- * <b>excludedsmartlist</b>, even if they are the only nodes available.
+ * named in <b>preferred</b> is available, pick one of those.  Never
+ * pick a node named in <b>excluded</b>, or whose routerinfo is in
+ * <b>excludedsmartlist</b>, even if they are the only nodes
+ * available.  If <b>strict</b> is true, never pick any node besides
+ * those in <b>preferred</b>.
  */
 routerinfo_t *router_choose_random_node(char *preferred, char *excluded,
                                         smartlist_t *excludedsmartlist,
-                                        int preferuptime, int preferbandwidth)
+                                        int preferuptime, int preferbandwidth,
+                                        int strict)
 {
   smartlist_t *sl, *excludednodes;
   routerinfo_t *choice;
@@ -302,7 +305,7 @@ routerinfo_t *router_choose_random_node(char *preferred, char *excluded,
   else
     choice = smartlist_choose(sl);
   smartlist_free(sl);
-  if(!choice) {
+  if(!choice && !strict) {
     sl = smartlist_create();
     router_add_running_routers_to_smartlist(sl);
     smartlist_subtract(sl,excludednodes);