Explorar el Código

Merge remote-tracking branch 'rransom/feature2411-v4'

Nick Mathewson hace 12 años
padre
commit
7cb804343b
Se han modificado 4 ficheros con 180 adiciones y 32 borrados
  1. 12 0
      changes/feature2411
  2. 57 0
      src/or/circuitlist.c
  3. 1 0
      src/or/circuitlist.h
  4. 110 32
      src/or/control.c

+ 12 - 0
changes/feature2411

@@ -0,0 +1,12 @@
+  o Minor features:
+
+    - Report flags that control a circuit's path selection to
+      controllers in CIRC events and in replies to 'GETINFO
+      circuit-status'.  Implements part of ticket 2411.
+
+    - Report the hidden service address and current state of a
+      hidden-service-related circuit to controllers in CIRC events and
+      in replies to 'GETINFO circuit-status'.  Implements part of
+      ticket 2411.
+
+

+ 57 - 0
src/or/circuitlist.c

@@ -378,6 +378,63 @@ circuit_purpose_to_controller_string(uint8_t purpose)
   }
 }
 
+/** Return a string specifying the state of the hidden-service circuit
+ * purpose <b>purpose</b>, or NULL if <b>purpose</b> is not a
+ * hidden-service-related circuit purpose. */
+const char *
+circuit_purpose_to_controller_hs_state_string(uint8_t purpose)
+{
+  switch (purpose)
+    {
+    default:
+      log_fn(LOG_WARN, LD_BUG,
+             "Unrecognized circuit purpose: %d",
+             (int)purpose);
+      tor_fragile_assert();
+      /* fall through */
+
+    case CIRCUIT_PURPOSE_OR:
+    case CIRCUIT_PURPOSE_C_GENERAL:
+    case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
+    case CIRCUIT_PURPOSE_TESTING:
+    case CIRCUIT_PURPOSE_CONTROLLER:
+      return NULL;
+
+    case CIRCUIT_PURPOSE_INTRO_POINT:
+      return "OR_HSSI_ESTABLISHED";
+    case CIRCUIT_PURPOSE_REND_POINT_WAITING:
+      return "OR_HSCR_ESTABLISHED";
+    case CIRCUIT_PURPOSE_REND_ESTABLISHED:
+      return "OR_HS_R_JOINED";
+
+    case CIRCUIT_PURPOSE_C_INTRODUCING:
+      return "HSCI_CONNECTING";
+    case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+      return "HSCI_INTRO_SENT";
+    case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
+      return "HSCI_DONE";
+
+    case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
+      return "HSCR_CONNECTING";
+    case CIRCUIT_PURPOSE_C_REND_READY:
+      return "HSCR_ESTABLISHED_IDLE";
+    case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
+      return "HSCR_ESTABLISHED_WAITING";
+    case CIRCUIT_PURPOSE_C_REND_JOINED:
+      return "HSCR_JOINED";
+
+    case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
+      return "HSSI_CONNECTING";
+    case CIRCUIT_PURPOSE_S_INTRO:
+      return "HSSI_ESTABLISHED";
+
+    case CIRCUIT_PURPOSE_S_CONNECT_REND:
+      return "HSSR_CONNECTING";
+    case CIRCUIT_PURPOSE_S_REND_JOINED:
+      return "HSSR_JOINED";
+    }
+}
+
 /** Return a human-readable string for the circuit purpose <b>purpose</b>. */
 const char *
 circuit_purpose_to_string(uint8_t purpose)

+ 1 - 0
src/or/circuitlist.h

@@ -15,6 +15,7 @@
 circuit_t * _circuit_get_global_list(void);
 const char *circuit_state_to_string(int state);
 const char *circuit_purpose_to_controller_string(uint8_t purpose);
+const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);
 const char *circuit_purpose_to_string(uint8_t purpose);
 void circuit_dump_by_conn(connection_t *conn, int severity);
 void circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id,

+ 110 - 32
src/or/control.c

@@ -1780,6 +1780,88 @@ getinfo_helper_dir(control_connection_t *control_conn,
   return 0;
 }
 
+/** Allocate and return a description of <b>circ</b>'s current status,
+ * including its path (if any). */
+static char *
+circuit_describe_status_for_controller(origin_circuit_t *circ)
+{
+  char *rv;
+  smartlist_t *descparts = smartlist_create();
+
+  {
+    char *vpath = circuit_list_path_for_controller(circ);
+    if (*vpath) {
+      smartlist_add(descparts, vpath);
+    } else {
+      tor_free(vpath); /* empty path; don't put an extra space in the result */
+    }
+  }
+
+  {
+    char *buildflags = NULL;
+    cpath_build_state_t *build_state = circ->build_state;
+    smartlist_t *flaglist = smartlist_create();
+    char *flaglist_joined;
+
+    if (build_state->onehop_tunnel)
+      smartlist_add(flaglist, (void *)"ONEHOP_TUNNEL");
+    if (build_state->is_internal)
+      smartlist_add(flaglist, (void *)"IS_INTERNAL");
+    if (build_state->need_capacity)
+      smartlist_add(flaglist, (void *)"NEED_CAPACITY");
+    if (build_state->need_uptime)
+      smartlist_add(flaglist, (void *)"NEED_UPTIME");
+
+    /* Only emit a BUILD_FLAGS argument if it will have a non-empty value. */
+    if (smartlist_len(flaglist)) {
+      flaglist_joined = smartlist_join_strings(flaglist, ",", 0, NULL);
+
+      tor_asprintf(&buildflags, "BUILD_FLAGS=%s", flaglist_joined);
+      smartlist_add(descparts, buildflags);
+
+      tor_free(flaglist_joined);
+    }
+
+    smartlist_free(flaglist);
+  }
+
+  {
+    char *purpose = NULL;
+    tor_asprintf(&purpose, "PURPOSE=%s",
+                 circuit_purpose_to_controller_string(circ->_base.purpose));
+    smartlist_add(descparts, purpose);
+  }
+
+  {
+    char *hs_state_arg = NULL;
+    const char *hs_state =
+      circuit_purpose_to_controller_hs_state_string(circ->_base.purpose);
+
+    if (hs_state != NULL) {
+      tor_asprintf(&hs_state_arg, "HS_STATE=%s",
+                   hs_state);
+
+      smartlist_add(descparts, hs_state_arg);
+    }
+  }
+
+  if (circ->rend_data != NULL) {
+    char *rend_query_arg = NULL;
+
+    tor_asprintf(&rend_query_arg, "REND_QUERY=%s",
+                 circ->rend_data->onion_address);
+
+    smartlist_add(descparts, rend_query_arg);
+  }
+
+  rv = smartlist_join_strings(descparts, " ", 0, NULL);
+
+  SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
+  smartlist_free(descparts);
+
+  return rv;
+}
+
 /** Implementation helper for GETINFO: knows how to generate summaries of the
  * current states of things we send events about. */
 static int
