[PATCH]: Export END_CIRC_REASON_* to controler

Mike Perry mikepery at fscked.org
Mon Oct 9 09:44:59 UTC 2006


Thus spake Mike Perry (mikepery at fscked.org):

> Attached is a patch to export circuit failure reasons to the
> controller. I had to convert several END_CIRC_AT_ORIGIN reason
> codes to the real reason codes for calls to circuit_mark_for_close().

Woops. In a couple places I forgot to negate the reason codes.

-- 
Mike Perry
Mad Computer Scientist
fscked.org evil labs
-------------- next part --------------
Index: src/or/circuitlist.c
===================================================================
--- src/or/circuitlist.c	(revision 8666)
+++ src/or/circuitlist.c	(working copy)
@@ -780,7 +780,7 @@
     if (CIRCUIT_IS_ORIGIN(circ) &&
         !circ->marked_for_close &&
         !circ->timestamp_dirty)
-      circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+      circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
   }
 }
 
@@ -824,6 +824,7 @@
 _circuit_mark_for_close(circuit_t *circ, int reason, int line,
                         const char *file)
 {
+  int orig_reason = reason;
   assert_circuit_ok(circ);
   tor_assert(line);
   tor_assert(file);
@@ -845,11 +846,13 @@
   } else if (CIRCUIT_IS_ORIGIN(circ) && reason != END_CIRC_REASON_NONE) {
     /* Don't warn about this; there are plenty of places where our code
      * is origin-agnostic. */
+    /* In fact, due to the desire to export reason information to the 
+     * controller, it has been made even more "origin-agnostic" than before */
     reason = END_CIRC_REASON_NONE;
   }
   if (reason < _END_CIRC_REASON_MIN || reason > _END_CIRC_REASON_MAX) {
     log_warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line);
-    reason = END_CIRC_REASON_NONE;
+    orig_reason = reason = END_CIRC_REASON_NONE;
   }
 
   if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
@@ -872,7 +875,8 @@
   }
   if (CIRCUIT_IS_ORIGIN(circ)) {
     control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
-     (circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED);
+     (circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
+     orig_reason);
   }
   if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
Index: src/or/rendservice.c
===================================================================
--- src/or/rendservice.c	(revision 8666)
+++ src/or/rendservice.c	(working copy)
@@ -612,7 +612,7 @@
  err:
   if (dh) crypto_dh_free(dh);
   if (launched)
-    circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_REASON_TORPROTOCOL);
   if (extend_info) extend_info_free(extend_info);
   return -1;
 }
@@ -763,7 +763,7 @@
 
   return;
  err:
-  circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+  circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
 }
 
 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
@@ -793,7 +793,7 @@
 
   return 0;
  err:
-  circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+  circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
   return -1;
 }
 
@@ -869,7 +869,7 @@
 
   return;
  err:
-  circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+  circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
 }
 
 /*
Index: src/or/control.c
===================================================================
--- src/or/control.c	(revision 8666)
+++ src/or/control.c	(working copy)
@@ -1867,8 +1867,9 @@
 
   /* now that we've populated the cpath, start extending */
   if (zero_circ) {
-    if (circuit_handle_first_hop(circ) < 0) {
-      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    int err_reason = 0;
+    if ((err_reason = circuit_handle_first_hop(circ)) < 0) {
+      circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
       if (v0)
         send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit");
       else
@@ -1877,11 +1878,12 @@
     }
   } else {
     if (circ->_base.state == CIRCUIT_STATE_OPEN) {
+      int err_reason = 0;
       circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
-      if (circuit_send_next_onion_skin(circ) < 0) {
+      if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
         log_info(LD_CONTROL,
                  "send_next_onion_skin failed; circuit marked for closing.");
-        circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+        circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
         if (v0)
           send_control0_error(conn, ERR_INTERNAL, "couldn't send onion skin");
         else
@@ -2745,7 +2747,8 @@
 /** Something has happened to circuit <b>circ</b>: tell any interested
  * control connections. */
 int
-control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
+control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
+        int rsn)
 {
   char *path=NULL, *msg;
   if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
@@ -2767,6 +2770,7 @@
   }
   if (EVENT_IS_INTERESTING1(EVENT_CIRCUIT_STATUS)) {
     const char *status;
+    const char *reason = "";
     switch (tp)
       {
       case CIRC_EVENT_LAUNCHED: status = "LAUNCHED"; break;
@@ -2778,18 +2782,37 @@
         log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
         return 0;
       }
+
+    if(tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
+        switch (rsn)
+          {
+          case END_CIRC_AT_ORIGIN: reason = " REASON=ORIGIN"; break;
+          case END_CIRC_REASON_NONE: reason = " REASON=NONE"; break;
+          case END_CIRC_REASON_TORPROTOCOL: reason = " REASON=TORPROTOCOL"; break;
+          case END_CIRC_REASON_INTERNAL: reason = " REASON=INTERNAL"; break;
+          case END_CIRC_REASON_REQUESTED: reason = " REASON=REQUESTED"; break;
+          case END_CIRC_REASON_HIBERNATING: reason = " REASON=HIBERNATING"; break;
+          case END_CIRC_REASON_RESOURCELIMIT: reason = " REASON=RESOURCELIMIT"; break;
+          case END_CIRC_REASON_CONNECTFAILED: reason = " REASON=CONNECTFAILED"; break;
+          case END_CIRC_REASON_OR_IDENTITY: reason = " REASON=OR_IDENTITY"; break;
+          case END_CIRC_REASON_OR_CONN_CLOSED: reason = " REASON=OR_CONN_CLOSED"; break;
+          default:
+            log_warn(LD_BUG, "Unrecognized reason code %d", (int)rsn);
+          }
+    }
+
     if (EVENT_IS_INTERESTING1S(EVENT_CIRCUIT_STATUS)) {
       send_control1_event(EVENT_CIRCUIT_STATUS, SHORT_NAMES,
-                          "650 CIRC %lu %s %s\r\n",
+                          "650 CIRC %lu %s %s%s\r\n",
                           (unsigned long)circ->global_identifier,
-                          status, path);
+                          status, path, reason);
     }
     if (EVENT_IS_INTERESTING1L(EVENT_CIRCUIT_STATUS)) {
       char *vpath = circuit_list_path_for_controller(circ);
       send_control1_event(EVENT_CIRCUIT_STATUS, LONG_NAMES,
-                          "650 CIRC %lu %s %s\r\n",
+                          "650 CIRC %lu %s %s%s\r\n",
                           (unsigned long)circ->global_identifier,
-                          status, vpath);
+                          status, vpath, reason);
       tor_free(vpath);
     }
   }
Index: src/or/or.h
===================================================================
--- src/or/or.h	(revision 8666)
+++ src/or/or.h	(working copy)
@@ -2069,7 +2069,7 @@
 int connection_control_process_inbuf(control_connection_t *conn);
 
 int control_event_circuit_status(origin_circuit_t *circ,
-                                 circuit_status_event_t e);
+                                 circuit_status_event_t e, int rsn);
 int control_event_stream_status(edge_connection_t *conn,
                                 stream_status_event_t e);
 int control_event_or_conn_status(or_connection_t *conn,
Index: src/or/command.c
===================================================================
--- src/or/command.c	(revision 8666)
+++ src/or/command.c	(working copy)
@@ -273,18 +273,19 @@
 
   if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */
     origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+    int err_reason = 0;
     log_debug(LD_OR,"at OP. Finishing handshake.");
-    if (circuit_finish_handshake(origin_circ, cell->command,
-                                 cell->payload) < 0) {
+    if ((err_reason = circuit_finish_handshake(origin_circ, cell->command,
+                                 cell->payload)) < 0) {
       log_warn(LD_OR,"circuit_finish_handshake failed.");
-      circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+      circuit_mark_for_close(circ, -err_reason);
       return;
     }
     log_debug(LD_OR,"Moving to next skin.");
-    if (circuit_send_next_onion_skin(origin_circ) < 0) {
+    if ((err_reason = circuit_send_next_onion_skin(origin_circ)) < 0) {
       log_info(LD_OR,"circuit_send_next_onion_skin failed.");
       /* XXX push this circuit_close lower */
-      circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+      circuit_mark_for_close(circ, -err_reason);
       return;
     }
   } else { /* pack it into an extended relay cell, and send it. */
Index: src/or/circuituse.c
===================================================================
--- src/or/circuituse.c	(revision 8666)
+++ src/or/circuituse.c	(working copy)
@@ -265,7 +265,7 @@
                circuit_state_to_string(victim->state), victim->purpose);
 
     circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
-    circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(victim, END_CIRC_REASON_CONNECTFAILED);
   }
 }
 
