diff --git a/briar-android/assets/tor b/briar-android/assets/tor
index 626014ad46505195e5e68e0be1b5d310939f9b12..2199e062e4eec1a8383ce537869de12802900956 100644
Binary files a/briar-android/assets/tor and b/briar-android/assets/tor differ
diff --git a/briar-android/libs/jtorctl-briar.jar b/briar-android/libs/jtorctl-briar.jar
index f5753c6337180ddae63602370594f05745b3af22..70d7a68546d34302fb077b4669ee28ecc5f0beab 100644
Binary files a/briar-android/libs/jtorctl-briar.jar and b/briar-android/libs/jtorctl-briar.jar differ
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
index cdf700b85a235983573eb8e0d8e9d41314c4c8f6..905040b5c696f2c20e15f758a084092655785788 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
+++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
@@ -525,6 +525,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 		}
 		try {
 			if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + onion);
+			controlConnection.forgetHiddenService(onion.substring(0, 16));
 			Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT);
 			proxy.resolveAddrLocally(false);
 			Socket s = new SocksSocket(proxy, onion, 80);
@@ -546,7 +547,6 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 	}
 
 	public void circuitStatus(String status, String id, String path) {
-		if(LOG.isLoggable(INFO)) LOG.info("Circuit " + id + " " + status);
 		if(status.equals("BUILT") && !circuitBuilt.getAndSet(true)) {
 			LOG.info("First circuit built");
 			if(isRunning()) callback.pollNow();
@@ -571,9 +571,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 		}
 	}
 
-	public void unrecognized(String type, String msg) {
-		if(LOG.isLoggable(INFO)) LOG.info(type + " " + msg);
-	}
+	public void unrecognized(String type, String msg) {}
 
 	private static class WriteObserver extends FileObserver {
 
diff --git a/jtorctl.patch b/jtorctl.patch
index 80fee4767a7498bad56cd2d11b95c85189f09774..891f48495a86e1c710f4728818987228288699b0 100644
--- a/jtorctl.patch
+++ b/jtorctl.patch
@@ -1,7 +1,7 @@
 diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java
 --- jtorctl/net/freehaven/tor/control/TorControlConnection.java	2014-10-03 12:21:51.883098440 +0100
-+++ jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java	2014-10-03 12:17:07.429687913 +0100
-@@ -728,5 +728,12 @@
++++ jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java	2014-10-06 16:28:53.516851714 +0100
+@@ -728,5 +728,19 @@
          sendAndWaitForResponse("CLOSECIRCUIT "+circID+
                                 (ifUnused?" IFUNUSED":"")+"\r\n", null);
      }
@@ -11,6 +11,13 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b
 +     */
 +    public void takeOwnership() throws IOException {
 +        sendAndWaitForResponse("TAKEOWNERSHIP\r\n", null);
++    }
++
++    /** Tells Tor to forget any cached client state relating to the hidden
++     * service with the given hostname (excluding the .onion extension).
++     */
++    public void forgetHiddenService(String hostname) throws IOException {
++        sendAndWaitForResponse("FORGETHS " + hostname + "\r\n", null);
 +    }
  }
  
