[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] Add an ap_bridge function to do a socketpair and skip socks.



Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/src/or

Modified Files:
	connection_edge.c directory.c main.c or.h router.c 
Log Message:
Add an ap_bridge function to do a socketpair and skip socks.
This allows us to do a directory connection *through* tor just
as if we're doing it as an application.

Make ap_conns tolerate it when the application sends stuff before
The socks handshake is done (it just buffers it).

Tell directory_initiate_command the length of the payload (because
it might include nuls).

Add a directory_has_arrived function to, for example, start building
the rendezvous service descriptor.


Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.119
retrieving revision 1.120
diff -u -d -r1.119 -r1.120
--- connection_edge.c	27 Mar 2004 05:45:52 -0000	1.119
+++ connection_edge.c	31 Mar 2004 22:02:13 -0000	1.120
@@ -72,6 +72,9 @@
 #endif
 }
 
+/* mark and return -1 if there was an unexpected error with the conn,
+ * else return 0.
+ */
 int connection_edge_process_inbuf(connection_t *conn) {
 
   assert(conn);
@@ -119,10 +122,14 @@
       }
       return 0;
     case EXIT_CONN_STATE_CONNECTING:
-      log_fn(LOG_INFO,"text from server while in 'connecting' state at exit. Leaving it on buffer.");
+    case AP_CONN_STATE_CIRCUIT_WAIT:
+    case AP_CONN_STATE_CONNECT_WAIT:
+      log_fn(LOG_INFO,"data from edge while in '%s' state. Leaving it on buffer.",
+                      conn_state_to_string[conn->type][conn->state]);
       return 0;
   }
   log_fn(LOG_WARN,"Got unexpected state %d. Closing.",conn->state);
+  connection_mark_for_close(conn, END_STREAM_REASON_MISC);
   return -1;
 }
 
@@ -192,8 +199,9 @@
   return 0;
 }
 