@@ -1789,33 +1871,33 @@ getinfo_helper_events(control_connection_t *control_conn,
 {
   (void) control_conn;
   if (!strcmp(question, "circuit-status")) {
-    circuit_t *circ;
+    circuit_t *circ_;
     smartlist_t *status = smartlist_create();
-    for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
-      char *s, *path;
+    for (circ_ = _circuit_get_global_list(); circ_; circ_ = circ_->next) {
+      origin_circuit_t *circ;
+      char *s, *circdesc;
       size_t slen;
       const char *state;
-      const char *purpose;
-      if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close)
+      if (! CIRCUIT_IS_ORIGIN(circ_) || circ_->marked_for_close)
         continue;
+      circ = TO_ORIGIN_CIRCUIT(circ_);
 
-      path = circuit_list_path_for_controller(TO_ORIGIN_CIRCUIT(circ));
-
-      if (circ->state == CIRCUIT_STATE_OPEN)
+      if (circ->_base.state == CIRCUIT_STATE_OPEN)
         state = "BUILT";
-      else if (strlen(path))
+      else if (circ->cpath)
         state = "EXTENDED";
       else
         state = "LAUNCHED";
 
-      purpose = circuit_purpose_to_controller_string(circ->purpose);
-      slen = strlen(path)+strlen(state)+strlen(purpose)+30;
+      circdesc = circuit_describe_status_for_controller(circ);
+
+      slen = strlen(circdesc)+strlen(state)+30;
       s = tor_malloc(slen+1);
-      tor_snprintf(s, slen, "%lu %s%s%s PURPOSE=%s",
-                   (unsigned long)TO_ORIGIN_CIRCUIT(circ)->global_identifier,
-                   state, *path ? " " : "", path, purpose);
+      tor_snprintf(s, slen, "%lu %s%s%s",
+                   (unsigned long)circ->global_identifier,
+                   state, *circdesc ? " " : "", circdesc);
       smartlist_add(status, s);
-      tor_free(path);
+      tor_free(circdesc);
     }
     *answer = smartlist_join_strings(status, "\r\n", 0, NULL);
     SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
@@ -3237,7 +3319,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
                              int reason_code)
 {
   const char *status;
-  char extended_buf[96];
+  char reasons[64] = "";
   if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
     return 0;
   tor_assert(circ);
@@ -3254,36 +3336,32 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
       return 0;
     }
 
-  tor_snprintf(extended_buf, sizeof(extended_buf), "PURPOSE=%s",
-               circuit_purpose_to_controller_string(circ->_base.purpose));
-
   if (tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
     const char *reason_str = circuit_end_reason_to_control_string(reason_code);
-    char *reason = NULL;
-    size_t n=strlen(extended_buf);
+    char unk_reason_buf[16];
     if (!reason_str) {
-      reason = tor_malloc(16);
-      tor_snprintf(reason, 16, "UNKNOWN_%d", reason_code);
-      reason_str = reason;
+      tor_snprintf(unk_reason_buf, 16, "UNKNOWN_%d", reason_code);
+      reason_str = unk_reason_buf;
     }
     if (reason_code > 0 && reason_code & END_CIRC_REASON_FLAG_REMOTE) {
-      tor_snprintf(extended_buf+n, sizeof(extended_buf)-n,
+      tor_snprintf(reasons, sizeof(reasons),
                    " REASON=DESTROYED REMOTE_REASON=%s", reason_str);
     } else {
-      tor_snprintf(extended_buf+n, sizeof(extended_buf)-n,
+      tor_snprintf(reasons, sizeof(reasons),
                    " REASON=%s", reason_str);
     }
-    tor_free(reason);
   }
 
   {
-    char *vpath = circuit_list_path_for_controller(circ);
-    const char *sp = strlen(vpath) ? " " : "";
+    char *circdesc = circuit_describe_status_for_controller(circ);
+    const char *sp = strlen(circdesc) ? " " : "";
     send_control_event(EVENT_CIRCUIT_STATUS, ALL_FORMATS,
-                                "650 CIRC %lu %s%s%s %s\r\n",
+                                "650 CIRC %lu %s%s%s%s\r\n",
                                 (unsigned long)circ->global_identifier,
-                                status, sp, vpath, extended_buf);
-    tor_free(vpath);
+                                status, sp,
+                                circdesc,
+                                reasons);
+    tor_free(circdesc);
   }
 
   return 0;