소스 검색

answer getinfo ns/purpose/bridge queries

svn:r12860
Roger Dingledine 16 년 전
부모
커밋
74d05f4b2c
5개의 변경된 파일73개의 추가작업 그리고 16개의 파일을 삭제
  1. 10 4
      doc/spec/control-spec.txt
  2. 2 1
      src/or/control.c
  3. 6 7
      src/or/dirserv.c
  4. 47 2
      src/or/networkstatus.c
  5. 8 2
      src/or/or.h

+ 10 - 4
doc/spec/control-spec.txt

@@ -379,8 +379,9 @@ $Id$
       hex) is <digest>.  Only available if we're downloading extra-info
       hex) is <digest>.  Only available if we're downloading extra-info
       documents.
       documents.
 
 
-    "ns/id/<OR identity>" or "ns/name/<OR nickname>" -- the latest network
-      status info for a given OR.  Network status info is as given in
+    "ns/id/<OR identity>" or "ns/name/<OR nickname>" -- the latest router
+      status info (v2 directory style) for a given OR.  Router status
+      info is as given in
       dir-spec.txt, and reflects the current beliefs of this Tor about the
       dir-spec.txt, and reflects the current beliefs of this Tor about the
       router in question. Like directory clients, controllers MUST
       router in question. Like directory clients, controllers MUST
       tolerate unrecognized flags and lines.  The published date and
       tolerate unrecognized flags and lines.  The published date and
@@ -388,10 +389,14 @@ $Id$
       not necessarily those for a descriptor that Tor currently has.
       not necessarily those for a descriptor that Tor currently has.
       [First implemented in 0.1.2.3-alpha.]
       [First implemented in 0.1.2.3-alpha.]
 
 
-    "ns/all" -- Network status info (v2 directory style) for all ORs we
+    "ns/all" -- Router status info (v2 directory style) for all ORs we
       have an opinion about, joined by newlines. [First implemented
       have an opinion about, joined by newlines. [First implemented
       in 0.1.2.3-alpha.]
       in 0.1.2.3-alpha.]
 
 
+    "ns/purpose/<purpose>" -- Router status info (v2 directory style)
+      for all ORs of this purpose. Mostly designed for /ns/purpose/bridge
+      queries. [First implemented in 0.2.0.13-alpha.]
+
     "desc/all-recent" -- the latest server descriptor for every router that
     "desc/all-recent" -- the latest server descriptor for every router that
       Tor knows about.
       Tor knows about.
 
 
@@ -401,7 +406,8 @@ $Id$
       3 for details.  (If VERBOSE_NAMES is enabled, the output will
       3 for details.  (If VERBOSE_NAMES is enabled, the output will
       not conform to dir-spec-v1.txt; instead, the result will be a
       not conform to dir-spec-v1.txt; instead, the result will be a
       space-separated list of LongName, each preceded by a "!" if it is
       space-separated list of LongName, each preceded by a "!" if it is
-      believed to be not running.)
+      believed to be not running.) This option is deprecated; use
+      "ns/all" instead.
 
 
     "address-mappings/all"
     "address-mappings/all"
     "address-mappings/config"
     "address-mappings/config"

+ 2 - 1
src/or/control.c

@@ -1453,7 +1453,8 @@ getinfo_helper_dir(control_connection_t *control_conn,
     routerlist_t *routerlist = router_get_routerlist();
     routerlist_t *routerlist = router_get_routerlist();
     int verbose = control_conn->use_long_names;
     int verbose = control_conn->use_long_names;
     if (!routerlist || !routerlist->routers ||
     if (!routerlist || !routerlist->routers ||
-        list_server_status(routerlist->routers, answer, verbose ? 2 : 1) < 0) {
+        list_server_status_v1(routerlist->routers, answer,
+                              verbose ? 2 : 1) < 0) {
       return -1;
       return -1;
     }
     }
   } else if (!strcmpstart(question, "extra-info/digest/")) {
   } else if (!strcmpstart(question, "extra-info/digest/")) {

+ 6 - 7
src/or/dirserv.c

@@ -56,8 +56,6 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
                         uint32_t addr, uint16_t or_port,
                         uint32_t addr, uint16_t or_port,
                         const char *platform, const char *contact,
                         const char *platform, const char *contact,
                         const char **msg, int should_log);
                         const char **msg, int should_log);