-int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command,
-                                 void *payload, int payload_len, crypt_path_t *cpath_layer) {
+int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
+                                 int relay_command, void *payload,
+                                 int payload_len, crypt_path_t *cpath_layer) {
   cell_t cell;
   relay_header_t rh;
   int cell_direction;
@@ -207,7 +215,6 @@
 
   memset(&cell, 0, sizeof(cell_t));
   cell.command = CELL_RELAY;
-//  if(fromconn && fromconn->type == CONN_TYPE_AP) {
   if(cpath_layer) {
     cell.circ_id = circ->n_circ_id;
     cell_direction = CELL_DIRECTION_OUT;
@@ -238,8 +245,9 @@
 
 /* an incoming relay cell has arrived. return -1 if you want to tear down the
  * circuit, else 0. */
-int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn,
-                                       int edge_type, crypt_path_t *layer_hint) {
+int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
+                                       connection_t *conn, int edge_type,
+                                       crypt_path_t *layer_hint) {
   static int num_seen=0;
   uint32_t addr;
   relay_header_t rh;
@@ -275,7 +283,6 @@
       if (rh.length >= 4) {
         memcpy(&addr, cell->payload + RELAY_HEADER_SIZE, 4);
         addr = ntohl(addr);
-//        addr = ntohl(*(uint32_t*)(cell->payload + RELAY_HEADER_SIZE));
         client_dns_set_entry(conn->socks_request->address, addr);
       }
       log_fn(LOG_INFO,"'connected' received after %d seconds.",
@@ -283,6 +290,11 @@
       circuit_log_path(LOG_INFO,circ);
       connection_ap_handshake_socks_reply(conn, NULL, 0, 1);
       conn->socks_request->has_finished = 1;
+      /* handle anything that might have queued */
+      if (connection_edge_package_raw_inbuf(conn) < 0) {
+        connection_mark_for_close(conn, END_STREAM_REASON_MISC);
+        return 0;
+      }
       return 0;
     } else {
       log_fn(LOG_WARN,"Got an unexpected relay command %d, in state %d (%s). Closing.",
@@ -353,7 +365,6 @@
          */
         memcpy(&addr, cell->payload+RELAY_HEADER_SIZE+1, 4);
         addr = ntohl(addr);
-//        addr = ntohl(*(uint32_t*)(cell->payload+RELAY_HEADER_SIZE+1));
         client_dns_set_entry(conn->socks_request->address, addr);
         conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
         if(connection_ap_handshake_attach_circuit(conn) >= 0)
@@ -503,7 +514,7 @@
       connection_stop_writing(conn);
       return 0;
     default:
-      log_fn(LOG_WARN,"BUG: called in unexpected state: %d", conn->state);
+      log_fn(LOG_WARN,"BUG: called in unexpected state %d.", conn->state);
       return -1;
   }
   return 0;
@@ -849,6 +860,59 @@
   return;
 }
 
+/* make an ap connection_t, do a socketpair and attach one side
+ * to the conn, connection_add it, initialize it to circuit_wait,
+ * and call connection_ap_handshake_attach_circuit(conn) on it.
+ * Return the other end of the socketpair, or -1 if error.
+ */
+int connection_ap_make_bridge(char *address, uint16_t port) {
+  int fd[2];
+  connection_t *conn;
+
+  log_fn(LOG_INFO,"Making AP bridge to %s:%d ...",address,port);
+
+  if(tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
+    log(LOG_ERR, "Couldn't construct socketpair: %s", strerror(errno));
+    exit(1);
+  }
+
+  set_socket_nonblocking(fd[0]);
+  set_socket_nonblocking(fd[1]);
+
+  conn = connection_new(CONN_TYPE_AP);
+  conn->s = fd[0];
+
+  /* populate conn->socks_request */
+
+  /* leave version at zero, so the socks_reply is empty */
+  conn->socks_request->socks_version = 0;
+  conn->socks_request->has_finished = 0; /* waiting for 'connected' */
+  strcpy(conn->socks_request->address, address);
+  conn->socks_request->port = port;
+
+  conn->address = tor_strdup("(local bridge)");
+  conn->addr = ntohs(0);
+  conn->port = 0;
+
+  if(connection_add(conn) < 0) { /* no space, forget it */
+    connection_free(conn); /* this closes fd[0] */
+    close(fd[1]);
+    return -1;
+  }
+
+  conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+  connection_start_reading(conn);
+
+  if (connection_ap_handshake_attach_circuit(conn) < 0) {
+    connection_mark_for_close(conn, 0);
+    close(fd[1]);
+    return -1;
+  }
+
+  log_fn(LOG_INFO,"... AP bridge created and connected.");
+  return fd[1];
+}
+
 void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
                                          int replylen, char success) {
   char buf[256];
@@ -877,7 +941,8 @@
                           The spec doesn't seem to say what to do here. -RD */
     connection_write_to_buf(buf,10,conn);
   }
-  /* if socks_version isn't 4 or 5, don't send anything */
+  /* If socks_version isn't 4 or 5, don't send anything.
+   * This can happen in the case of AP bridges. */
   return;
 }
 

Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/src/or/directory.c,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -d -r1.77 -r1.78
--- directory.c	31 Mar 2004 20:58:35 -0000	1.77
+++ directory.c	31 Mar 2004 22:02:13 -0000	1.78
@@ -4,8 +4,8 @@
 
 #include "or.h"
 
-static void directory_send_command(connection_t *conn,
-                                   int purpose, const char *payload);
+static void directory_send_command(connection_t *conn, int purpose,
+                                   const char *payload, int payload_len);
 static int directory_handle_command(connection_t *conn);
 
 /********* START VARIABLES **********/
@@ -18,23 +18,18 @@
 
 /********* END VARIABLES ************/
 