diff --git a/tor.patch b/tor.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f4e278c563600b8434da7824b27a12fc5337682c
--- /dev/null
+++ b/tor.patch
@@ -0,0 +1,194 @@
+diff --git a/src/or/config.c b/src/or/config.c
+index 919dd27..c2d3caf 100644
+--- a/src/or/config.c
++++ b/src/or/config.c
+@@ -1039,6 +1039,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)
+                  "non-control network connections. Shutting down all existing "
+                  "connections.");
+       connection_mark_all_noncontrol_connections();
++      /* We can't complete circuits until the network is re-enabled. */
++      can_complete_circuit = 0;
+     }
+   }
+ 
+diff --git a/src/or/control.c b/src/or/control.c
+index ae9dd69..0ead4c1 100644
+--- a/src/or/control.c
++++ b/src/or/control.c
+@@ -36,6 +36,8 @@
+ #include "nodelist.h"
+ #include "policies.h"
+ #include "reasons.h"
++#include "rendclient.h"
++#include "rendcommon.h"
+ #include "rephist.h"
+ #include "router.h"
+ #include "routerlist.h"
+@@ -197,6 +199,8 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len,
+ static int handle_control_usefeature(control_connection_t *conn,
+                                      uint32_t len,
+                                      const char *body);
++static int handle_control_forgeths(control_connection_t *conn, uint32_t len,
++                                   const char *body);
+ static int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
+                                       size_t len);
+ static void orconn_target_get_name(char *buf, size_t len,
+@@ -3181,6 +3185,33 @@ handle_control_usefeature(control_connection_t *conn,
+   return 0;
+ }
+ 
++/** Called when we get a FORGETHS command: parse the hidden service's onion
++ * address and purge any cached state related to the service. */
++static int
++handle_control_forgeths(control_connection_t *conn, uint32_t len,
++                        const char *body)
++{
++  smartlist_t *args;
++  char *onion_address;
++
++  args = getargs_helper("FORGETHS", conn, body, 1, 1);
++  if (!args)
++    return -1;
++  onion_address = smartlist_get(args, 0);
++  smartlist_free(args);
++
++  if (!rend_valid_service_id(onion_address)) {
++    connection_write_str_to_buf("513 Invalid hidden service address\r\n", conn);
++    tor_free(onion_address);
++    return -1;
++  }
++
++  rend_client_purge_hidden_service(onion_address);
++  tor_free(onion_address);
++  send_control_done(conn);
++  return 0;
++}
++
+ /** Called when <b>conn</b> has no more bytes left on its outbuf. */
+ int
+ connection_control_finished_flushing(control_connection_t *conn)
+@@ -3480,6 +3511,9 @@ connection_control_process_inbuf(control_connection_t *conn)
+   } else if (!strcasecmp(conn->incoming_cmd, "AUTHCHALLENGE")) {
+     if (handle_control_authchallenge(conn, cmd_data_len, args))
+       return -1;
++  } else if (!strcasecmp(conn->incoming_cmd, "FORGETHS")) {
++    if (handle_control_forgeths(conn, cmd_data_len, args))
++      return -1;
+   } else {
+     connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
+                              conn->incoming_cmd);
+diff --git a/src/or/rendclient.c b/src/or/rendclient.c
+index 7abbfd6..e550b65 100644
+--- a/src/or/rendclient.c
++++ b/src/or/rendclient.c
+@@ -29,6 +29,8 @@
+ static extend_info_t *rend_client_get_random_intro_impl(
+                           const rend_cache_entry_t *rend_query,
+                           const int strict, const int warnings);
++static void purge_hid_serv_from_last_hid_serv_requests(
++                          const char *onion_address);
+ 
+ /** Purge all potentially remotely-detectable state held in the hidden
+  * service client code.  Called on SIGNAL NEWNYM. */
+@@ -40,6 +42,16 @@ rend_client_purge_state(void)
+   rend_client_purge_last_hid_serv_requests();
+ }
+ 
++/** Purge all cached state relating to the given hidden service. */
++void
++rend_client_purge_hidden_service(const char *onion_address)
++{
++  tor_assert(rend_valid_service_id(onion_address));
++
++  rend_cache_remove_entry(onion_address);
++  purge_hid_serv_from_last_hid_serv_requests(onion_address);
++}
++
+ /** Called when we've established a circuit to an introduction point:
+  * send the introduction request. */
+ void
+diff --git a/src/or/rendclient.h b/src/or/rendclient.h
+index 1f731d0..7084aef 100644
+--- a/src/or/rendclient.h
++++ b/src/or/rendclient.h
+@@ -13,6 +13,7 @@
+ #define TOR_RENDCLIENT_H
+ 
+ void rend_client_purge_state(void);
++void rend_client_purge_hidden_service(const char *onion_address);
+ 
+ void rend_client_introcirc_has_opened(origin_circuit_t *circ);
+ void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
+diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
+index d1b4941..3deb5fc 100644
+--- a/src/or/rendcommon.c
++++ b/src/or/rendcommon.c
+@@ -954,6 +954,34 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
+   return 1;
+ }
+ 
++/** Remove any cached descriptors for <b>service_id/b>. */
++void
++rend_cache_remove_entry(const char *service_id)
++{
++  char key[REND_SERVICE_ID_LEN_BASE32+2]; /* <version><service_id>\0 */
++  rend_cache_entry_t *removed;
++
++  tor_assert(rend_valid_service_id(service_id));
++  if (!rend_cache)
++    return;
++
++  tor_snprintf(key, sizeof(key), "2%s", service_id);
++  removed = (rend_cache_entry_t *)strmap_remove_lc(rend_cache, key);
++  if (removed) {
++    log_info(LD_REND, "Removed cached v2 descriptor for service %s.",
++               safe_str_client(service_id));
++    rend_cache_entry_free(removed);
++  }
++
++  tor_snprintf(key, sizeof(key), "0%s", service_id);
++  removed = (rend_cache_entry_t *)strmap_remove_lc(rend_cache, key);
++  if (removed) {
++    log_info(LD_REND, "Removed cached v0 descriptor for service %s.",
++               safe_str_client(service_id));
++    rend_cache_entry_free(removed);
++  }
++}
++
+ /** <b>query</b> is a base32'ed service id. If it's malformed, return -1.
+  * Else look it up.
+  *   - If it is found, point *desc to it, and write its length into
+diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
+index f476593..331784f 100644
+--- a/src/or/rendcommon.h
++++ b/src/or/rendcommon.h
+@@ -43,6 +43,7 @@ int rend_cache_lookup_desc(const char *query, int version, const char **desc,
+                            size_t *desc_len);
+ int rend_cache_lookup_entry(const char *query, int version,
+                             rend_cache_entry_t **entry_out);
++void rend_cache_remove_entry(const char *service_id);
+ int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);
+ int rend_cache_store(const char *desc, size_t desc_len, int published,
+                      const char *service_id);
+diff --git a/src/or/rendservice.c b/src/or/rendservice.c
+index 8a4a11e..35f5e18 100644
+--- a/src/or/rendservice.c
++++ b/src/or/rendservice.c
+@@ -15,6 +15,7 @@
+ #include "circuituse.h"
+ #include "config.h"
+ #include "directory.h"
++#include "main.h"
+ #include "networkstatus.h"
+ #include "nodelist.h"
+ #include "rendclient.h"
+@@ -3024,6 +3025,9 @@ rend_services_introduce(void)
+   time_t now;
+   const or_options_t *options = get_options();
+ 
++  if (!can_complete_circuit) 
++    return;
++
+   intro_nodes = smartlist_new();
+   now = time(NULL);
+