@@ -583,7 +583,7 @@
       log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)",
                 circ->n_circ_id, (int)(now - circ->timestamp_dirty),
                 circ->purpose);
-      circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+      circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
     } else if (!circ->timestamp_dirty &&
                circ->state == CIRCUIT_STATE_OPEN &&
                circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
@@ -591,7 +591,7 @@
         log_debug(LD_CIRC,
                   "Closing circuit that has been unused for %d seconds.",
                   (int)(now - circ->timestamp_created));
-        circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+        circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
       }
     }
   }
@@ -674,7 +674,7 @@
 void
 circuit_has_opened(origin_circuit_t *circ)
 {
-  control_event_circuit_status(circ, CIRC_EVENT_BUILT);
+  control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0);
 
   switch (TO_CIRCUIT(circ)->purpose) {
     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
Index: src/or/circuitbuild.c
===================================================================
--- src/or/circuitbuild.c	(revision 8666)
+++ src/or/circuitbuild.c	(working copy)
@@ -299,19 +299,20 @@
                           int need_uptime, int need_capacity, int internal)
 {
   origin_circuit_t *circ;
+  int err_reason = 0;
 
   circ = origin_circuit_init(purpose, need_uptime, need_capacity, internal);
 
   if (onion_pick_cpath_exit(circ, info) < 0 ||
       onion_populate_cpath(circ) < 0) {
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
     return NULL;
   }
 
-  control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED);
+  control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED, 0);
 
-  if (circuit_handle_first_hop(circ) < 0) {
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+  if ((err_reason = circuit_handle_first_hop(circ)) < 0) {
+    circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
     return NULL;
   }
   return circ;
@@ -328,6 +329,7 @@
   or_connection_t *n_conn;
   char tmpbuf[INET_NTOA_BUF_LEN];
   struct in_addr in;
+  int err_reason = 0;
 
   firsthop = onion_next_hop_in_cpath(circ->cpath);
   tor_assert(firsthop);
@@ -360,7 +362,7 @@
                                      firsthop->extend_info->identity_digest);
       if (!n_conn) { /* connect failed, forget the whole thing */
         log_info(LD_CIRC,"connect to firsthop failed. Closing.");
-        return -1;
+        return -END_CIRC_REASON_CONNECTFAILED;
       }
     }
 
@@ -375,9 +377,9 @@
     circ->_base.n_port = n_conn->_base.port;
     circ->_base.n_conn = n_conn;
     log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
-    if (circuit_send_next_onion_skin(circ) < 0) {
+    if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
       log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
-      return -1;
+      return err_reason;
     }
   }
   return 0;
