diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/circuit.c | 242 | ||||
-rw-r--r-- | src/or/config.c | 2 | ||||
-rw-r--r-- | src/or/connection_ap.c | 208 | ||||
-rw-r--r-- | src/or/connection_or.c | 2 | ||||
-rw-r--r-- | src/or/main.c | 17 | ||||
-rw-r--r-- | src/or/onion.c | 20 | ||||
-rw-r--r-- | src/or/or.h | 39 | ||||
-rw-r--r-- | src/or/test.c | 2 |
8 files changed, 288 insertions, 244 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c index 593c5bddf..2157be0f2 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -4,6 +4,8 @@ #include "or.h" +extern or_options_t options; /* command-line and config-file options */ + /********* START VARIABLES **********/ static circuit_t *global_circuitlist=NULL; @@ -49,12 +51,18 @@ void circuit_remove(circuit_t *circ) { circuit_t *circuit_new(aci_t p_aci, connection_t *p_conn) { circuit_t *circ; + struct timeval now; + + if(gettimeofday(&now,NULL) < 0) + return NULL; circ = (circuit_t *)malloc(sizeof(circuit_t)); if(!circ) return NULL; memset(circ,0,sizeof(circuit_t)); /* zero it out */ + circ->timestamp_created = now.tv_sec; + circ->p_aci = p_aci; circ->p_conn = p_conn; @@ -252,20 +260,24 @@ circuit_t *circuit_get_by_conn(connection_t *conn) { return NULL; } -circuit_t *circuit_get_by_edge_type(char edge_type) { - circuit_t *circ; +circuit_t *circuit_get_newest_by_edge_type(char edge_type) { + circuit_t *circ, *bestcirc=NULL; for(circ=global_circuitlist;circ;circ = circ->next) { - if(edge_type == EDGE_AP && circ->n_conn && circ->n_conn->type == CONN_TYPE_OR) { - log(LOG_DEBUG,"circuit_get_by_edge_type(): Choosing n_aci %d.", circ->n_aci); - return circ; + if(edge_type == EDGE_AP && (!circ->p_conn || circ->p_conn->type == CONN_TYPE_AP)) { + if(!bestcirc || + (circ->state == CIRCUIT_STATE_OPEN && bestcirc->timestamp_created < circ->timestamp_created)) { + log(LOG_DEBUG,"circuit_get_newest_by_edge_type(): Choosing n_aci %d.", circ->n_aci); + bestcirc = circ; + } } - if(edge_type == EDGE_EXIT && circ->p_conn && circ->p_conn->type == CONN_TYPE_OR) { - return circ; + if(edge_type == EDGE_EXIT && (!circ->n_conn || circ->n_conn->type == CONN_TYPE_EXIT)) { + if(!bestcirc || + (circ->state == CIRCUIT_STATE_OPEN && bestcirc->timestamp_created < circ->timestamp_created)) + bestcirc = circ; } - log(LOG_DEBUG,"circuit_get_by_edge_type(): Skipping p_aci %d / n_aci %d.", circ->p_aci, circ->n_aci); } - return NULL; + return bestcirc; } int circuit_deliver_data_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type) { @@ -517,8 +529,11 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type) { void circuit_close(circuit_t *circ) { connection_t *conn; + circuit_t *youngest; assert(circ); + if(options.APPort) + youngest = circuit_get_newest_by_edge_type(EDGE_AP); circuit_remove(circ); for(conn=circ->n_conn; conn; conn=conn->next_topic) { connection_send_destroy(circ->n_aci, circ->n_conn); @@ -526,6 +541,11 @@ void circuit_close(circuit_t *circ) { for(conn=circ->p_conn; conn; conn=conn->next_topic) { connection_send_destroy(circ->p_aci, circ->p_conn); } + if(options.APPort && youngest == circ) { /* check this after we've sent the destroys, to reduce races */ + /* our current circuit just died. Launch another one pronto. */ + log(LOG_INFO,"circuit_close(): Youngest circuit dying. Launching a replacement."); + circuit_launch_new(1); + } circuit_free(circ); } @@ -610,6 +630,210 @@ void circuit_dump_by_conn(connection_t *conn) { } } +void circuit_expire_unused_circuits(void) { + circuit_t *circ, *tmpcirc; + circuit_t *youngest; + + youngest = circuit_get_newest_by_edge_type(EDGE_AP); + + circ = global_circuitlist; + while(circ) { + tmpcirc = circ; + circ = circ->next; + if(tmpcirc != youngest && (!tmpcirc->p_conn || tmpcirc->p_conn->type == CONN_TYPE_AP)) { + log(LOG_DEBUG,"circuit_expire_unused_circuits(): Closing n_aci %d",tmpcirc->n_aci); + circuit_close(tmpcirc); + } + } +} + +/* failure_status code: negative means reset failures to 0. Other values mean + * add that value to the current number of failures, then if we don't have too + * many failures on record, try to make a new circuit. + */ +void circuit_launch_new(int failure_status) { + static int failures=0; + + if(failure_status == -1) { /* I was called because a circuit succeeded */ + failures = 0; + return; + } + + failures += failure_status; + +retry_circuit: + + if(failures > 5) { + log(LOG_INFO,"circuit_launch_new(): Giving up, %d failures.", failures); + return; + } + + if(circuit_create_onion() < 0) { + failures++; + goto retry_circuit; + } + + failures = 0; + return; +} + +int circuit_create_onion(void) { + int i; + int routelen; /* length of the route */ + unsigned int *route; /* hops in the route as an array of indexes into rarray */ + unsigned char *onion; /* holds the onion */ + int onionlen; /* onion length in host order */ + crypt_path_t **cpath; /* defines the crypt operations that need to be performed on incoming/outgoing data */ + + /* choose a route */ + route = (unsigned int *)router_new_route(&routelen); + if (!route) { + log(LOG_ERR,"circuit_create_onion(): Error choosing a route through the OR network."); + return -1; + } + log(LOG_DEBUG,"circuit_create_onion(): Chosen a route of length %u : ",routelen); + + /* allocate memory for the crypt path */ + cpath = malloc(routelen * sizeof(crypt_path_t *)); + if (!cpath) { + log(LOG_ERR,"circuit_create_onion(): Error allocating memory for cpath."); + free(route); + return -1; + } + + /* create an onion and calculate crypto keys */ + onion = router_create_onion(route,routelen,&onionlen,cpath); + if (!onion) { + log(LOG_ERR,"circuit_create_onion(): Error creating an onion."); + free(route); + free(cpath); /* it's got nothing in it, since !onion */ + return -1; + } + log(LOG_DEBUG,"circuit_create_onion(): Created an onion of size %u bytes.",onionlen); + log(LOG_DEBUG,"circuit_create_onion(): Crypt path :"); + for (i=0;i<routelen;i++) { + log(LOG_DEBUG,"circuit_create_onion() : %u/%u",(cpath[i])->forwf, (cpath[i])->backf); + } + + return circuit_establish_circuit(route, routelen, onion, onionlen, cpath); +} + +int circuit_establish_circuit(unsigned int *route, int routelen, char *onion, + int onionlen, crypt_path_t **cpath) { + routerinfo_t *firsthop; + connection_t *n_conn; + circuit_t *circ; + + /* now see if we're already connected to the first OR in 'route' */ + firsthop = router_get_first_in_route(route, routelen); + assert(firsthop); /* should always be defined */ + free(route); /* we don't need it anymore */ + + circ = circuit_new(0, NULL); /* sets circ->p_aci and circ->p_conn */ + circ->state = CIRCUIT_STATE_OR_WAIT; + circ->onion = onion; + circ->onionlen = onionlen; + circ->cpath = cpath; + circ->cpathlen = routelen; + + log(LOG_DEBUG,"circuit_establish_circuit(): Looking for firsthop '%s:%u'", + firsthop->address,firsthop->or_port); + n_conn = connection_twin_get_by_addr_port(firsthop->addr,firsthop->or_port); + if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) { /* not currently connected */ + circ->n_addr = firsthop->addr; + circ->n_port = firsthop->or_port; + if(options.ORPort) { /* we would be connected if he were up. but he's not. */ + log(LOG_DEBUG,"circuit_establish_circuit(): Route's firsthop isn't connected."); + circuit_close(circ); + return -1; + } + + if(!n_conn) { /* launch the connection */ + n_conn = connection_or_connect_as_op(firsthop); + if(!n_conn) { /* connect failed, forget the whole thing */ + log(LOG_DEBUG,"circuit_establish_circuit(): connect to firsthop failed. Closing."); + circuit_close(circ); + return -1; + } + } + + return 0; /* return success. The onion/circuit/etc will be taken care of automatically + * (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN. + */ + } else { /* it (or a twin) is already open. use it. */ + circ->n_addr = n_conn->addr; + circ->n_port = n_conn->port; + return circuit_send_onion(n_conn, circ); + } +} + +/* find circuits that are waiting on me, if any, and get them to send the onion */ +void circuit_n_conn_open(connection_t *or_conn) { + circuit_t *circ; + + log(LOG_DEBUG,"circuit_n_conn_open(): Starting."); + circ = circuit_enumerate_by_naddr_nport(NULL, or_conn->addr, or_conn->port); + for(;;) { + if(!circ) + return; + + log(LOG_DEBUG,"circuit_n_conn_open(): Found circ, sending onion."); + if(circuit_send_onion(or_conn, circ) < 0) { + log(LOG_DEBUG,"circuit_n_conn_open(): circuit marked for closing."); + circuit_close(circ); + return; /* FIXME will want to try the other circuits too? */ + } + circ = circuit_enumerate_by_naddr_nport(circ, or_conn->addr, or_conn->port); + } +} + +int circuit_send_onion(connection_t *n_conn, circuit_t *circ) { + cell_t cell; + int tmpbuflen, dataleft; + char *tmpbuf; + + circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, ACI_TYPE_BOTH); + circ->n_conn = n_conn; + log(LOG_DEBUG,"circuit_send_onion(): n_conn is %s:%u",n_conn->address,n_conn->port); + + /* deliver the onion as one or more create cells */ + cell.command = CELL_CREATE; + cell.aci = circ->n_aci; + + tmpbuflen = circ->onionlen+4; + tmpbuf = malloc(tmpbuflen); + if(!tmpbuf) + return -1; + *(uint32_t*)tmpbuf = htonl(circ->onionlen); + memcpy(tmpbuf+4, circ->onion, circ->onionlen); + + dataleft = tmpbuflen; + while(dataleft) { + cell.command = CELL_CREATE; + cell.aci = circ->n_aci; + log(LOG_DEBUG,"circuit_send_onion(): Sending a create cell for the onion..."); + if(dataleft >= CELL_PAYLOAD_SIZE) { + cell.length = CELL_PAYLOAD_SIZE; + memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, CELL_PAYLOAD_SIZE); + connection_write_cell_to_buf(&cell, n_conn); + dataleft -= CELL_PAYLOAD_SIZE; + } else { /* last cell */ + cell.length = dataleft; + memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, dataleft); + /* fill extra space with 0 bytes */ + memset(cell.payload + dataleft, 0, CELL_PAYLOAD_SIZE - dataleft); + connection_write_cell_to_buf(&cell, n_conn); + dataleft = 0; + } + } + free(tmpbuf); + + circ->state = CIRCUIT_STATE_OPEN; + /* FIXME should set circ->expire to something here */ + + return 0; +} + /* Local Variables: mode:c diff --git a/src/or/config.c b/src/or/config.c index d8828bdd3..f6c0bda54 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -187,6 +187,7 @@ void config_assign(or_options_t *options, struct config_line *list) { config_compare(list, "DirFetchPeriod", CONFIG_TYPE_INT, &options->DirFetchPeriod) || config_compare(list, "KeepalivePeriod", CONFIG_TYPE_INT, &options->KeepalivePeriod) || config_compare(list, "MaxOnionsPending",CONFIG_TYPE_INT, &options->MaxOnionsPending) || + config_compare(list, "NewCircuitPeriod",CONFIG_TYPE_INT, &options->NewCircuitPeriod) || config_compare(list, "Daemon", CONFIG_TYPE_BOOL, &options->Daemon) || config_compare(list, "TrafficShaping", CONFIG_TYPE_BOOL, &options->TrafficShaping) || @@ -224,6 +225,7 @@ int getconfig(int argc, char **argv, or_options_t *options) { options->DirFetchPeriod = 600; options->KeepalivePeriod = 300; options->MaxOnionsPending = 10; + options->NewCircuitPeriod = 60; /* once a minute */ // options->ReconnectPeriod = 6001; /* get config lines from /etc/torrc and assign them */ diff --git a/src/or/connection_ap.c b/src/or/connection_ap.c index 831dd9b16..2a98537b8 100644 --- a/src/or/connection_ap.c +++ b/src/or/connection_ap.c @@ -4,8 +4,6 @@ #include "or.h" -extern or_options_t options; /* command-line and config-file options */ - int ap_handshake_process_socks(connection_t *conn) { char c; socks4_t socks4_info; @@ -96,211 +94,25 @@ int ap_handshake_process_socks(connection_t *conn) { } /* find the circuit that we should use, if there is one. */ - circ = circuit_get_by_edge_type(EDGE_AP); + circ = circuit_get_newest_by_edge_type(EDGE_AP); + circ->dirty = 1; /* now we're all ready to make an onion or send a begin */ - if(circ && circ->state == CIRCUIT_STATE_OPEN) { - /* FIXME if circ not yet open, figure out how to queue this begin? */ - /* add it into the linked list of topics on this circuit */ - log(LOG_DEBUG,"ap_handshake_process_socks(): attaching new conn to circ. n_aci %d.", circ->n_aci); - conn->next_topic = circ->p_conn; - circ->p_conn = conn; - - if(ap_handshake_send_begin(conn, circ) < 0) { - circuit_close(circ); - return -1; - } - } else { - if(ap_handshake_create_onion(conn) < 0) { - if(circ) - circuit_close(circ); - return -1; - } - } - return 0; -} - -int ap_handshake_create_onion(connection_t *conn) { - int i; - int routelen = 0; /* length of the route */ - unsigned int *route = NULL; /* hops in the route as an array of indexes into rarray */ - unsigned char *onion = NULL; /* holds the onion */ - int onionlen = 0; /* onion length in host order */ - crypt_path_t **cpath = NULL; /* defines the crypt operations that need to be performed on incoming/outgoing data */ - - assert(conn); - - /* choose a route */ - route = (unsigned int *)router_new_route(&routelen); - if (!route) { - log(LOG_ERR,"ap_handshake_create_onion(): Error choosing a route through the OR network."); + if(!circ) { + log(LOG_INFO,"ap_handshake_process_socks(): No circuit ready. Closing."); return -1; } - log(LOG_DEBUG,"ap_handshake_create_onion(): Chosen a route of length %u : ",routelen); -#if 0 - for (i=routelen-1;i>=0;i--) - { - log(LOG_DEBUG,"ap_handshake_process_ss() : %u : %s:%u, %u",routelen-i,(routerarray[route[i]])->address,ntohs((routerarray[route[i]])->port),RSA_size((routerarray[route[i]])->pkey)); - } -#endif - /* allocate memory for the crypt path */ - cpath = malloc(routelen * sizeof(crypt_path_t *)); - if (!cpath) { - log(LOG_ERR,"ap_handshake_create_onion(): Error allocating memory for cpath."); - free(route); - return -1; - } + /* add it into the linked list of topics on this circuit */ + log(LOG_DEBUG,"ap_handshake_process_socks(): attaching new conn to circ. n_aci %d.", circ->n_aci); + conn->next_topic = circ->p_conn; + circ->p_conn = conn; - /* create an onion and calculate crypto keys */ - onion = router_create_onion(route,routelen,&onionlen,cpath); - if (!onion) { - log(LOG_ERR,"ap_handshake_create_onion(): Error creating an onion."); - free(route); - free(cpath); /* it's got nothing in it, since !onion */ + if(ap_handshake_send_begin(conn, circ) < 0) { + circuit_close(circ); return -1; } - log(LOG_DEBUG,"ap_handshake_create_onion(): Created an onion of size %u bytes.",onionlen); - log(LOG_DEBUG,"ap_handshake_create_onion(): Crypt path :"); - for (i=0;i<routelen;i++) { - log(LOG_DEBUG,"ap_handshake_create_onion() : %u/%u",(cpath[i])->forwf, (cpath[i])->backf); - } - - return ap_handshake_establish_circuit(conn, route, routelen, onion, onionlen, cpath); -} - -int ap_handshake_establish_circuit(connection_t *conn, unsigned int *route, int routelen, char *onion, - int onionlen, crypt_path_t **cpath) { - routerinfo_t *firsthop; - connection_t *n_conn; - circuit_t *circ; - - /* now see if we're already connected to the first OR in 'route' */ - firsthop = router_get_first_in_route(route, routelen); - assert(firsthop); /* should always be defined */ - free(route); /* we don't need it anymore */ - - circ = circuit_new(0, conn); /* sets circ->p_aci and circ->p_conn */ - circ->state = CIRCUIT_STATE_OR_WAIT; - circ->onion = onion; - circ->onionlen = onionlen; - circ->cpath = cpath; - circ->cpathlen = routelen; - - log(LOG_DEBUG,"ap_handshake_establish_circuit(): Looking for firsthop '%s:%u'", - firsthop->address,firsthop->or_port); - n_conn = connection_twin_get_by_addr_port(firsthop->addr,firsthop->or_port); - if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) { /* not currently connected */ - circ->n_addr = firsthop->addr; - circ->n_port = firsthop->or_port; - if(options.ORPort) { /* we would be connected if he were up. but he's not. */ - log(LOG_DEBUG,"ap_handshake_establish_circuit(): Route's firsthop isn't connected."); - circuit_close(circ); - return -1; - } - - conn->state = AP_CONN_STATE_OR_WAIT; - connection_stop_reading(conn); /* Stop listening for input from the AP! */ - - if(!n_conn) { /* launch the connection */ - n_conn = connection_or_connect_as_op(firsthop); - if(!n_conn) { /* connect failed, forget the whole thing */ - log(LOG_DEBUG,"ap_handshake_establish_circuit(): connect to firsthop failed. Closing."); - circuit_close(circ); - return -1; - } - } - - return 0; /* return success. The onion/circuit/etc will be taken care of automatically - * (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN. - */ - } else { /* it (or a twin) is already open. use it. */ - circ->n_addr = n_conn->addr; - circ->n_port = n_conn->port; - return ap_handshake_send_onion(conn, n_conn, circ); - } -} - -/* find circuits that are waiting on me, if any, and get them to send the onion */ -void ap_handshake_n_conn_open(connection_t *or_conn) { - circuit_t *circ; - connection_t *p_conn; - - log(LOG_DEBUG,"ap_handshake_n_conn_open(): Starting."); - circ = circuit_enumerate_by_naddr_nport(NULL, or_conn->addr, or_conn->port); - for(;;) { - if(!circ) - return; - - p_conn = circ->p_conn; - if(p_conn->state != AP_CONN_STATE_OR_WAIT) { - log(LOG_WARNING,"Bug: ap_handshake_n_conn_open() got an ap_conn not in OR_WAIT state."); - } - connection_start_reading(p_conn); /* resume listening for reads */ - log(LOG_DEBUG,"ap_handshake_n_conn_open(): Found circ, sending onion."); - if(ap_handshake_send_onion(p_conn, or_conn, circ) < 0) { - log(LOG_DEBUG,"ap_handshake_n_conn_open(): circuit marked for closing."); - circuit_close(circ); - return; /* FIXME will want to try the other circuits too? */ - } - for(p_conn = p_conn->next_topic; p_conn; p_conn = p_conn->next_topic) { /* start up any other pending topics */ - if(ap_handshake_send_begin(p_conn, circ) < 0) { - circuit_close(circ); - return; - } - } - circ = circuit_enumerate_by_naddr_nport(circ, or_conn->addr, or_conn->port); - } -} - -int ap_handshake_send_onion(connection_t *ap_conn, connection_t *n_conn, circuit_t *circ) { - cell_t cell; - int tmpbuflen, dataleft; - char *tmpbuf; - - circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, ACI_TYPE_BOTH); - circ->n_conn = n_conn; - log(LOG_DEBUG,"ap_handshake_send_onion(): n_conn is %s:%u",n_conn->address,n_conn->port); - - /* deliver the onion as one or more create cells */ - cell.command = CELL_CREATE; - cell.aci = circ->n_aci; - - tmpbuflen = circ->onionlen+4; - tmpbuf = malloc(tmpbuflen); - if(!tmpbuf) - return -1; - *(uint32_t*)tmpbuf = htonl(circ->onionlen); - memcpy(tmpbuf+4, circ->onion, circ->onionlen); - - dataleft = tmpbuflen; - while(dataleft) { - cell.command = CELL_CREATE; - cell.aci = circ->n_aci; - log(LOG_DEBUG,"ap_handshake_send_onion(): Sending a create cell for the onion..."); - if(dataleft >= CELL_PAYLOAD_SIZE) { - cell.length = CELL_PAYLOAD_SIZE; - memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, CELL_PAYLOAD_SIZE); - connection_write_cell_to_buf(&cell, n_conn); - dataleft -= CELL_PAYLOAD_SIZE; - } else { /* last cell */ - cell.length = dataleft; - memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, dataleft); - /* fill extra space with 0 bytes */ - memset(cell.payload + dataleft, 0, CELL_PAYLOAD_SIZE - dataleft); - connection_write_cell_to_buf(&cell, n_conn); - dataleft = 0; - } - } - free(tmpbuf); - - if(ap_handshake_send_begin(ap_conn, circ) < 0) { - return -1; - } - - circ->state = CIRCUIT_STATE_OPEN; - /* FIXME should set circ->expire to something here */ return 0; } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 9cac2c9ca..15ad3839d 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -334,7 +334,7 @@ int or_handshake_op_finished_sending_keys(connection_t *conn) { conn_or_init_crypto(conn); connection_or_set_open(conn); - ap_handshake_n_conn_open(conn); /* send the pending onions */ + circuit_n_conn_open(conn); /* send the pending onion(s) */ return 0; } diff --git a/src/or/main.c b/src/or/main.c index 446603627..023836d4b 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -302,8 +302,10 @@ int prepare_for_poll(int *timeout) { struct timeval now; //soonest; static long current_second = 0; /* from previous calls to gettimeofday */ static long time_to_fetch_directory = 0; + static long time_to_new_circuit = 0; // int ms_until_conn; cell_t cell; + circuit_t *circ; if(gettimeofday(&now,NULL) < 0) return -1; @@ -321,6 +323,17 @@ int prepare_for_poll(int *timeout) { } } + if(options.APPort && time_to_new_circuit < now.tv_sec) { + circuit_expire_unused_circuits(); + circuit_launch_new(-1); /* tell it to forget about previous failures */ + circ = circuit_get_newest_by_edge_type(EDGE_AP); + if(!circ || circ->dirty) { + log(LOG_INFO,"prepare_for_poll(): Youngest circuit missing or dirty; launching replacement."); + circuit_launch_new(0); /* make an onion and lay the circuit */ + } + time_to_new_circuit = now.tv_sec + options.NewCircuitPeriod; + } + /* do housekeeping for each connection */ for(i=0;i<nfds;i++) { tmpconn = connection_array[i]; @@ -514,7 +527,7 @@ static void catch(int the_signal) { } } -void dumpstats (void) { /* dump stats to stdout */ +void dumpstats(void) { /* dump stats to stdout */ int i; connection_t *conn; struct timeval now; @@ -638,7 +651,7 @@ void dump_directory_to_string(char *s, int maxlen) { } -void daemonize() { +void daemonize(void) { /* Fork; parent exits. */ if (fork()) exit(0); diff --git a/src/or/onion.c b/src/or/onion.c index 6d920052a..d2cc6839b 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -337,9 +337,9 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r { int i, j; int num_acceptable_routers; - unsigned int *route = NULL; + unsigned int *route; unsigned int oldchoice, choice; - + assert((cw >= 0) && (cw < 1) && (rarray) && (routelen) ); /* valid parameters */ *routelen = chooselen(cw); @@ -351,6 +351,11 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r num_acceptable_routers = count_acceptable_routers(rarray, rarray_len); + if(num_acceptable_routers < 2) { + log(LOG_INFO,"new_route(): Not enough acceptable routers. Failing."); + return NULL; + } + if(num_acceptable_routers < *routelen) { log(LOG_DEBUG,"new_route(): Cutting routelen from %d to %d.",*routelen, num_acceptable_routers); *routelen = num_acceptable_routers; @@ -399,13 +404,16 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) { int i, j; int num=0; + connection_t *conn; for(i=0;i<rarray_len;i++) { log(LOG_DEBUG,"Contemplating whether router %d is a new option...",i); - if(options.ORPort && - !connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port)) { - log(LOG_DEBUG,"Nope, %d is not connected.",i); - goto next_i_loop; + if(options.ORPort) { + conn = connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port); + if(!conn || conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN) { + log(LOG_DEBUG,"Nope, %d is not connected.",i); + goto next_i_loop; + } } for(j=0;j<i;j++) { if(!crypto_pk_cmp_keys(rarray[i]->pkey, rarray[j]->pkey)) { diff --git a/src/or/or.h b/src/or/or.h index cc8f0461e..fcd3acff8 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -341,7 +341,7 @@ struct data_queue_t { struct data_queue_t *next; }; -/* per-anonymous-connection struct */ +/* struct for a path (circuit) through the network */ typedef struct { uint32_t n_addr; uint16_t n_port; @@ -365,6 +365,8 @@ typedef struct { int cpathlen; uint32_t expire; /* expiration time for the corresponding onion */ + long timestamp_created; + char dirty; /* whether this circuit has been used yet */ int state; @@ -381,20 +383,6 @@ struct onion_queue_t { struct onion_queue_t *next; }; -#if 0 -typedef struct -{ - int zero:1; - int version:7; - int backf:4; - int forwf:4; - uint16_t port; - uint32_t addr; - uint32_t expire; - unsigned char keyseed[16]; -} onion_layer_t; -#endif - #define ONION_LAYER_SIZE 28 #define ONION_PADDING_SIZE (128-ONION_LAYER_SIZE) @@ -415,11 +403,11 @@ typedef struct { int DirFetchPeriod; int KeepalivePeriod; int MaxOnionsPending; + int NewCircuitPeriod; int Role; int loglevel; } or_options_t; - /* all the function prototypes go here */ /********************************* buffers.c ***************************/ @@ -491,7 +479,7 @@ aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type); circuit_t *circuit_get_by_aci_conn(aci_t aci, connection_t *conn); circuit_t *circuit_get_by_conn(connection_t *conn); -circuit_t *circuit_get_by_edge_type(char edge_type); +circuit_t *circuit_get_newest_by_edge_type(char edge_type); circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *start, uint32_t naddr, uint16_t nport); int circuit_deliver_data_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type); @@ -506,8 +494,6 @@ int circuit_init(circuit_t *circ, int aci_type); void circuit_free(circuit_t *circ); void circuit_free_cpath(crypt_path_t **cpath, int cpathlen); - - void circuit_close(circuit_t *circ); void circuit_about_to_close_connection(connection_t *conn); @@ -515,6 +501,13 @@ void circuit_about_to_close_connection(connection_t *conn); void circuit_dump_by_conn(connection_t *conn); +void circuit_launch_new(int failure_status); +int circuit_create_onion(void); +int circuit_establish_circuit(unsigned int *route, int routelen, char *onion, + int onionlen, crypt_path_t **cpath); +void circuit_n_conn_open(connection_t *or_conn); +int circuit_send_onion(connection_t *or_conn, circuit_t *circ); + /********************************* command.c ***************************/ void command_process_cell(cell_t *cell, connection_t *conn); @@ -611,14 +604,6 @@ int connection_finished_flushing(connection_t *conn); int ap_handshake_process_socks(connection_t *conn); -int ap_handshake_create_onion(connection_t *conn); - -int ap_handshake_establish_circuit(connection_t *conn, unsigned int *route, int routelen, char *onion, - int onionlen, crypt_path_t **cpath); - -void ap_handshake_n_conn_open(connection_t *or_conn); - -int ap_handshake_send_onion(connection_t *ap_conn, connection_t *or_conn, circuit_t *circ); int ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ); int ap_handshake_socks_reply(connection_t *conn, char result); diff --git a/src/or/test.c b/src/or/test.c index 5453f4b18..3ff3fb6f6 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -182,7 +182,7 @@ test_buffers() { j = decompress_buf_to_buf(&buf, &buflen, &buf_datalen, &buf2, &buf2len, &buf2_datalen, decomp, 1); - /*XXXX check result * + /*XXXX check result */ /* Now compress more, into less room. */ for (i = 0; i < 20; ++i) { |