[or-cvs] Add an ap_bridge function to do a socketpair and skip socks.
Roger Dingledine
arma at seul.org
Wed Mar 31 22:02:16 UTC 2004
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));
}
}
More information about the tor-commits
mailing list