@@ -394,6 +396,7 @@
 circuit_n_conn_done(or_connection_t *or_conn, int status)
 {
   smartlist_t *changed_circs;
+  int err_reason = 0;
 
   log_debug(LD_CIRC,"or_conn to %s, status=%d",
             or_conn->nickname ? or_conn->nickname : "NULL", status);
@@ -422,10 +425,10 @@
        * set_circid_orconn here. */
       circ->n_conn = or_conn;
       if (CIRCUIT_IS_ORIGIN(circ)) {
-        if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
+        if ((err_reason = circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ))) < 0) {
           log_info(LD_CIRC,
                    "send_next_onion_skin failed; circuit marked for closing.");
-          circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+          circuit_mark_for_close(circ, -err_reason);
           continue;
           /* XXX could this be bad, eg if next_onion_skin failed because conn
            *     died? */
@@ -865,7 +868,7 @@
   log_info(LD_CIRC,"Finished building %scircuit hop:",
            (reply_type == CELL_CREATED_FAST) ? "fast " : "");
   circuit_log_path(LOG_INFO,LD_CIRC,circ);
-  control_event_circuit_status(circ, CIRC_EVENT_EXTENDED);
+  control_event_circuit_status(circ, CIRC_EVENT_EXTENDED, 0);
 
   return 0;
 }
@@ -889,7 +892,7 @@
    *     means that a connection broke or an extend failed. For now,
    *     just give up.
    */
-  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
   return 0;
 
 #if 0
@@ -1393,12 +1396,13 @@
 int
 circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info)
 {
+  int err_reason = 0;
   circuit_append_new_exit(circ, info);
   circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
-  if (circuit_send_next_onion_skin(circ)<0) {
+  if ((err_reason = circuit_send_next_onion_skin(circ))<0) {
     log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.",
              info->nickname);
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
     return -1;
   }
   return 0;
Index: src/or/rendclient.c
===================================================================
--- src/or/rendclient.c	(revision 8666)
+++ src/or/rendclient.c	(working copy)
@@ -34,7 +34,7 @@
 
   if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) {
     log_warn(LD_BUG, "Internal error: Couldn't produce random cookie.");
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
     return -1;
   }
   if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
@@ -157,8 +157,8 @@
 
   return 0;
 err:
-  circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_AT_ORIGIN);
-  circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_AT_ORIGIN);
+  circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
+  circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
   return -1;
 }
 
@@ -190,7 +190,7 @@
     log_warn(LD_PROTOCOL,
              "Received REND_INTRODUCE_ACK on unexpected circuit %d.",
              circ->_base.n_circ_id);
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
     return -1;
   }
 
@@ -229,7 +229,7 @@
       if (!extend_info) {
         log_warn(LD_REND, "No introduction points left for %s. Closing.",
                  escaped_safe_str(circ->rend_query));
-        circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+        circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
         return -1;
       }
       log_info(LD_REND,
@@ -349,7 +349,7 @@
   if (circ->_base.purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
     log_warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. "
              "Closing circ.");
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
     return -1;
   }
   log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
@@ -371,7 +371,7 @@
       || !circ->build_state->pending_final_cpath) {
     log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not "
              "expecting it. Closing.");
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
     return -1;
   }
 
@@ -417,7 +417,7 @@
   circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
   return 0;
  err:
-  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
   return -1;
 }
 
Index: doc/control-spec.txt
===================================================================
--- doc/control-spec.txt	(revision 8666)
+++ doc/control-spec.txt	(working copy)
@@ -751,7 +751,8 @@
 
    The syntax is:
 
-     "650" SP "CIRC" SP CircuitID SP CircStatus [SP Path]
+     "650" SP "CIRC" SP CircuitID SP CircStatus [SP Path] 
+          [SP "REASON=" Reason] CRLF
 
       CircStatus =
                "LAUNCHED" / ; circuit ID assigned to new circuit
@@ -762,9 +763,15 @@
 
       Path = ServerID *("," ServerID)
 
+      Reason = "NONE" / "TORPROTOCOL" / "INTERNAL" / "REQUESTED" / 
+               "HIBERNATING" / "RESOURCELIMIT" / "CONNECTFAILED" /
+               "OR_IDENTITY" / "OR_CONN_CLOSED"
+
    The path is provided only when the circuit has been extended at least one
    hop.
 
+   Reason is provided only for FAILED and CLOSED events.
+
 4.1.2. Stream status changed
 
     The syntax is:


More information about the tor-dev mailing list