-static void dirserv_set_router_is_running(routerinfo_t *router,
-                                          time_t now);
 static void clear_cached_dir(cached_dir_t *d);
 static void clear_cached_dir(cached_dir_t *d);
 
 
 static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
 static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
@@ -915,7 +913,7 @@ list_single_server_status(routerinfo_t *desc, int is_live)
 /** Treat a router as alive if
 /** Treat a router as alive if
  *    - It's me, and I'm not hibernating.
  *    - It's me, and I'm not hibernating.
  * or - We've found it reachable recently. */
  * or - We've found it reachable recently. */
-static void
+void
 dirserv_set_router_is_running(routerinfo_t *router, time_t now)
 dirserv_set_router_is_running(routerinfo_t *router, time_t now)
 {
 {
   int answer;
   int answer;
@@ -942,8 +940,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
  * If for_controller is &gt;1, use the verbose nickname format.
  * If for_controller is &gt;1, use the verbose nickname format.
  */
  */
 int
 int
-list_server_status(smartlist_t *routers, char **router_status_out,
-                   int for_controller)
+list_server_status_v1(smartlist_t *routers, char **router_status_out,
+                      int for_controller)
 {
 {
   /* List of entries in a router-status style: An optional !, then an optional
   /* List of entries in a router-status style: An optional !, then an optional
    * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
    * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
@@ -952,7 +950,8 @@ list_server_status(smartlist_t *routers, char **router_status_out,
   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
   or_options_t *options = get_options();
   or_options_t *options = get_options();
   /* We include v2 dir auths here too, because they need to answer
   /* We include v2 dir auths here too, because they need to answer
-   * controllers. Eventually we'll deprecate this whole function. */
+   * controllers. Eventually we'll deprecate this whole function;
+   * see also networkstatus_getinfo_by_purpose(). */
   int authdir = authdir_mode_publishes_statuses(options);
   int authdir = authdir_mode_publishes_statuses(options);
   tor_assert(router_status_out);
   tor_assert(router_status_out);
 
 
@@ -1996,7 +1995,7 @@ get_possible_sybil_list(const smartlist_t *routers)
  * We assume that ri-\>is_running has already been set, e.g. by
  * We assume that ri-\>is_running has already been set, e.g. by
  *   dirserv_set_router_is_running(ri, now);
  *   dirserv_set_router_is_running(ri, now);
  */
  */
-static void
+void
 set_routerstatus_from_routerinfo(routerstatus_t *rs,
 set_routerstatus_from_routerinfo(routerstatus_t *rs,
                                  routerinfo_t *ri, time_t now,
                                  routerinfo_t *ri, time_t now,
                                  int naming, int exits_can_be_guards,
                                  int naming, int exits_can_be_guards,

+ 47 - 2
src/or/networkstatus.c

@@ -1677,6 +1677,49 @@ networkstatus_getinfo_helper_single(routerstatus_t *rs)
   return tor_strdup(buf);
   return tor_strdup(buf);
 }
 }
 
 
+/** Alloc and return a string describing routerstatuses for the most
+ * recent info of each router we know about that is of purpose
+ * <b>purpose_string</b>. Return NULL if unrecognized purpose.
+ *
+ * Right now this function is oriented toward listing bridges (you
+ * shouldn't use this for general-purpose routers, since those
+ * should be listed from the consensus, not from the routers list). */
+char *
+networkstatus_getinfo_by_purpose(const char *purpose_string)
+{
+  time_t now = time(NULL);
+  time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
+  char *answer;
+  routerlist_t *rl = router_get_routerlist();
+  smartlist_t *statuses = smartlist_create();
+  uint8_t purpose = router_purpose_from_string(purpose_string);
+  routerstatus_t rs;
+  int bridge_auth = authdir_mode_bridge(get_options());
+
+  if (purpose == ROUTER_PURPOSE_UNKNOWN) {
+    log_info(LD_DIR, "Unrecognized purpose '%s' when listing router statuses.",
+             purpose_string);
+    return NULL;
+  }
+
+  SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+    if (ri->cache_info.published_on < cutoff)
+      continue;
+    if (ri->purpose != purpose)
+      continue;
+    if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
+      dirserv_set_router_is_running(ri, now);
+    /* then generate and write out status lines for each of them */
+    set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0, 0);
+    smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
+  });
+
+  answer = smartlist_join_strings(statuses, "", 0, NULL);
+  SMARTLIST_FOREACH(statuses, char *, cp, tor_free(cp));
+  smartlist_free(statuses);
+  return answer;
+}
+
 /** If <b>question</b> is a string beginning with "ns/" in a format the
 /** If <b>question</b> is a string beginning with "ns/" in a format the
  * control interface expects for a GETINFO question, set *<b>answer</b> to a
  * control interface expects for a GETINFO question, set *<b>answer</b> to a
  * newly-allocated string containing networkstatus lines for the appropriate
  * newly-allocated string containing networkstatus lines for the appropriate
@@ -1712,13 +1755,15 @@ getinfo_helper_networkstatus(control_connection_t *conn,
     status = router_get_consensus_status_by_id(d);
     status = router_get_consensus_status_by_id(d);
   } else if (!strcmpstart(question, "ns/name/")) {
   } else if (!strcmpstart(question, "ns/name/")) {
     status = router_get_consensus_status_by_nickname(question+8, 0);
     status = router_get_consensus_status_by_nickname(question+8, 0);
+  } else if (!strcmpstart(question, "ns/purpose/")) {
+    *answer = networkstatus_getinfo_by_purpose(question+11);
+    return *answer ? 0 : -1;
   } else {
   } else {
     return -1;
     return -1;
   }
   }
 
 
-  if (status) {
+  if (status)
     *answer = networkstatus_getinfo_helper_single(status);
     *answer = networkstatus_getinfo_helper_single(status);
-  }
   return 0;
   return 0;
 }
 }
 
 

+ 8 - 2
src/or/or.h

@@ -3051,8 +3051,9 @@ int dirserv_add_descriptor(routerinfo_t *ri, const char **msg);
 int getinfo_helper_dirserv_unregistered(control_connection_t *conn,
 int getinfo_helper_dirserv_unregistered(control_connection_t *conn,
                                         const char *question, char **answer);
                                         const char *question, char **answer);
 void dirserv_free_descriptors(void);
 void dirserv_free_descriptors(void);
-int list_server_status(smartlist_t *routers, char **router_status_out,
-                       int for_controller);
+void dirserv_set_router_is_running(routerinfo_t *router, time_t now);
+int list_server_status_v1(smartlist_t *routers, char **router_status_out,
+                          int for_controller);
 int dirserv_dump_directory_to_string(char **dir_out,
 int dirserv_dump_directory_to_string(char **dir_out,
                                      crypto_pk_env_t *private_key);
                                      crypto_pk_env_t *private_key);
 
 
@@ -3158,6 +3159,10 @@ const char *dirvote_get_pending_detached_signatures(void);
 #define DGV_INCLUDE_PENDING 2
 #define DGV_INCLUDE_PENDING 2
 #define DGV_INCLUDE_PREVIOUS 4
 #define DGV_INCLUDE_PREVIOUS 4
 const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
 const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
+void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+                                      routerinfo_t *ri, time_t now,
+                                      int naming, int exits_can_be_guards,
+                                      int listbadexits, int listbaddirs);
 void router_clear_status_flags(routerinfo_t *ri);
 void router_clear_status_flags(routerinfo_t *ri);
 networkstatus_vote_t *
 networkstatus_vote_t *
 dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
 dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
@@ -3348,6 +3353,7 @@ void signed_descs_update_status_from_consensus_networkstatus(
                                                          smartlist_t *descs);
                                                          smartlist_t *descs);
 
 
 char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
 char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
+char *networkstatus_getinfo_by_purpose(const char *purpose_string);
 int getinfo_helper_networkstatus(control_connection_t *conn,
 int getinfo_helper_networkstatus(control_connection_t *conn,
                                  const char *question, char **answer);
                                  const char *question, char **answer);
 void networkstatus_free_all(void);
 void networkstatus_free_all(void);