[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] incremental path building in; uses ephemeral DH; onions are...
- To: or-cvs@freehaven.net
- Subject: [or-cvs] incremental path building in; uses ephemeral DH; onions are...
- From: arma@seul.org (Roger Dingledine)
- Date: Mon, 5 May 2003 19:24:48 -0400 (EDT)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Mon, 05 May 2003 19:24:58 -0400
- Reply-to: or-dev@freehaven.net
- Sender: owner-or-cvs@freehaven.net
Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home/arma/work/onion/cvs/src/or
Modified Files:
circuit.c command.c connection.c connection_edge.c main.c
onion.c or.h routers.c
Log Message:
incremental path building in; uses ephemeral DH; onions are gone
still need to change circuit-level sendmes
Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- circuit.c 2 May 2003 21:29:25 -0000 1.41
+++ circuit.c 5 May 2003 23:24:45 -0000 1.42
@@ -65,7 +65,7 @@
circ->p_aci = p_aci;
circ->p_conn = p_conn;
- circ->state = CIRCUIT_STATE_ONION_WAIT;
+ circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
/* ACIs */
circ->p_aci = p_aci;
@@ -87,8 +87,6 @@
if (circ->p_crypto)
crypto_free_cipher_env(circ->p_crypto);
- if(circ->onion)
- free(circ->onion);
circuit_free_cpath(circ->cpath);
while(circ->relay_queue) {
tmpd = circ->relay_queue;
@@ -122,6 +120,8 @@
crypto_free_cipher_env(victim->f_crypto);
if(victim->b_crypto)
crypto_free_cipher_env(victim->b_crypto);
+ if(victim->handshake_state)
+ crypto_dh_free(victim->handshake_state);
free(victim);
}
@@ -155,66 +155,6 @@
return test_aci;
}
-int circuit_init(circuit_t *circ, int aci_type, onion_layer_t *layer) {
- unsigned char iv[16];
- unsigned char digest1[20];
- unsigned char digest2[20];
- struct timeval start, end;
- long time_passed;
-
- assert(circ && circ->onion);
-
- log(LOG_DEBUG,"circuit_init(): starting");
- circ->n_port = layer->port;
- log(LOG_DEBUG,"circuit_init(): Set port to %u.",circ->n_port);
- circ->n_addr = layer->addr;
- circ->state = CIRCUIT_STATE_OPEN;
-
- log(LOG_DEBUG,"circuit_init(): aci_type = %u.",aci_type);
-
- my_gettimeofday(&start);
-
- circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, aci_type);
- if(!circ->n_aci) {
- log(LOG_ERR,"circuit_init(): failed to get unique aci.");
- return -1;
- }
-
- my_gettimeofday(&end);
-
- time_passed = tv_udiff(&start, &end);
- if (time_passed > 1000) {/* more than 1ms */
- log(LOG_NOTICE,"circuit_init(): get_unique_aci just took %d us!",time_passed);
- }
-
- log(LOG_DEBUG,"circuit_init(): Chosen ACI %u.",circ->n_aci);
-
- /* keys */
- memset(iv, 0, 16);
- crypto_SHA_digest(layer->keyseed,16,digest1);
- crypto_SHA_digest(digest1,20,digest2);
- crypto_SHA_digest(digest2,20,digest1);
- log(LOG_DEBUG,"circuit_init(): Computed keys.");
-
- if (!(circ->p_crypto =
- crypto_create_init_cipher(DEFAULT_CIPHER,digest2,iv,1))) {
- log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci);
- return -1;
- }
-
- if (!(circ->n_crypto =
- crypto_create_init_cipher(DEFAULT_CIPHER,digest1,iv,0))) {
- log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci);
- return -1;
- }
-
- log(LOG_DEBUG,"circuit_init(): Cipher initialization complete.");
-
- circ->expire = layer->expire;
-
- return 0;
-}
-
circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *circ, uint32_t naddr, uint16_t nport) {
if(!circ) /* use circ if it's defined, else start from the beginning */
@@ -269,13 +209,11 @@
circuit_t *circ, *bestcirc=NULL;
for(circ=global_circuitlist;circ;circ = circ->next) {
- if(!circ->p_conn || circ->p_conn->type == CONN_TYPE_AP) {
- if(circ->state == CIRCUIT_STATE_OPEN && (!bestcirc ||
- bestcirc->timestamp_created < circ->timestamp_created)) {
- log(LOG_DEBUG,"circuit_get_newest_ap(): Choosing n_aci %d.", circ->n_aci);
- assert(circ->n_aci);
- bestcirc = circ;
- }
+ if(circ->cpath && circ->state == CIRCUIT_STATE_OPEN && (!bestcirc ||
+ bestcirc->timestamp_created < circ->timestamp_created)) {
+ log(LOG_DEBUG,"circuit_get_newest_ap(): Choosing n_aci %d.", circ->n_aci);
+ assert(circ->n_aci);
+ bestcirc = circ;
}
}
return bestcirc;
@@ -331,7 +269,7 @@
buf[0] = cell->length;
memcpy(buf+1, cell->payload, CELL_PAYLOAD_SIZE);
- log(LOG_DEBUG,"circuit_deliver_relay_cell(): streamid %d before crypt.", *(int*)(cell->payload+1));
+ log(LOG_DEBUG,"circuit_deliver_relay_cell(): direction %d, streamid %d before crypt.", cell_direction, *(int*)(cell->payload+1));
if(relay_crypt(circ, buf, 1+CELL_PAYLOAD_SIZE, cell_direction, layer_hint, &recognized, &conn) < 0) {
log(LOG_DEBUG,"circuit_deliver_relay_cell(): relay crypt failed. Dropping connection.");
@@ -363,6 +301,7 @@
return 0;
}
+ log(LOG_DEBUG,"circuit_deliver_relay_cell(): Passing on unrecognized cell.");
return connection_write_cell_to_buf(cell, conn);
}
@@ -378,32 +317,42 @@
if(cell_direction == CELL_DIRECTION_IN) {
if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */
thishop = circ->cpath;
+ if(thishop->state != CPATH_STATE_OPEN) {
+ log(LOG_INFO,"relay_crypt(): Relay cell before first created cell?");
+ return -1;
+ }
do { /* Remember: cpath is in forward order, that is, first hop first. */
assert(thishop);
+ log(LOG_DEBUG,"relay_crypt(): before decrypt: %d",*(int*)(in+2));
/* decrypt */
if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) {
log(LOG_ERR,"Error performing decryption:%s",crypto_perror());
return -1;
}
memcpy(in,out,inlen);
+ log(LOG_DEBUG,"relay_crypt(): after decrypt: %d",*(int*)(in+2));
if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn)))
return 0;
thishop = thishop->next;
- } while(thishop != circ->cpath);
+ } while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
log(LOG_INFO,"relay_crypt(): in-cell at OP not recognized. Killing circuit.");
- return -1;
+ return 0;
+// return -1;
} else { /* we're in the middle. Just one crypt. */
+ log(LOG_DEBUG,"relay_crypt(): before encrypt: %d",*(int*)(in+2));
if(crypto_cipher_encrypt(circ->p_crypto, in, inlen, out)) {
log(LOG_ERR,"circuit_encrypt(): Encryption failed for ACI : %u (%s).",
circ->p_aci, crypto_perror());
return -1;
}
memcpy(in,out,inlen);
+ log(LOG_DEBUG,"relay_crypt(): after encrypt: %d",*(int*)(in+2));
+ log(LOG_DEBUG,"circuit_encrypt(): Skipping recognized check, because we're not the OP.");
/* don't check for recognized. only the OP can recognize a stream on the way back. */
}
@@ -415,12 +364,13 @@
do {
assert(thishop);
- /* encrypt */
+ log(LOG_DEBUG,"relay_crypt(): before encrypt: %d",*(int*)(in+2));
if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, out)) {
log(LOG_ERR,"Error performing encryption:%s",crypto_perror());
return -1;
}
memcpy(in,out,inlen);
+ log(LOG_DEBUG,"relay_crypt(): after encrypt: %d",*(int*)(in+2));
thishop = thishop->prev;
} while(thishop != circ->cpath->prev);
@@ -450,8 +400,10 @@
connection_t *tmpconn;
log(LOG_DEBUG,"relay_check_recognized(): entering");
- if(!memcmp(stream,ZERO_STREAM,STREAM_ID_SIZE))
+ if(!memcmp(stream,ZERO_STREAM,STREAM_ID_SIZE)) {
+ log(LOG_DEBUG,"relay_check_recognized(): It's the zero stream. Recognized.");
return 1; /* the zero stream is always recognized */
+ }
if(cell_direction == CELL_DIRECTION_OUT)
tmpconn = circ->n_conn;
@@ -459,8 +411,10 @@
tmpconn = circ->p_conn;
log(LOG_DEBUG,"relay_check_recognized(): not the zero stream.");
- if(!tmpconn)
+ if(!tmpconn) {
+ log(LOG_DEBUG,"relay_check_recognized(): No conns. Not recognized.");
return 0; /* no conns? don't recognize it */
+ }
while(tmpconn && tmpconn->type == CONN_TYPE_OR) {
log(LOG_DEBUG,"relay_check_recognized(): skipping over an OR conn");
@@ -723,7 +677,7 @@
return;
}
- if(circuit_create_onion() < 0) {
+ if(circuit_establish_circuit() < 0) {
failures++;
goto retry_circuit;
}
@@ -732,50 +686,21 @@
return;
}
-int circuit_create_onion(void) {
- 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);
-
- /* 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);
- return -1;
- }
- log(LOG_DEBUG,"circuit_create_onion(): Created an onion of size %u bytes.",onionlen);
-// log(LOG_DEBUG,"circuit_create_onion(): Crypt path :");
-
- 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) {
+int circuit_establish_circuit(void) {
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->cpath = onion_generate_cpath(&firsthop);
+ if(!circ->cpath) {
+ log(LOG_DEBUG,"circuit_establish_circuit(): Generating cpath failed.");
+ circuit_close(circ);
+ return -1;
+ }
+
+ /* now see if we're already connected to the first OR in 'route' */
log(LOG_DEBUG,"circuit_establish_circuit(): Looking for firsthop '%s:%u'",
firsthop->address,firsthop->or_port);
@@ -798,14 +723,22 @@
}
}
+ log(LOG_DEBUG,"circuit_establish_circuit(): connecting in progress (or finished). Good.");
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);
+ circ->n_conn = n_conn;
+ log(LOG_DEBUG,"circuit_establish_circuit(): Conn open. Delivering first onion skin.");
+ if(circuit_send_next_onion_skin(circ) < 0) {
+ log(LOG_DEBUG,"circuit_establish_circuit(): circuit_send_next_onion_skin failed.");
+ circuit_close(circ);
+ return -1;
+ }
}
+ return 0;
}
/* find circuits that are waiting on me, if any, and get them to send the onion */
@@ -818,8 +751,9 @@
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(): Found circ, sending onion skin.");
+ circ->n_conn = or_conn;
+ if(circuit_send_next_onion_skin(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? */
@@ -828,50 +762,182 @@
}
}
-int circuit_send_onion(connection_t *n_conn, circuit_t *circ) {
+int circuit_send_next_onion_skin(circuit_t *circ) {
cell_t cell;
- int tmpbuflen, dataleft;
- char *tmpbuf;
+ crypt_path_t *hop;
+ routerinfo_t *router;
- 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);
+ assert(circ && circ->cpath);
- /* deliver the onion as one or more create cells */
- cell.command = CELL_CREATE;
- cell.aci = circ->n_aci;
+ if(circ->cpath->state == CPATH_STATE_CLOSED) {
- tmpbuflen = circ->onionlen+4;
- tmpbuf = malloc(tmpbuflen);
- if(!tmpbuf)
- return -1;
- *(uint32_t*)tmpbuf = htonl(circ->onionlen);
- memcpy(tmpbuf+4, circ->onion, circ->onionlen);
+ log(LOG_DEBUG,"circuit_send_next_onion_skin(): First skin; sending create cell.");
+ circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, ACI_TYPE_BOTH);
- dataleft = tmpbuflen;
- while(dataleft) {
+ memset(&cell, 0, sizeof(cell_t));
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;
+ cell.length = 208;
+
+ if(onion_skin_create(circ->n_conn->pkey, &(circ->cpath->handshake_state), cell.payload) < 0) {
+ log(LOG_INFO,"circuit_send_next_onion_skin(): onion_skin_create (first hop) failed.");
+ return -1;
+ }
+
+ if(connection_write_cell_to_buf(&cell, circ->n_conn) < 0) {
+ return -1;
+ }
+
+ circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
+ circ->state = CIRCUIT_STATE_BUILDING;
+ log(LOG_DEBUG,"circuit_send_next_onion_skin(): first skin; finished sending create cell.");
+ } else {
+ assert(circ->cpath->state == CPATH_STATE_OPEN);
+ assert(circ->state == CIRCUIT_STATE_BUILDING);
+ log(LOG_DEBUG,"circuit_send_next_onion_skin(): starting to send subsequent skin.");
+ for(hop=circ->cpath->next;
+ hop != circ->cpath && hop->state == CPATH_STATE_OPEN;
+ hop=hop->next) ;
+ if(hop == circ->cpath) { /* done building the circuit. whew. */
+ circ->state = CIRCUIT_STATE_OPEN;
+ log(LOG_DEBUG,"circuit_send_next_onion_skin(): circuit built!");
+ return 0;
+ }
+
+ router = router_get_by_addr_port(hop->addr,hop->port);
+ if(!router) {
+ log(LOG_INFO,"circuit_send_next_onion_skin(): couldn't lookup router %d:%d",hop->addr,hop->port);
+ return -1;
+ }
+
+ memset(&cell, 0, sizeof(cell_t));
+ cell.command = CELL_RELAY;
+ cell.aci = circ->n_aci;
+ SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_EXTEND);
+ SET_CELL_STREAM_ID(cell, ZERO_STREAM);
+
+ cell.length = RELAY_HEADER_SIZE + 6 + 208;
+ *(uint32_t*)(cell.payload+RELAY_HEADER_SIZE) = htonl(hop->addr);
+ *(uint32_t*)(cell.payload+RELAY_HEADER_SIZE+4) = htons(hop->port);
+ if(onion_skin_create(router->pkey, &(hop->handshake_state), cell.payload+RELAY_HEADER_SIZE+6) < 0) {
+ log(LOG_INFO,"circuit_send_next_onion_skin(): onion_skin_create failed.");
+ return -1;
}
+
+ log(LOG_DEBUG,"circuit_send_next_onion_skin(): Sending extend relay cell.");
+ /* send it to hop->prev, because it will transfer it to a create cell and then send to hop */
+ if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, hop->prev) < 0) {
+ log(LOG_DEBUG,"circuit_send_next_onion_skin(): failed to deliver extend cell. Closing.");
+ return -1;
+ }
+ hop->state = CPATH_STATE_AWAITING_KEYS;
}
- free(tmpbuf);
+ return 0;
+}
- circ->state = CIRCUIT_STATE_OPEN;
- /* FIXME should set circ->expire to something here */
+/* take the 'extend' cell, pull out addr/port plus the onion skin. Connect
+ * to the next hop, and pass it the onion skin in a create cell.
+ */
+int circuit_extend(cell_t *cell, circuit_t *circ) {
+ connection_t *n_conn;
+ aci_t aci_type;
+ struct sockaddr_in me; /* my router identity */
+ cell_t newcell;
+
+ circ->n_addr = ntohl(*(uint32_t*)(cell->payload+RELAY_HEADER_SIZE));
+ circ->n_port = ntohs(*(uint16_t*)(cell->payload+RELAY_HEADER_SIZE+4));
+
+ if(learn_my_address(&me) < 0)
+ return -1;
+
+ n_conn = connection_twin_get_by_addr_port(circ->n_addr,circ->n_port);
+ if(!n_conn || n_conn->type != CONN_TYPE_OR) {
+ /* i've disabled making connections through OPs, but it's definitely
+ * possible here. I'm not sure if it would be a bug or a feature. -RD
+ */
+ /* note also that this will close circuits where the onion has the same
+ * router twice in a row in the path. i think that's ok. -RD
+ */
+ log(LOG_DEBUG,"circuit_extend(): Next router not connected. Closing.");
+ /* XXX later we should fail more gracefully here, like with a 'truncated' */
+ return -1;
+ }
+
+ circ->n_addr = n_conn->addr; /* these are different if we found a twin instead */
+ circ->n_port = n_conn->port;
+
+ circ->n_conn = n_conn;
+ log(LOG_DEBUG,"circuit_extend(): n_conn is %s:%u",n_conn->address,n_conn->port);
+
+ aci_type = decide_aci_type(ntohl(me.sin_addr.s_addr), ntohs(me.sin_port),
+ circ->n_addr, circ->n_port);
+
+ log(LOG_DEBUG,"circuit_extend(): aci_type = %u.",aci_type);
+ circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, aci_type);
+ if(!circ->n_aci) {
+ log(LOG_ERR,"circuit_extend(): failed to get unique aci.");
+ return -1;
+ }
+ log(LOG_DEBUG,"circuit_extend(): Chosen ACI %u.",circ->n_aci);
+
+ memset(&newcell, 0, sizeof(cell_t));
+ newcell.command = CELL_CREATE;
+ newcell.aci = circ->n_aci;
+ newcell.length = 208;
+
+ memcpy(newcell.payload, cell->payload+RELAY_HEADER_SIZE+6, 208);
+
+ if(connection_write_cell_to_buf(&newcell, circ->n_conn) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int circuit_finish_handshake(circuit_t *circ, char *reply) {
+ unsigned char iv[16];
+ unsigned char keys[32];
+ crypt_path_t *hop;
+
+ memset(iv, 0, 16);
+
+ assert(circ->cpath);
+ if(circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
+ hop = circ->cpath;
+ else {
+ for(hop=circ->cpath->next;
+ hop != circ->cpath && hop->state == CPATH_STATE_OPEN;
+ hop=hop->next) ;
+ if(hop == circ->cpath) { /* got an extended when we're all done? */
+ log(LOG_INFO,"circuit_finish_handshake(): got extended when circ already built? Weird.");
+ return 0;
+ }
+ }
+ assert(hop->state == CPATH_STATE_AWAITING_KEYS);
+ if(onion_skin_client_handshake(hop->handshake_state, reply, keys, 32) < 0) {
+ log(LOG_ERR,"circuit_finish_handshake(): onion_skin_client_handshake failed.");
+ return -1;
+ }
+
+ crypto_dh_free(hop->handshake_state); /* don't need it anymore */
+ hop->handshake_state = NULL;
+
+ log(LOG_DEBUG,"circuit_finish_handshake(): hop %d init cipher forward %d, backward %d.", hop, *(int*)keys, *(int*)(keys+16));
+ if (!(hop->f_crypto =
+ crypto_create_init_cipher(DEFAULT_CIPHER,keys,iv,1))) {
+ log(LOG_ERR,"Cipher initialization failed.");
+ return -1;
+ }
+
+ if (!(hop->b_crypto =
+ crypto_create_init_cipher(DEFAULT_CIPHER,keys+16,iv,0))) {
+ log(LOG_ERR,"Cipher initialization failed.");
+ return -1;
+ }
+
+ hop->state = CPATH_STATE_OPEN;
+ log(LOG_DEBUG,"circuit_finish_handshake(): Completed.");
return 0;
}
Index: command.c
===================================================================
RCS file: /home/or/cvsroot/src/or/command.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- command.c 2 May 2003 21:29:25 -0000 1.26
+++ command.c 5 May 2003 23:24:45 -0000 1.27
@@ -28,8 +28,8 @@
}
void command_process_cell(cell_t *cell, connection_t *conn) {
- static int num_create=0, num_relay=0, num_destroy=0, num_sendme=0;
- static int create_time=0, relay_time=0, destroy_time=0, sendme_time=0;
+ static int num_create=0, num_created=0, num_relay=0, num_destroy=0, num_sendme=0;
+ static int create_time=0, created_time=0, relay_time=0, destroy_time=0, sendme_time=0;
static long current_second = 0; /* from previous calls to gettimeofday */
struct timeval now;
@@ -39,18 +39,20 @@
/* print stats */
log(LOG_INFO,"At end of second:");
log(LOG_INFO,"Create: %d (%d ms)", num_create, create_time/1000);
+ log(LOG_INFO,"Created: %d (%d ms)", num_created, created_time/1000);
log(LOG_INFO,"Relay: %d (%d ms)", num_relay, relay_time/1000);
log(LOG_INFO,"Destroy: %d (%d ms)", num_destroy, destroy_time/1000);
log(LOG_INFO,"Sendme: %d (%d ms)", num_sendme, sendme_time/1000);
/* zero out stats */
- num_create = num_relay = num_destroy = num_sendme = 0;
- create_time = relay_time = destroy_time = sendme_time = 0;
+ num_create = num_created = num_relay = num_destroy = num_sendme = 0;
+ create_time = created_time = relay_time = destroy_time = sendme_time = 0;
/* remember which second it is, for next time */
current_second = now.tv_sec;
}
+ log(LOG_DEBUG,"command_process_cell(): Examining cell type %d.", cell->command);
switch(cell->command) {
case CELL_PADDING:
/* do nothing */
@@ -59,6 +61,10 @@
command_time_process_cell(cell, conn, &num_create, &create_time,
command_process_create_cell);
break;
+ case CELL_CREATED:
+ command_time_process_cell(cell, conn, &num_created, &created_time,
+ command_process_created_cell);
+ break;
case CELL_RELAY:
command_time_process_cell(cell, conn, &num_relay, &relay_time,
command_process_relay_cell);
@@ -82,60 +88,76 @@
circ = circuit_get_by_aci_conn(cell->aci, conn);
- if(circ && circ->state != CIRCUIT_STATE_ONION_WAIT) {
- log(LOG_DEBUG,"command_process_create_cell(): received CREATE cell, not in onion_wait. Dropping.");
+ if(circ) {
+ log(LOG_DEBUG,"command_process_create_cell(): received CREATE cell for known circ. Dropping.");
return;
}
- if(!circ) { /* if it's not there, create it */
- circ = circuit_new(cell->aci, conn);
- circ->state = CIRCUIT_STATE_ONION_WAIT;
- circ->onionlen = ntohl(*(int*)cell->payload);
- log(LOG_DEBUG,"command_process_create_cell(): Onion length is %u.",circ->onionlen);
- if(circ->onionlen > 50000 || circ->onionlen < 1) { /* too big or too small */
- log(LOG_DEBUG,"That's ludicrous. Closing.");
- circuit_close(circ);
- return;
- }
- circ->onion = malloc(circ->onionlen);
- if(!circ->onion) {
- log(LOG_DEBUG,"command_process_create_cell(): Out of memory. Closing.");
+ circ = circuit_new(cell->aci, conn);
+ circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
+ if(cell->length != 208) {
+ log(LOG_DEBUG,"command_process_create_cell(): Bad cell length %d. Dropping.", cell->length);
+ circuit_close(circ);
+ return;
+ }
+
+ memcpy(circ->onionskin,cell->payload,cell->length);
+
+ /* add it to the pending onions queue, and then return */
+ if(onion_pending_add(circ) < 0) {
+ log(LOG_DEBUG,"command_process_create_cell(): Failed to queue onionskin. Closing.");
+ circuit_close(circ);
+ }
+ log(LOG_DEBUG,"command_process_create_cell(): success: queued onionskin.");
+ return;
+}
+
+void command_process_created_cell(cell_t *cell, connection_t *conn) {
+ circuit_t *circ;
+ cell_t newcell;
+
+ circ = circuit_get_by_aci_conn(cell->aci, conn);
+
+ if(!circ) {
+ log(LOG_DEBUG,"command_process_created_cell(): received CREATED cell for unknown circ. Dropping.");
+ return;
+ }
+
+ if(circ->n_aci != cell->aci) {
+ log(LOG_DEBUG,"command_process_created_cell(): got created cell from OPward? Dropping.");
+ return;
+ }
+ assert(cell->length == 192);
+
+ if(circ->cpath) { /* we're the OP. Handshake this. */
+ log(LOG_DEBUG,"command_process_created_cell(): at OP. Finishing handshake.");
+ if(circuit_finish_handshake(circ, cell->payload) < 0) {
+ log(LOG_INFO,"command_process_created_cell(): circuit_finish_handshake failed.");
circuit_close(circ);
return;
}
- if(circ->onionlen < cell->length-4) { /* protect from buffer overflow */
- log(LOG_DEBUG,"command_process_create_cell(): Onion too small. Closing.");
+ log(LOG_DEBUG,"command_process_created_cell(): Moving to next skin.");
+ if(circuit_send_next_onion_skin(circ) < 0) {
+ log(LOG_INFO,"command_process_created_cell(): circuit_send_next_onion_skin failed.");
circuit_close(circ);
return;
}
- memcpy((void *)circ->onion,(void *)(cell->payload+4),cell->length-4);
- circ->recvlen = cell->length-4;
- log(LOG_DEBUG,"command_process_create_cell(): Primary create cell handled, have received %d of %d onion bytes.",
- circ->recvlen,circ->onionlen);
+ } else { /* pack it into an extended relay cell, and send it. */
+ memset(&newcell, 0, sizeof(cell_t));
+ newcell.command = CELL_RELAY;
+ newcell.aci = circ->p_aci;
+ SET_CELL_RELAY_COMMAND(newcell, RELAY_COMMAND_EXTENDED);
+ SET_CELL_STREAM_ID(newcell, ZERO_STREAM);
- } else { /* pull over as much of the onion as we can */
- if(cell->length + circ->recvlen > circ->onionlen) { /* protect from buffer overflow */
- log(LOG_DEBUG,"command_process_create_cell(): payload too big for onion. Closing.");
+ newcell.length = RELAY_HEADER_SIZE + cell->length;
+ memcpy(newcell.payload+RELAY_HEADER_SIZE, cell->payload, 192);
+
+ log(LOG_DEBUG,"command_process_created_cell(): Sending extended relay cell.");
+ if(circuit_deliver_relay_cell_from_edge(&newcell, circ, EDGE_EXIT, NULL) < 0) {
+ log(LOG_DEBUG,"command_process_created_cell(): failed to deliver extended cell. Closing.");
circuit_close(circ);
return;
}
- memcpy((void *)(circ->onion+circ->recvlen),(void *)cell->payload,cell->length);
- circ->recvlen += cell->length;
- log(LOG_DEBUG,"command_process_create_cell(): Secondary create cell handled, have received %d of %d onion bytes (aci %d)",
- circ->recvlen,circ->onionlen,circ->p_aci);
- }
-
- if(circ->recvlen != circ->onionlen) {
- log(LOG_DEBUG,"command_process_create_cell(): Onion not all here yet. Ok.");
- return;
- }
-
- /* add it to the pending onions queue, and then return */
- circ->state = CIRCUIT_STATE_ONION_PENDING;
-
- if(onion_pending_add(circ) < 0) {
- log(LOG_DEBUG,"command_process_create_cell(): Failed to queue onion. Closing.");
- circuit_close(circ);
}
return;
}
@@ -150,6 +172,7 @@
return;
}
+#if 0
if(circ->state == CIRCUIT_STATE_ONION_WAIT) {
log(LOG_DEBUG,"command_process_sendme_cell(): circuit in onion_wait. Dropping.");
return;
@@ -158,6 +181,7 @@
log(LOG_DEBUG,"command_process_sendme_cell(): circuit in or_wait. Dropping.");
return;
}
+#endif
/* at this point both circ->n_conn and circ->p_conn are guaranteed to be set */
@@ -205,7 +229,7 @@
return;
}
- if(circ->state == CIRCUIT_STATE_ONION_PENDING) {
+ if(circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
log(LOG_DEBUG,"command_process_relay_cell(): circuit in create_wait. Queueing relay cell.");
onion_pending_relay_add(circ, cell);
return;
@@ -213,22 +237,23 @@
if(cell->aci == circ->p_aci) { /* it's an outgoing cell */
if(--circ->p_receive_circwindow < 0) { /* is it less than 0 after decrement? */
- log(LOG_INFO,"connection_process_relay_cell(): Too many relay cells for out circuit (aci %d). Closing.", circ->p_aci);
+ log(LOG_INFO,"command_process_relay_cell(): Too many relay cells for out circuit (aci %d). Closing.", circ->p_aci);
circuit_close(circ);
return;
}
- log(LOG_DEBUG,"connection_process_relay_cell(): p_receive_circwindow for aci %d is %d.",circ->p_aci,circ->p_receive_circwindow);
+ log(LOG_DEBUG,"command_process_relay_cell(): p_receive_circwindow for aci %d is %d.",circ->p_aci,circ->p_receive_circwindow);
}
if(cell->aci == circ->n_aci) { /* it's an ingoing cell */
if(--circ->n_receive_circwindow < 0) { /* is it less than 0 after decrement? */
- log(LOG_INFO,"connection_process_relay_cell(): Too many relay cells for in circuit (aci %d). Closing.", circ->n_aci);
+ log(LOG_INFO,"command_process_relay_cell(): Too many relay cells for in circuit (aci %d). Closing.", circ->n_aci);
circuit_close(circ);
return;
}
- log(LOG_DEBUG,"connection_process_relay_cell(): n_receive_circwindow for aci %d is %d.",circ->n_aci,circ->n_receive_circwindow);
+ log(LOG_DEBUG,"command_process_relay_cell(): n_receive_circwindow for aci %d is %d.",circ->n_aci,circ->n_receive_circwindow);
}
+#if 0
if(circ->state == CIRCUIT_STATE_ONION_WAIT) {
log(LOG_WARNING,"command_process_relay_cell(): circuit in onion_wait. Dropping relay cell.");
return;
@@ -237,6 +262,7 @@
log(LOG_WARNING,"command_process_relay_cell(): circuit in or_wait. Dropping relay cell.");
return;
}
+#endif
/* circ->p_conn and n_conn are only null if we're at an edge point with no connections yet */
if(cell->aci == circ->p_aci) { /* it's an outgoing cell */
@@ -267,7 +293,7 @@
}
log(LOG_DEBUG,"command_process_destroy_cell(): Received for aci %d.",cell->aci);
- if(circ->state == CIRCUIT_STATE_ONION_PENDING) {
+ if(circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
onion_pending_remove(circ);
}
Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -d -r1.59 -r1.60
--- connection.c 2 May 2003 21:29:25 -0000 1.59
+++ connection.c 5 May 2003 23:24:45 -0000 1.60
@@ -607,6 +607,8 @@
printf("\n");
#endif
+ assert(conn);
+
if(crypto_cipher_encrypt(conn->f_crypto, cellp, CELL_NETWORK_SIZE, cryptcell)) {
log(LOG_ERR,"Could not encrypt cell for connection %s:%u.",conn->address,conn->port);
return -1;
Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- connection_edge.c 2 May 2003 21:29:25 -0000 1.7
+++ connection_edge.c 5 May 2003 23:24:45 -0000 1.8
@@ -23,7 +23,7 @@
circ = circuit_get_by_conn(conn);
if (!circ)
return -1;
-
+
memset(&cell, 0, sizeof(cell_t));
cell.command = CELL_RELAY;
cell.length = RELAY_HEADER_SIZE;
@@ -123,13 +123,12 @@
if(edge_type == EDGE_AP) {
log(LOG_INFO,"connection_edge_process_relay_cell(): relay begin request unsupported. Dropping.");
return 0;
- } else {
- if(conn) {
- log(LOG_INFO,"connection_edge_process_relay_cell(): begin cell for known stream. Dropping.");
- return 0;
- }
- return connection_exit_begin_conn(cell, circ);
}
+ if(conn) {
+ log(LOG_INFO,"connection_edge_process_relay_cell(): begin cell for known stream. Dropping.");
+ return 0;
+ }
+ return connection_exit_begin_conn(cell, circ);
case RELAY_COMMAND_DATA:
if(!conn) {
log(LOG_DEBUG,"connection_edge_process_relay_cell(): relay cell dropped, unknown stream %d.",*(int*)conn->stream_id);
@@ -166,14 +165,6 @@
}
log(LOG_DEBUG,"connection_edge_process_relay_cell(): end cell for stream %d. Removing stream.",*(int*)conn->stream_id);
- /* go through and identify who points to conn. remove conn from the list. */
-#if 0
- if(conn == circ->p_conn) {
- circ->p_conn = conn->next_stream;
- }
- for(prevconn = circ->p_conn; prevconn->next_stream != conn; prevconn = prevconn->next_stream) ;
- prevconn->next_stream = conn->next_stream;
-#endif
#ifdef HALF_OPEN
conn->done_sending = 1;
shutdown(conn->s, 1); /* XXX check return; refactor NM */
@@ -182,6 +173,23 @@
#endif
conn->marked_for_close = 1;
break;
+ case RELAY_COMMAND_EXTEND:
+ if(conn) {
+ log(LOG_INFO,"connection_edge_process_relay_cell(): 'extend' for non-zero stream. Dropping.");
+ return 0;
+ }
+ return circuit_extend(cell, circ);
+ case RELAY_COMMAND_EXTENDED:
+ if(edge_type == EDGE_EXIT) {
+ log(LOG_INFO,"connection_edge_process_relay_cell(): 'extended' unsupported at exit. Dropping.");
+ return 0;
+ }
+ log(LOG_DEBUG,"connection_edge_process_relay_cell(): Got an extended cell! Yay.");
+ if(circuit_finish_handshake(circ, cell->payload+RELAY_HEADER_SIZE) < 0) {
+ log(LOG_INFO,"connection_edge_process_relay_cell(): circuit_finish_handshake failed.");
+ return -1;
+ }
+ return circuit_send_next_onion_skin(circ);
case RELAY_COMMAND_CONNECTED:
if(edge_type == EDGE_EXIT) {
log(LOG_INFO,"connection_edge_process_relay_cell(): 'connected' unsupported at exit. Dropping.");
Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- main.c 1 May 2003 22:55:51 -0000 1.51
+++ main.c 5 May 2003 23:24:45 -0000 1.52
@@ -337,7 +337,6 @@
for(i=0;i<nfds;i++) {
tmpconn = connection_array[i];
connection_increment_receiver_bucket(tmpconn);
- connection_array[i]->onions_handled_this_second = 0;
/* check connections to see whether we should send a keepalive, expire, or wait */
if(!connection_speaks_cells(tmpconn))
@@ -683,7 +682,6 @@
}
}
- init_tracked_tree(); /* initialize the replay detection tree */
init_cache_tree(); /* initialize the dns resolve tree */
signal (SIGINT, catch); /* catch kills so we can exit cleanly */
Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- onion.c 5 May 2003 04:26:57 -0000 1.43
+++ onion.c 5 May 2003 23:24:45 -0000 1.44
@@ -6,11 +6,8 @@
extern or_options_t options; /* command-line and config-file options */
-static int onion_process(circuit_t *circ);
-static int onion_deliver_to_conn(aci_t aci, unsigned char *onion, uint32_t onionlen, connection_t *conn);
static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len);
-static int find_tracked_onion(unsigned char *onion, uint32_t onionlen,
- int expire);
+static int onionskin_process(circuit_t *circ);
int decide_aci_type(uint32_t local_addr, uint16_t local_port,
uint32_t remote_addr, uint16_t remote_port) {
@@ -76,17 +73,19 @@
if(!ol_list)
return; /* no onions pending, we're done */
- assert(ol_list->circ && ol_list->circ->p_conn);
+ assert(ol_list->circ);
+ assert(ol_list->circ->p_conn);
assert(ol_length > 0);
circ = ol_list->circ;
- if(onion_process(circ) < 0) {
+ if(onionskin_process(circ) < 0) {
log(LOG_DEBUG,"onion_pending_process_one(): Failed. Closing.");
onion_pending_remove(circ);
circuit_close(circ);
} else {
log(LOG_DEBUG,"onion_pending_process_one(): Succeeded. Delivering queued relay cells.");
for(tmpd = ol_list->relay_cells; tmpd; tmpd=tmpd->next) {
+ log(LOG_DEBUG,"onion_pending_process_one(): Delivering relay cell...");
command_process_relay_cell(tmpd->cell, circ->p_conn);
}
onion_pending_remove(circ);
@@ -174,136 +173,48 @@
}
}
-/* helper function for onion_process */
-static int onion_deliver_to_conn(aci_t aci, unsigned char *onion, uint32_t onionlen, connection_t *conn) {
- char *buf;
- int buflen, dataleft;
+/* learn keys, initialize, then send a created cell back */
+static int onionskin_process(circuit_t *circ) {
+ unsigned char iv[16];
+ unsigned char keys[32];
cell_t cell;
-
- assert(aci && onion && onionlen);
-
- buflen = onionlen+4;
- buf = malloc(buflen);
- if(!buf)
- return -1;
-
- log(LOG_DEBUG,"onion_deliver_to_conn(): Setting onion length to %u.",onionlen);
- *(uint32_t*)buf = htonl(onionlen);
- memcpy((buf+4),onion,onionlen);
-
- dataleft = buflen;
- while(dataleft > 0) {
- memset(&cell,0,sizeof(cell_t));
- cell.command = CELL_CREATE;
- cell.aci = aci;
- if(dataleft >= CELL_PAYLOAD_SIZE)
- cell.length = CELL_PAYLOAD_SIZE;
- else
- cell.length = dataleft;
- memcpy(cell.payload, buf+buflen-dataleft, cell.length);
- dataleft -= cell.length;
-
- log(LOG_DEBUG,"onion_deliver_to_conn(): Delivering create cell, payload %d bytes.",cell.length);
- if(connection_write_cell_to_buf(&cell, conn) < 0) {
- log(LOG_DEBUG,"onion_deliver_to_conn(): Could not buffer new create cells. Closing.");
- free(buf);
- return -1;
- }
- }
- free(buf);
- return 0;
-}
-static int onion_process(circuit_t *circ) {
- connection_t *n_conn;
- int retval;
- aci_t aci_type;
- struct sockaddr_in me; /* my router identity */
- onion_layer_t layer;
+ memset(iv, 0, 16);
- if(learn_my_address(&me) < 0)
- return -1;
+ memset(&cell, 0, sizeof(cell_t));
+ cell.command = CELL_CREATED;
+ cell.aci = circ->p_aci;
+ cell.length = 192;
- /* decrypt it in-place */
- if(decrypt_onion(circ->onion,circ->onionlen,getprivatekey(),&layer) < 0) {
- log(LOG_DEBUG,"command_process_create_cell(): decrypt_onion() failed, closing circuit.");
+ circ->state = CIRCUIT_STATE_OPEN;
+
+ log(LOG_DEBUG,"onionskin_process(): Entering.");
+
+ if(onion_skin_server_handshake(circ->onionskin, getprivatekey(),
+ cell.payload, keys, 32) < 0) {
+ log(LOG_ERR,"onionskin_process(): onion_skin_server_handshake failed.");
return -1;
}
- log(LOG_DEBUG,"command_process_create_cell(): Onion decrypted.");
- /* check freshness */
- if (layer.expire < (uint32_t)time(NULL)) /* expired onion */ /*XXXX*/
- {
- log(LOG_NOTICE,"I have just received an expired onion. This could be a replay attack.");
+ log(LOG_DEBUG,"onionskin_process: init cipher forward %d, backward %d.", *(int*)keys, *(int*)(keys+16));
+
+ if (!(circ->n_crypto =
+ crypto_create_init_cipher(DEFAULT_CIPHER,keys,iv,0))) {
+ log(LOG_ERR,"Cipher initialization failed.");
return -1;
}
- aci_type = decide_aci_type(ntohl(me.sin_addr.s_addr), ntohs(me.sin_port),
- layer.addr, layer.port);
-
- if(circuit_init(circ, aci_type, &layer) < 0) {
- log(LOG_ERR,"process_onion(): init_circuit() failed.");
+ if (!(circ->p_crypto =
+ crypto_create_init_cipher(DEFAULT_CIPHER,keys+16,iv,1))) {
+ log(LOG_ERR,"Cipher initialization failed.");
return -1;
}
- /* check for replay. at the same time, add it to the pile of tracked onions. */
- if(find_tracked_onion(circ->onion, circ->onionlen, layer.expire)) {
- log(LOG_NOTICE,"process_onion(): I have just received a replayed onion. This could be a replay attack.");
+ if(connection_write_cell_to_buf(&cell, circ->p_conn) < 0) {
return -1;
}
+ log(LOG_DEBUG,"onionskin_process(): Finished sending 'created' cell.");
- /* now we must send create cells to the next router */
- if(circ->n_addr && circ->n_port) {
- n_conn = connection_twin_get_by_addr_port(circ->n_addr,circ->n_port);
- if(!n_conn || n_conn->type != CONN_TYPE_OR) {
- /* i've disabled making connections through OPs, but it's definitely
- * possible here. I'm not sure if it would be a bug or a feature. -RD
- */
- /* note also that this will close circuits where the onion has the same
- * router twice in a row in the path. i think that's ok. -RD
- */
- log(LOG_DEBUG,"command_process_create_cell(): Next router not connected. Closing.");
- return -1;
- }
-
- circ->n_addr = n_conn->addr; /* these are different if we found a twin instead */
- circ->n_port = n_conn->port;
-
- circ->n_conn = n_conn;
- log(LOG_DEBUG,"command_process_create_cell(): n_conn is %s:%u",n_conn->address,n_conn->port);
-
- /* send the CREATE cells on to the next hop */
- pad_onion(circ->onion, circ->onionlen, ONION_LAYER_SIZE);
- log(LOG_DEBUG,"command_process_create_cell(): Padded the onion with random data.");
-
- retval = onion_deliver_to_conn(circ->n_aci, circ->onion, circ->onionlen, n_conn);
- free(circ->onion);
- circ->onion = NULL;
- if (retval == -1) {
- log(LOG_DEBUG,"command_process_create_cell(): Could not deliver the onion to next conn. Closing.");
- return -1;
- }
- } else { /* this is destined for an exit */
- log(LOG_DEBUG,"command_process_create_cell(): create cell reached exit. Circuit established.");
-#if 0
- log(LOG_DEBUG,"command_process_create_cell(): Creating new exit connection.");
- n_conn = connection_new(CONN_TYPE_EXIT);
- if(!n_conn) {
- log(LOG_DEBUG,"command_process_create_cell(): connection_new failed. Closing.");
- return -1;
- }
- n_conn->state = EXIT_CONN_STATE_CONNECTING_WAIT;
- n_conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */
- n_conn->bandwidth = -1;
- n_conn->s = -1; /* not yet valid */
- if(connection_add(n_conn) < 0) { /* no space, forget it */
- log(LOG_DEBUG,"command_process_create_cell(): connection_add failed. Closing.");
- connection_free(n_conn);
- return -1;
- }
- circ->n_conn = n_conn;
-#endif
- }
return 0;
}
@@ -432,402 +343,82 @@
return num;
}
-/* creates a new onion from route, stores it and its length into buf and len respectively */
-unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int *route, int routelen, int *len, crypt_path_t **cpath)
-{
+crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop) {
+ int routelen; /* length of the route */
+ unsigned int *route; /* hops in the route as an array of indexes into rarray */
+ crypt_path_t *cpath=NULL;
+ routerinfo_t **rarray;
+ int rarray_len;
int i;
- char *layerp;
crypt_path_t *hop;
- unsigned char *buf;
routerinfo_t *router;
- unsigned char iv[16];
struct in_addr netaddr;
- onion_layer_t layer;
-
- assert(rarray && route && len && routelen && cpath);
- *cpath = NULL;
-
- /* calculate the size of the onion */
- *len = routelen * ONION_LAYER_SIZE + ONION_PADDING_SIZE;
- /* 28 bytes per layer + 100 bytes padding for the innermost layer */
- log(LOG_DEBUG,"create_onion() : Size of the onion is %u.",*len);
+ router_get_rarray(&rarray, &rarray_len);
- /* allocate memory for the onion */
- buf = malloc(*len);
- if(!buf) {
- log(LOG_ERR,"Error allocating memory.");
+ /* choose a route */
+ route = new_route(options.CoinWeight, rarray, rarray_len, &routelen);
+ if (!route) {
+ log(LOG_ERR,"onion_generate_cpath(): Error choosing a route through the OR network.");
return NULL;
}
- log(LOG_DEBUG,"create_onion() : Allocated memory for the onion.");
+ log(LOG_DEBUG,"onion_generate_cpath(): Chosen a route of length %u: ",routelen);
+
+ *firsthop = rarray[route[routelen-1]];
+ assert(*firsthop); /* should always be defined */
for(i=0; i<routelen; i++) {
netaddr.s_addr = htonl((rarray[route[i]])->addr);
- log(LOG_DEBUG,"create_onion(): %u : %s:%u, %u/%u",routelen-i,
+ log(LOG_DEBUG,"onion_generate_cpath(): %u : %s:%u, %u/%u",routelen-i,
inet_ntoa(netaddr),
(rarray[route[i]])->or_port,
(rarray[route[i]])->pkey,
crypto_pk_keysize((rarray[route[i]])->pkey));
}
- layerp = buf + *len - ONION_LAYER_SIZE - ONION_PADDING_SIZE; /* pointer to innermost layer */
- /* create the onion layer by layer, starting with the innermost */
+ /* create the cpath layer by layer, starting at the last hop */
for (i=0;i<routelen;i++) {
router = rarray[route[i]];
- layer.version = OR_VERSION;
- if (i) { /* not last hop */
- layer.port = rarray[route[i-1]]->or_port;
- layer.addr = rarray[route[i-1]]->addr;
- } else {
- layer.port = 0;
- layer.addr = 0;
- }
-
- /* Expiration Time */
- layer.expire = (uint32_t)(time(NULL) + 86400); /* NOW + 1 day */
-
- /* Key Seed Material */
- if(crypto_rand(ONION_KEYSEED_LEN, layer.keyseed)) { /* error */
- log(LOG_ERR,"Error generating random data.");
- goto error;
- }
-
- onion_pack(layerp, &layer);
-
-// log(LOG_DEBUG,"create_onion() : Onion layer %u built : %u, %u, %u, %s, %u.",i+1,layer->zero,layer->backf,layer->forwf,inet_ntoa(*((struct in_addr *)&layer->addr)),layer->port);
-
/* build up the crypt_path */
hop = (crypt_path_t *)malloc(sizeof(crypt_path_t));
if(!hop) {
- log(LOG_ERR,"Error allocating memory.");
- goto error;
+ log(LOG_ERR,"Error allocating crypt path hop memory.");
+ circuit_free_cpath(cpath);
+ free(route);
+ return NULL;
}
+ memset(hop, 0, sizeof(crypt_path_t));
/* link hop into the cpath, at the front */
- hop->next = *cpath;
+ hop->next = cpath;
hop->prev = NULL;
- hop->state = CPATH_STATE_OPEN; /* change when we move to incremental paths */
- if(*cpath) {
- (*cpath)->prev = hop;
- }
- *cpath = hop;
-
- log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
-
- /* calculate keys */
- crypto_SHA_digest(layer.keyseed,16,hop->digest3);
- log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
- crypto_SHA_digest(hop->digest3,20,hop->digest2);
- log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
- crypto_SHA_digest(hop->digest2,20,hop->digest3);
- log(LOG_DEBUG,"create_onion() : Third SHA pass performed.");
- log(LOG_DEBUG,"create_onion() : Keys generated.");
- /* set IV to zero */
- memset((void *)iv,0,16);
-
- /* initialize cipher engines */
- if (! (hop->f_crypto =
- crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest3, iv, 1))) {
- /* cipher initialization failed */
- log(LOG_ERR,"Could not create a crypto environment.");
- goto error;
- }
-
- if (! (hop->b_crypto =
- crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest2, iv, 0))) {
- /* cipher initialization failed */
- log(LOG_ERR,"Could not create a crypto environment.");
- goto error;
- }
-
- log(LOG_DEBUG,"create_onion() : Built corresponding crypt path hop.");
-
- /* padding if this is the innermost layer */
- if (!i) {
- if (crypto_pseudo_rand(ONION_PADDING_SIZE, layerp + ONION_LAYER_SIZE)) { /* error */
- log(LOG_ERR,"Error generating pseudo-random data.");
- goto error;
- }
- log(LOG_DEBUG,"create_onion() : This is the innermost layer. Adding 100 bytes of padding.");
+ hop->state = CPATH_STATE_CLOSED;
+ if(cpath) {
+ cpath->prev = hop;
}
+ cpath = hop;
- /* encrypt */
-
- if(encrypt_onion(layerp,ONION_PADDING_SIZE+(i+1)*ONION_LAYER_SIZE,router->pkey,layer.keyseed) < 0) {
- log(LOG_ERR,"Error encrypting onion layer.");
- goto error;
+#if 0
+ if (i) { /* not last hop. (last hop has 0's for these.) */
+ hop->port = rarray[route[i-1]]->or_port;
+ hop->addr = rarray[route[i-1]]->addr;
}
- log(LOG_DEBUG,"create_onion() : Encrypted layer.");
+#endif
+ hop->port = rarray[route[i]]->or_port;
+ hop->addr = rarray[route[i]]->addr;
- /* calculate pointer to next layer */
- layerp = buf + (routelen-i-2)*ONION_LAYER_SIZE;
+ log(LOG_DEBUG,"onion_generate_cpath() : Building hop %u of crypt path.",i+1);
}
/* now link cpath->prev to the end of cpath */
- for(hop=*cpath; hop->next; hop=hop->next) ;
- hop->next = *cpath;
- (*cpath)->prev = hop;
-
- return buf;
-
- error:
- if(buf)
- free(buf);
- circuit_free_cpath(*cpath);
- return NULL;
-}
-
-/* encrypts 128 bytes of the onion with the specified public key, the rest with
- * DES OFB with the key as defined in the outter layer */
-int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey, char* keyseed) {
- unsigned char *tmpbuf = NULL; /* temporary buffer for crypto operations */
- unsigned char digest[20]; /* stores SHA1 output - 160 bits */
- unsigned char iv[8];
-
- crypto_cipher_env_t *crypt_env = NULL; /* crypto environment */
-
- assert(onion && pkey);
- assert(onionlen >= 128);
-
- memset(iv,0,8);
-
-// log(LOG_DEBUG,"Onion layer : %u, %u, %u, %s, %u.",onion->zero,onion->backf,onion->forwf,inet_ntoa(*((struct in_addr *)&onion->addr)),onion->port);
- /* allocate space for tmpbuf */
- tmpbuf = (unsigned char *)malloc(onionlen);
- if(!tmpbuf) {
- log(LOG_ERR,"Could not allocate memory.");
- return -1;
- }
- log(LOG_DEBUG,"encrypt_onion() : allocated %u bytes of memory for the encrypted onion (at %u).",onionlen,tmpbuf);
-
- /* get key1 = SHA1(KeySeed) */
- if (crypto_SHA_digest(keyseed,16,digest)) {
- log(LOG_ERR,"Error computing SHA1 digest.");
- goto error;
- }
- log(LOG_DEBUG,"encrypt_onion() : Computed DES key.");
-
- log(LOG_DEBUG,"encrypt_onion() : Trying to RSA encrypt.");
- /* encrypt 128 bytes with RSA *pkey */
- if (crypto_pk_public_encrypt(pkey, onion, 128, tmpbuf, RSA_NO_PADDING) == -1) {
- log(LOG_ERR,"Error RSA-encrypting data :%s",crypto_perror());
- goto error;
- }
-
- log(LOG_DEBUG,"encrypt_onion() : RSA encrypted first 128 bytes of the onion.");
-
- /* now encrypt the rest with 3DES OFB */
- crypt_env = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, digest, iv, 1);
- if (!crypt_env) {
- log(LOG_ERR,"Error creating the crypto environment.");
- goto error;
- }
-
- if (crypto_cipher_encrypt(crypt_env,onion+128, onionlen-128, (unsigned char *)tmpbuf+128)) { /* error */
- log(LOG_ERR,"Error performing DES encryption:%s",crypto_perror());
- goto error;
- }
- log(LOG_DEBUG,"encrypt_onion() : 3DES OFB encrypted the rest of the onion.");
-
- /* now copy tmpbuf to onion */
- memcpy(onion,tmpbuf,onionlen);
- log(LOG_DEBUG,"encrypt_onion() : Copied cipher to original onion buffer.");
- free(tmpbuf);
- crypto_free_cipher_env(crypt_env);
- return 0;
-
- error:
- if (tmpbuf)
- free(tmpbuf);
- if (crypt_env)
- crypto_free_cipher_env(crypt_env);
- return -1;
-}
-
-/* decrypts the first 128 bytes using RSA and prkey, decrypts the rest with DES OFB with key1 */
-int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prkey, onion_layer_t *layer) {
- void *tmpbuf = NULL; /* temporary buffer for crypto operations */
- unsigned char digest[20]; /* stores SHA1 output - 160 bits */
- unsigned char iv[8];
-
- crypto_cipher_env_t *crypt_env =NULL; /* crypto environment */
-
- assert(onion && prkey);
-
- memset(iv,0,8);
-
- /* allocate space for tmpbuf */
- tmpbuf = malloc(onionlen);
- if (!tmpbuf) {
- log(LOG_ERR,"Could not allocate memory.");
- return -1;
- }
- log(LOG_DEBUG,"decrypt_onion() : Allocated memory for the temporary buffer.");
-
- /* decrypt 128 bytes with RSA *prkey */
- if (crypto_pk_private_decrypt(prkey, onion, 128, tmpbuf, RSA_NO_PADDING) == -1)
- {
- log(LOG_ERR,"Error RSA-decrypting data :%s",crypto_perror());
- goto error;
- }
- log(LOG_DEBUG,"decrypt_onion() : RSA decryption complete.");
-
- onion_unpack(layer, tmpbuf);
-
- /* get key1 = SHA1(KeySeed) */
- if (crypto_SHA_digest(layer->keyseed,16,digest)) {
- log(LOG_ERR,"Error computing SHA1 digest.");
- goto error;
- }
- log(LOG_DEBUG,"decrypt_onion() : Computed DES key.");
-
- /* now decrypt the rest with 3DES OFB */
- crypt_env = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, digest, iv, 0);
- if (!crypt_env) {
- log(LOG_ERR,"Error creating crypto environment");
- goto error;
- }
-
- if (crypto_cipher_decrypt(crypt_env,onion+128, onionlen-128,tmpbuf+128)) {
- log(LOG_ERR,"Error performing DES decryption:%s",crypto_perror());
- goto error;
- }
-
- log(LOG_DEBUG,"decrypt_onion() : DES decryption complete.");
-
- /* now copy tmpbuf to onion */
- memcpy(onion,tmpbuf,onionlen);
- free(tmpbuf);
- crypto_free_cipher_env(crypt_env);
- return 0;
-
- error:
- if (tmpbuf)
- free(tmpbuf);
- if (crypt_env)
- crypto_free_cipher_env(crypt_env);
- return -1;
-}
-
-/* delete first n bytes of the onion and pads the end with n bytes of random data */
-void pad_onion(unsigned char *onion, uint32_t onionlen, int n)
-{
- assert(onion);
-
- memmove(onion,onion+n,onionlen-n);
- crypto_pseudo_rand(n, onion+onionlen-n);
-}
-
-
-
-
-/* red black tree using Niels' tree.h. I used
-http://www.openbsd.org/cgi-bin/cvsweb/src/regress/sys/sys/tree/rb/
-as my guide */
-
-#include "tree.h"
-
-struct tracked_onion {
- RB_ENTRY(tracked_onion) node;
- uint32_t expire;
- char digest[20]; /* SHA digest of the onion */
- struct tracked_onion *next;
-};
-
-RB_HEAD(tracked_tree, tracked_onion) tracked_root;
-
-int compare_tracked_onions(struct tracked_onion *a, struct tracked_onion *b) {
- return memcmp(a->digest, b->digest, 20);
-}
-
-RB_PROTOTYPE(tracked_tree, tracked_onion, node, compare_tracked_onions)
-RB_GENERATE(tracked_tree, tracked_onion, node, compare_tracked_onions)
-
-void init_tracked_tree(void) {
- RB_INIT(&tracked_root);
-}
-
-/* see if this onion has been seen before. if so, return 1, else
- * return 0 and add the sha1 of this onion to the tree.
- */
-static int find_tracked_onion(unsigned char *onion, uint32_t onionlen,
- int expire) {
- static struct tracked_onion *head_tracked_onions = NULL; /* linked list of tracked onions */
- static struct tracked_onion *tail_tracked_onions = NULL;
-
- uint32_t now = time(NULL);
- struct tracked_onion *to;
-
- /* first take this opportunity to see if there are any expired
- * onions in the tree. we know this is fast because the linked list
- * 'tracked_onions' is ordered by when they were seen.
- */
- while(head_tracked_onions && (head_tracked_onions->expire < now)) {
- to = head_tracked_onions;
- log(LOG_DEBUG,"find_tracked_onion(): Forgetting old onion (expires %d)", to->expire);
- head_tracked_onions = to->next;
- if(!head_tracked_onions) /* if there are no more, */
- tail_tracked_onions = NULL; /* then make sure the list's tail knows that too */
- RB_REMOVE(tracked_tree, &tracked_root, to);
- free(to);
- }
-
- to = malloc(sizeof(struct tracked_onion));
-
- /* compute the SHA digest of the onion */
- crypto_SHA_digest(onion, onionlen, to->digest);
-
- /* try adding it to the tree. if it's already there it will return it. */
- if(RB_INSERT(tracked_tree, &tracked_root, to)) {
- /* yes, it's already there: this is a replay. */
- free(to);
- return 1;
- }
-
- /* this is a new onion. add it to the list. */
-
- to->expire = expire; /* set the expiration date */
- to->next = NULL;
-
- if (!head_tracked_onions) {
- head_tracked_onions = to;
- } else {
- tail_tracked_onions->next = to;
- }
- tail_tracked_onions = to;
-
- log(LOG_DEBUG,"find_tracked_onion(): Remembered new onion (expires %d)", to->expire);
-
- return 0;
-}
-
-void
-onion_pack(char *dest, onion_layer_t *src)
-{
- assert((src->version & 0x80) == 0);
-
- *(uint8_t*)(dest) = src->version;
- *(uint16_t*)(dest+1) = htons(src->port);
- *(uint32_t*)(dest+3) = htonl(src->addr);
- *(uint32_t*)(dest+7) = htonl(src->expire);
- memcpy(dest+11, src->keyseed, ONION_KEYSEED_LEN);
- log(LOG_DEBUG,"onion_pack(): version %d, port %d, addr %s, expire %u", src->version, src->port,
- inet_ntoa(*((struct in_addr *)(dest+3))), src->expire);
-}
-
-void
-onion_unpack(onion_layer_t *dest, char *src)
-{
- dest->version = *(uint8_t*)src;
- dest->port = ntohs(*(uint16_t*)(src+1));
- dest->addr = ntohl(*(uint32_t*)(src+3));
- dest->expire = ntohl(*(uint32_t*)(src+7));
- memcpy(dest->keyseed, src+11, ONION_KEYSEED_LEN);
+ for(hop=cpath; hop->next; hop=hop->next) ;
+ hop->next = cpath;
+ cpath->prev = hop;
- log(LOG_DEBUG,"onion_unpack(): version %d, port %d, addr %s, expire %u", dest->version, dest->port,
- inet_ntoa(*((struct in_addr *)(src+3))), dest->expire);
+ free(route);
+ return cpath;
}
/*----------------------------------------------------------------------*/
@@ -843,7 +434,7 @@
* and the last 80 are encrypted with the symmetric key.
*/
int
-onion_skin_create(crypto_pk_env_t *router_key,
+onion_skin_create(crypto_pk_env_t *dest_router_key,
crypto_dh_env_t **handshake_state_out,
char *onion_skin_out) /* Must be 208 bytes long */
{
@@ -861,7 +452,7 @@
goto err;
dhbytes = crypto_dh_get_bytes(dh);
- pkbytes = crypto_pk_keysize(router_key);
+ pkbytes = crypto_pk_keysize(dest_router_key);
assert(dhbytes+16 == 208);
if (!(pubkey = malloc(dhbytes+16)))
goto err;
@@ -896,7 +487,7 @@
if (!cipher)
goto err;
- if (crypto_pk_public_encrypt(router_key, pubkey, pkbytes,
+ if (crypto_pk_public_encrypt(dest_router_key, pubkey, pkbytes,
onion_skin_out, RSA_NO_PADDING)==-1)
goto err;
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -d -r1.72 -r1.73
--- or.h 5 May 2003 04:26:59 -0000 1.72
+++ or.h 5 May 2003 23:24:46 -0000 1.73
@@ -113,9 +113,9 @@
#define DIR_CONN_STATE_COMMAND_WAIT 3
#define DIR_CONN_STATE_WRITING 4
-#define CIRCUIT_STATE_ONION_WAIT 0 /* receiving the onion */
-#define CIRCUIT_STATE_ONION_PENDING 1 /* waiting to process the onion */
-#define CIRCUIT_STATE_OR_WAIT 2 /* I'm at the beginning of the path, my firsthop is still connecting */
+#define CIRCUIT_STATE_BUILDING 0 /* I'm the OP, still haven't done all my handshakes */
+#define CIRCUIT_STATE_ONIONSKIN_PENDING 1 /* waiting to process the onion */
+#define CIRCUIT_STATE_OR_WAIT 2 /* I'm the OP, my firsthop is still connecting */
#define CIRCUIT_STATE_OPEN 3 /* onion processed, ready to send data along the connection */
//#define CIRCUIT_STATE_CLOSE_WAIT1 4 /* sent two "destroy" signals, waiting for acks */
//#define CIRCUIT_STATE_CLOSE_WAIT2 5 /* received one ack, waiting for one more
@@ -127,23 +127,14 @@
#define RELAY_COMMAND_END 3
#define RELAY_COMMAND_CONNECTED 4
#define RELAY_COMMAND_SENDME 5
+#define RELAY_COMMAND_EXTEND 6
+#define RELAY_COMMAND_EXTENDED 7
#define RELAY_HEADER_SIZE 8
#define RELAY_STATE_RESOLVING
-/* available cipher functions */
-#if 0
-#define ONION_CIPHER_IDENTITY 0
-#define ONION_CIPHER_DES 1
-#define ONION_CIPHER_RC4 2
-#define ONION_CIPHER_3DES 3
-#endif
-
/* default cipher function */
-#if 0
-#define ONION_DEFAULT_CIPHER ONION_CIPHER_3DES
-#endif
#define DEFAULT_CIPHER CRYPTO_CIPHER_3DES
#define CELL_DIRECTION_IN 1
@@ -160,9 +151,10 @@
/* cell commands */
#define CELL_PADDING 0
#define CELL_CREATE 1
-#define CELL_RELAY 2
-#define CELL_DESTROY 3
-#define CELL_SENDME 4
+#define CELL_CREATED 2
+#define CELL_RELAY 3
+#define CELL_DESTROY 4
+#define CELL_SENDME 5
#define CELL_PAYLOAD_SIZE 248
#define CELL_NETWORK_SIZE 256
@@ -246,8 +238,6 @@
long timestamp_created;
- int onions_handled_this_second;
-
/* used by OR and OP: */
uint32_t bandwidth; /* connection bandwidth */
@@ -339,16 +329,19 @@
} routerinfo_t;
struct crypt_path_t {
- char digest2[20]; /* second SHA output for onion_layer_t.keyseed */
- char digest3[20]; /* third SHA output for onion_layer_t.keyseed */
/* crypto environments */
crypto_cipher_env_t *f_crypto;
crypto_cipher_env_t *b_crypto;
+ crypto_dh_env_t *handshake_state;
+
+ uint32_t addr;
+ uint16_t port;
+
char state;
#define CPATH_STATE_CLOSED 0
-#define CPATH_STATE_AWAITING_KEY 1
+#define CPATH_STATE_AWAITING_KEYS 1
#define CPATH_STATE_OPEN 2
struct crypt_path_t *next;
struct crypt_path_t *prev; /* doubly linked list */
@@ -382,15 +375,15 @@
crypt_path_t *cpath;
- uint32_t expire; /* expiration time for the corresponding onion */
+ char onionskin[208]; /* for storage while onionskin pending */
long timestamp_created;
char dirty; /* whether this circuit has been used yet */
int state;
- unsigned char *onion; /* stores the onion when state is CONN_STATE_OPEN_WAIT */
- uint32_t onionlen; /* total onion length */
- uint32_t recvlen; /* length of the onion so far */
+// unsigned char *onion; /* stores the onion when state is CONN_STATE_OPEN_WAIT */
+// uint32_t onionlen; /* total onion length */
+// uint32_t recvlen; /* length of the onion so far */
void *next;
} circuit_t;
@@ -538,17 +531,18 @@
void circuit_expire_unused_circuits(void);
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);
+int circuit_establish_circuit(void);
void circuit_n_conn_open(connection_t *or_conn);
-int circuit_send_onion(connection_t *or_conn, circuit_t *circ);
+int circuit_send_next_onion_skin(circuit_t *circ);
+int circuit_extend(cell_t *cell, circuit_t *circ);
+int circuit_finish_handshake(circuit_t *circ, char *reply);
/********************************* command.c ***************************/
void command_process_cell(cell_t *cell, connection_t *conn);
void command_process_create_cell(cell_t *cell, connection_t *conn);
+void command_process_created_cell(cell_t *cell, connection_t *conn);
void command_process_sendme_cell(cell_t *cell, connection_t *conn);
void command_process_relay_cell(cell_t *cell, connection_t *conn);
void command_process_destroy_cell(cell_t *cell, connection_t *conn);
@@ -775,23 +769,7 @@
*/
unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen);
-/* creates a new onion from route, stores it and its length into bufp and lenp respectively */
-unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int *route, int routelen, int *len, crypt_path_t **cpath);
-
-/* encrypts 128 bytes of the onion with the specified public key, the rest with
- * DES OFB with the key as defined in the outter layer */
-int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey, char *keyseed);
-
-/* decrypts the first 128 bytes using RSA and prkey, decrypts the rest with DES OFB with key1. Writes the first layer into 'layer' */
-int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prkey, onion_layer_t *layer);
-
-/* delete first n bytes of the onion and pads the end with n bytes of random data */
-void pad_onion(unsigned char *onion, uint32_t onionlen, int n);
-
-void init_tracked_tree(void);
-
-void onion_pack(char *dest, onion_layer_t *src);
-void onion_unpack(onion_layer_t *dest, char *src);
+crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop);
int onion_skin_create(crypto_pk_env_t *router_key,
crypto_dh_env_t **handshake_state_out,
@@ -814,10 +792,8 @@
void router_retry_connections(void);
routerinfo_t *router_pick_directory_server(void);
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
-unsigned int *router_new_route(int *routelen);
-unsigned char *router_create_onion(unsigned int *route, int routelen, int *len, crypt_path_t **cpath);
+void router_get_rarray(routerinfo_t ***prouter_array, int *prarray_len);
int router_is_me(uint32_t addr, uint16_t port);
-routerinfo_t *router_get_first_in_route(unsigned int *route, int routelen);
void router_forget_router(uint32_t addr, uint16_t port);
int router_get_list_from_file(char *routerfile);
int router_get_list_from_string(char *s);
Index: routers.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routers.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- routers.c 8 Apr 2003 06:44:38 -0000 1.21
+++ routers.c 5 May 2003 23:24:46 -0000 1.22
@@ -98,18 +98,9 @@
return NULL;
}
-routerinfo_t *router_get_first_in_route(unsigned int *route, int routelen) {
- return router_array[route[routelen-1]];
-}
-
-/* a wrapper around new_route. put all these in routers.c perhaps? */
-unsigned int *router_new_route(int *routelen) {
- return new_route(options.CoinWeight, router_array, rarray_len, routelen);
-}
-
-/* a wrapper around create_onion */
-unsigned char *router_create_onion(unsigned int *route, int routelen, int *len, crypt_path_t **cpath) {
- return create_onion(router_array,rarray_len,route,routelen,len,cpath);
+void router_get_rarray(routerinfo_t ***prouter_array, int *prarray_len) {
+ *prouter_array = router_array;
+ *prarray_len = rarray_len;
}
/* return 1 if addr and port corresponds to my addr and my or_listenport. else 0,
@@ -132,52 +123,6 @@
return 0;
-#if 0
- /* local host information */
- char localhostname[512];
- struct hostent *localhost;
- struct in_addr *a;
- char *tmp1;
-
- char *addr = NULL;
- int i = 0;
-
- /* obtain local host information */
- if (gethostname(localhostname,512) < 0) {
- log(LOG_ERR,"router_is_me(): Error obtaining local hostname.");
- return -1;
- }
- localhost = gethostbyname(localhostname);
- if (!localhost) {
- log(LOG_ERR,"router_is_me(): Error obtaining local host info.");
- return -1;
- }
-
- /* check host addresses for a match with or_address above */
- addr = localhost->h_addr_list[i++]; /* set to the first local address */
- while(addr)
- {
- a = (struct in_addr *)addr;
-
- tmp1 = strdup(inet_ntoa(*a)); /* can't call inet_ntoa twice in the same
- printf, since it overwrites its static
- memory each time */
- log(LOG_DEBUG,"router_is_me(): Comparing '%s' to '%s'.",tmp1,
- inet_ntoa( *((struct in_addr *)&or_address) ) );
- free(tmp1);
- if (!memcmp((void *)&or_address, (void *)addr, sizeof(uint32_t))) { /* addresses match */
- log(LOG_DEBUG,"router_is_me(): Addresses match. Comparing ports.");
- if (or_listenport == my_or_listenport) { /* ports also match */
- log(LOG_DEBUG,"router_is_me(): Ports match too.");
- return 1;
- }
- }
-
- addr = localhost->h_addr_list[i++];
- }
-
- return 0;
-#endif
}
/* delete a list of routers from memory */