-void directory_initiate_command(routerinfo_t *router, int purpose, const char *payload) {
+void directory_initiate_command(routerinfo_t *router, int purpose,
+                                const char *payload, int payload_len) {
   connection_t *conn;
 
-  switch(purpose) {
-    case DIR_PURPOSE_FETCH_DIR:
-      log_fn(LOG_DEBUG,"initiating directory fetch");
-      break;
-    case DIR_PURPOSE_FETCH_HIDSERV:
-      log_fn(LOG_DEBUG,"initiating hidden-service descriptor fetch");
-      break;
-    case DIR_PURPOSE_UPLOAD_DIR:
-      log_fn(LOG_DEBUG,"initiating server descriptor upload");
-      break;
-    case DIR_PURPOSE_UPLOAD_HIDSERV:
-      log_fn(LOG_DEBUG,"initiating hidden-service descriptor upload");
-      break;
-  }
+  if(purpose == DIR_PURPOSE_FETCH_DIR)
+    log_fn(LOG_DEBUG,"initiating directory fetch");
+  if(purpose == DIR_PURPOSE_FETCH_HIDSERV)
+    log_fn(LOG_DEBUG,"initiating hidden-service descriptor fetch");
+  if(purpose == DIR_PURPOSE_UPLOAD_DIR)
+    log_fn(LOG_DEBUG,"initiating server descriptor upload");
+  if(purpose == DIR_PURPOSE_UPLOAD_HIDSERV)
+    log_fn(LOG_DEBUG,"initiating hidden-service descriptor upload");
 
   if (!router) { /* i guess they didn't have one in mind for me to use */
     log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose);
@@ -59,7 +54,7 @@
   }
 
   /* queue the command on the outbuf */
-  directory_send_command(conn, purpose, payload);
+  directory_send_command(conn, purpose, payload, payload_len);
 
   if(purpose == DIR_PURPOSE_FETCH_DIR ||
      purpose == DIR_PURPOSE_UPLOAD_DIR) {
@@ -86,14 +81,20 @@
      *   populate it and add it at the right state
      * socketpair and hook up both sides
      */
+    conn->s = connection_ap_make_bridge(conn->address, conn->port);
+    if(conn->s < 0) {
+      log_fn(LOG_WARN,"Making AP bridge to dirserver failed.");
+      connection_mark_for_close(conn, 0);
+      return;
+    }
 
     conn->state = DIR_CONN_STATE_CLIENT_SENDING; 
     connection_set_poll_socket(conn);
   }
 }
 
-static void directory_send_command(connection_t *conn,
-                                   int purpose, const char *payload) {
+static void directory_send_command(connection_t *conn, int purpose,
+                                   const char *payload, int payload_len) {
   char fetchstring[] = "GET / HTTP/1.0\r\n\r\n";
   char tmp[8192];
 
@@ -107,7 +108,7 @@
     case DIR_PURPOSE_UPLOAD_DIR:
       assert(payload);
       snprintf(tmp, sizeof(tmp), "POST / HTTP/1.0\r\nContent-Length: %d\r\n\r\n%s",
-               (int)strlen(payload), payload);
+               payload_len, payload);
       connection_write_to_buf(tmp, strlen(tmp), conn);
       break;
     case DIR_PURPOSE_FETCH_HIDSERV:
@@ -118,9 +119,10 @@
     case DIR_PURPOSE_UPLOAD_HIDSERV:
       assert(payload);
       snprintf(tmp, sizeof(tmp),
-        "POST /hidserv/ HTTP/1.0\r\nContent-Length: %d\r\n\r\n%s",
-        (int)strlen(payload), payload);
+        "POST /hidserv/ HTTP/1.0\r\nContent-Length: %d\r\n\r\n", payload_len);
       connection_write_to_buf(tmp, strlen(tmp), conn);
+      /* could include nuls, need to write it separately */
+      connection_write_to_buf(payload, payload_len, conn);
       break;
   }
 }
@@ -230,7 +232,10 @@
       } else {
         log_fn(LOG_INFO,"updated routers.");
       }
-      has_fetched_directory=1;
+      if (has_fetched_directory==0) {
+        has_fetched_directory=1;
+        directory_has_arrived(); /* do things we've been waiting to do */
+      }
       if(options.ORPort) { /* connect to them all */
         router_retry_connections();
       }

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.215
retrieving revision 1.216
diff -u -d -r1.215 -r1.216
--- main.c	31 Mar 2004 21:35:23 -0000	1.215
+++ main.c	31 Mar 2004 22:02:13 -0000	1.216
@@ -277,6 +277,15 @@
   }
 }
 
