瀏覽代碼

Fix infinite recursion when connect() fails in microdesc consensus fetch

The underlying fix is to stop indicating requests "ns" consensuses by
putting NULL in their requested_resource field: we already had a
specialized meaning for requested_resource==NULL, which was (more or
less) "Treat a failure here as a network failure, since it's too early
to possibly be a resource or directory failure."  Overloading the two
meant that very early microdesc consensus download failures would get
treated as ns consensus download failures, so the failure count there
would get incremented, but the microdesc download would get retried
immediately in an infinite loop.

Fix for bug2381.  Diagnosed by mobmix.
Nick Mathewson 14 年之前
父節點
當前提交
22ec4d5426
共有 2 個文件被更改,包括 12 次插入8 次删除
  1. 11 7
      src/or/directory.c
  2. 1 1
      src/or/networkstatus.c

+ 11 - 7
src/or/directory.c

@@ -631,9 +631,8 @@ connection_dir_request_failed(dir_connection_t *conn)
       connection_dir_bridge_routerdesc_failed(conn);
     connection_dir_download_routerdesc_failed(conn);
   } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
-    const char *flavname =
-      conn->requested_resource ? conn->requested_resource : "ns";
-    networkstatus_consensus_download_failed(0, flavname);
+    if (conn->requested_resource)
+      networkstatus_consensus_download_failed(0, conn->requested_resource);
   } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
     log_info(LD_DIR, "Giving up on certificate fetch from directory server "
              "at '%s'; retrying",
@@ -1004,8 +1003,14 @@ directory_get_consensus_url(int supports_conditional_consensus,
                             const char *resource)
 {
   char *url = NULL;
-  const char *hyphen = resource ? "-" : "";
-  const char *flavor = resource ? resource : "";
+  const char *hyphen, *flavor;
+  if (resource==NULL || strcmp(resource, "ns")==0) {
+    flavor = ""; /* Request ns consensuses as "", so older servers will work*/
+    hyphen = "";
+  } else {
+    flavor = resource;
+    hyphen = "-";
+  }
 
   if (supports_conditional_consensus) {
     char *authority_id_list;
@@ -1746,8 +1751,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
 
   if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
     int r;
-    const char *flavname =
-      conn->requested_resource ? conn->requested_resource : "ns";
+    const char *flavname = conn->requested_resource;
     if (status_code != 200) {
       int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
       log(severity, LD_DIR,

+ 1 - 1
src/or/networkstatus.c

@@ -1217,7 +1217,7 @@ update_consensus_networkstatus_downloads(time_t now)
     if (! we_want_to_fetch_flavor(options, i))
       continue;
 
-    resource = i==FLAV_NS ? NULL : networkstatus_get_flavor_name(i);
+    resource = networkstatus_get_flavor_name(i);
 
     if (!download_status_is_ready(&consensus_dl_status[i], now,
                                   CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))