]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
When no usable exit satisfies a predicted port, stop predicting it.
authorNick Mathewson <nickm@torproject.org>
Fri, 11 May 2012 16:52:21 +0000 (12:52 -0400)
committerNick Mathewson <nickm@torproject.org>
Fri, 11 May 2012 16:52:21 +0000 (12:52 -0400)
Fix for bug 3296.

changes/bug3296 [new file with mode: 0644]
src/or/circuitbuild.c
src/or/rephist.c
src/or/rephist.h

diff --git a/changes/bug3296 b/changes/bug3296
new file mode 100644 (file)
index 0000000..31c9eac
--- /dev/null
@@ -0,0 +1,5 @@
+  o Major bugfixes:
+    - If we are unable to find any exit that supports our predicted
+      ports, stop calling them predicted, so that we don't loop and
+      build hopeless circuits indefinitely. Fix for bug 3296; bugfix
+      on 0.0.9pre6, which introduced predicted ports.
index 5481838ccb499ea3f105dd297ef0f84b576ab203..3b82ed7455dc2f73c0ec3f52cf0776465e123a28 100644 (file)
@@ -2847,6 +2847,10 @@ choose_good_exit_server_general(int need_uptime, int need_capacity)
       if (node)
         break;
       smartlist_clear(supporting);
+      /* If we reach this point, we can't actually support any unhandled
+       * predicted ports, so clear all the remaining ones. */
+      if (smartlist_len(needed_ports))
+        rep_hist_remove_predicted_ports(needed_ports);
     }
     SMARTLIST_FOREACH(needed_ports, uint16_t *, cp, tor_free(cp));
     smartlist_free(needed_ports);
index 0cd60eeb83662d4a13f3aa2bb8b74829bbc7ed17..c3f059839ccfd33294674c3b831d2eb07aeddb69 100644 (file)
@@ -1868,6 +1868,26 @@ rep_hist_get_predicted_ports(time_t now)
   return out;
 }
 
+/**
+ * Take a list of uint16_t *, and remove every port in the list from the
+ * current list of predicted ports.
+ */
+void
+rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports)
+{
+  /* Let's do this on O(N), not O(N^2). */
+  bitarray_t *remove_ports = bitarray_init_zero(UINT16_MAX);
+  SMARTLIST_FOREACH(rmv_ports, const uint16_t *, p,
+                    bitarray_set(remove_ports, *p));
+  SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+    if (bitarray_is_set(remove_ports, pp->port)) {
+      tor_free(pp);
+      SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
+    }
+  } SMARTLIST_FOREACH_END(pp);
+  bitarray_free(remove_ports);
+}
+
 /** The user asked us to do a resolve. Rather than keeping track of
  * timings and such of resolves, we fake it for now by treating
  * it the same way as a connection to port 80. This way we will continue
index 0a3e46ae1a58deb7b24711a454f5e9efab523b30..800b957d5ad19efc0abf0a75d75dbda2f9491b59 100644 (file)
@@ -49,6 +49,7 @@ const char *rep_hist_get_router_stability_doc(time_t now);
 
 void rep_hist_note_used_port(time_t now, uint16_t port);
 smartlist_t *rep_hist_get_predicted_ports(time_t now);
+void rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports);
 void rep_hist_note_used_resolve(time_t now);
 void rep_hist_note_used_internal(time_t now, int need_uptime,
                                  int need_capacity);