+void directory_has_arrived(void) {
+
+  log_fn(LOG_INFO, "We now have a directory.");
+
+  directory_initiate_command(router_pick_directory_server(),
+                             DIR_PURPOSE_FETCH_HIDSERV, "foo", 3);
+
+}
+
 /* Perform regular maintenance tasks for a single connection.  This
  * function gets run once per second per connection by run_housekeeping.
  */
@@ -329,7 +338,7 @@
       /* NOTE directory servers do not currently fetch directories.
        * Hope this doesn't bite us later. */
       directory_initiate_command(router_pick_directory_server(),
-                                 DIR_PURPOSE_FETCH_DIR, NULL);
+                                 DIR_PURPOSE_FETCH_DIR, NULL, 0);
     } else {
       /* We're a directory; dump any old descriptors. */
       dirserv_remove_old_servers();
@@ -362,7 +371,7 @@
    *    that became dirty more than NewCircuitPeriod seconds ago,
    *    and we make a new circ if there are no clean circuits.
    */
-  if((has_fetched_directory || options.DirPort) &&
+  if(has_fetched_directory &&
      (options.SocksPort || options.RunTesting)) {
 
     if (options.SocksPort)
@@ -521,7 +530,7 @@
   } else {
     /* fetch a new directory */
     directory_initiate_command(router_pick_directory_server(),
-                               DIR_PURPOSE_FETCH_DIR, NULL);
+                               DIR_PURPOSE_FETCH_DIR, NULL, 0);
   }
   if(options.ORPort) {
     router_rebuild_descriptor();
@@ -558,6 +567,11 @@
     return -1;
   }
 
+  if(options.DirPort) { /* the directory is already here, run startup things */
+    has_fetched_directory = 1;
+    directory_has_arrived();
+  }
+
   if(options.ORPort) {
     cpu_init(); /* launch cpuworkers. Need to do this *after* we've read the onion key. */
     router_upload_desc_to_dirservers(); /* upload our descriptor to all dirservers */

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.267
retrieving revision 1.268
diff -u -d -r1.267 -r1.268
--- or.h	31 Mar 2004 21:35:23 -0000	1.267
+++ or.h	31 Mar 2004 22:02:13 -0000	1.268
@@ -793,16 +793,18 @@
 int connection_edge_process_inbuf(connection_t *conn);
 int connection_edge_destroy(uint16_t circ_id, connection_t *conn);
 int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer);
-
-int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command,
-                                 void *payload, int payload_len, crypt_path_t *cpath_layer);
-
-int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn,
-                                       int edge_type, crypt_path_t *layer_hint);
+int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
+                                 int relay_command, void *payload,
+                                 int payload_len, crypt_path_t *cpath_layer);
+int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
+                                       connection_t *conn, int edge_type,
+                                       crypt_path_t *layer_hint);
 int connection_edge_finished_flushing(connection_t *conn);
 
 int connection_edge_package_raw_inbuf(connection_t *conn);
 
+int connection_ap_make_bridge(char *address, uint16_t port);
+
 void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
                                          int replylen, char success);
 
@@ -843,7 +845,8 @@
 
 /********************************* directory.c ***************************/
 
-void directory_initiate_command(routerinfo_t *router, int purpose, const char *payload);
+void directory_initiate_command(routerinfo_t *router, int purpose,
+                                const char *payload, int payload_len);
 int connection_dir_process_inbuf(connection_t *conn);
 int connection_dir_finished_flushing(connection_t *conn);
 
@@ -874,6 +877,8 @@
 void connection_stop_writing(connection_t *conn);
 void connection_start_writing(connection_t *conn);
 
+void directory_has_arrived(void);
+
 int main(int argc, char *argv[]);
 
 /********************************* onion.c ***************************/

Index: router.c
===================================================================
RCS file: /home/or/cvsroot/src/or/router.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- router.c	31 Mar 2004 21:35:23 -0000	1.17
+++ router.c	31 Mar 2004 22:02:13 -0000	1.18
@@ -255,7 +255,7 @@
   for(i=0;i<rl->n_routers;i++) {
     router = rl->routers[i];
     if(router->dir_port > 0)
-      directory_initiate_command(router, DIR_PURPOSE_UPLOAD_DIR, s);
+      directory_initiate_command(router, DIR_PURPOSE_UPLOAD_DIR, s, strlen(s));
   }
 }