cleanup and a variety of bugfixes

svn:r132
This commit is contained in:
Roger Dingledine 2002-10-02 22:54:20 +00:00
parent bef3424bec
commit bf53852a00
10 changed files with 155 additions and 149 deletions

View File

@ -148,7 +148,7 @@ void connection_free(connection_t *conn) {
free(conn); free(conn);
} }
int connection_create_listener(struct sockaddr_in *local, int type) { int connection_create_listener(struct sockaddr_in *bindaddr, int type) {
connection_t *conn; connection_t *conn;
int s; int s;
int one=1; int one=1;
@ -162,15 +162,14 @@ int connection_create_listener(struct sockaddr_in *local, int type) {
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if(bind(s,(struct sockaddr *)local,sizeof(*local)) < 0) { if(bind(s,(struct sockaddr *)bindaddr,sizeof(*bindaddr)) < 0) {
perror("bind "); perror("bind ");
log(LOG_ERR,"Could not bind to local port %u.",ntohs(local->sin_port)); log(LOG_ERR,"Could not bind to port %u.",ntohs(bindaddr->sin_port));
return -1; return -1;
} }
/* start local server */
if(listen(s,SOMAXCONN) < 0) { if(listen(s,SOMAXCONN) < 0) {
log(LOG_ERR,"Could not listen on local port %u.",ntohs(local->sin_port)); log(LOG_ERR,"Could not listen on port %u.",ntohs(bindaddr->sin_port));
return -1; return -1;
} }
@ -189,10 +188,7 @@ int connection_create_listener(struct sockaddr_in *local, int type) {
return -1; return -1;
} }
/* remember things so you can tell the baby sockets */ log(LOG_DEBUG,"connection_create_listener(): Listening on port %u.",ntohs(bindaddr->sin_port));
memcpy(&conn->local,local,sizeof(struct sockaddr_in));
log(LOG_DEBUG,"connection_create_listener(): Listening on local port %u.",ntohs(local->sin_port));
conn->state = LISTENER_STATE_READY; conn->state = LISTENER_STATE_READY;
connection_start_reading(conn); connection_start_reading(conn);
@ -227,8 +223,6 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st
newconn->bandwidth = -1; newconn->bandwidth = -1;
} }
/* learn things from parent, so we can perform auth */
memcpy(&newconn->local,&conn->local,sizeof(struct sockaddr_in));
newconn->address = strdup(inet_ntoa(remote.sin_addr)); /* remember the remote address */ newconn->address = strdup(inet_ntoa(remote.sin_addr)); /* remember the remote address */
if(connection_add(newconn) < 0) { /* no space, forget it */ if(connection_add(newconn) < 0) { /* no space, forget it */
@ -243,88 +237,53 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st
return 0; return 0;
} }
/* create the 'local' variable used below */
int learn_local(struct sockaddr_in *local) {
/* local host information */
char localhostname[512];
struct hostent *localhost;
/* obtain local host information */
if(gethostname(localhostname,512) < 0) {
log(LOG_ERR,"Error obtaining local hostname.");
return -1;
}
log(LOG_DEBUG,"learn_local: localhostname is '%s'.",localhostname);
localhost = gethostbyname(localhostname);
if (!localhost) {
log(LOG_ERR,"Error obtaining local host info.");
return -1;
}
memset((void *)local,0,sizeof(struct sockaddr_in));
local->sin_family = AF_INET;
memcpy((void *)&local->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
log(LOG_DEBUG,"learn_local: chose address as '%s'.",inet_ntoa(local->sin_addr));
return 0;
}
int retry_all_connections(int role, uint16_t or_listenport, int retry_all_connections(int role, uint16_t or_listenport,
uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport) {
/* start all connections that should be up but aren't */ /* start all connections that should be up but aren't */
struct sockaddr_in local; /* local address */ struct sockaddr_in bindaddr; /* where to bind */
if(learn_local(&local) < 0)
return -1;
local.sin_port = htons(or_listenport);
if(role & ROLE_OR_CONNECT_ALL) { if(role & ROLE_OR_CONNECT_ALL) {
router_retry_connections(&local); router_retry_connections();
} }
local.sin_addr.s_addr = htonl(INADDR_ANY); /* anyone can connect */ memset(&bindaddr,0,sizeof(struct sockaddr_in));
bindaddr.sin_family = AF_INET;
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* anyone can connect */
if(role & ROLE_OR_LISTEN) { if(role & ROLE_OR_LISTEN) {
bindaddr.sin_port = htons(or_listenport);
if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) { if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) {
connection_or_create_listener(&local); connection_or_create_listener(&bindaddr);
} }
} }
if(role & ROLE_OP_LISTEN) { if(role & ROLE_OP_LISTEN) {
local.sin_port = htons(op_listenport); bindaddr.sin_port = htons(op_listenport);
if(!connection_get_by_type(CONN_TYPE_OP_LISTENER)) { if(!connection_get_by_type(CONN_TYPE_OP_LISTENER)) {
connection_op_create_listener(&local); connection_op_create_listener(&bindaddr);
} }
} }
if(role & ROLE_DIR_LISTEN) { if(role & ROLE_DIR_LISTEN) {
local.sin_port = htons(dir_listenport); bindaddr.sin_port = htons(dir_listenport);
if(!connection_get_by_type(CONN_TYPE_DIR_LISTENER)) { if(!connection_get_by_type(CONN_TYPE_DIR_LISTENER)) {
connection_dir_create_listener(&local); connection_dir_create_listener(&bindaddr);
} }
} }
if(role & ROLE_AP_LISTEN) { if(role & ROLE_AP_LISTEN) {
local.sin_port = htons(ap_listenport); bindaddr.sin_port = htons(ap_listenport);
inet_aton("127.0.0.1", &(local.sin_addr)); /* the AP listens only on localhost! */ inet_aton("127.0.0.1", &(bindaddr.sin_addr)); /* the AP listens only on localhost! */
if(!connection_get_by_type(CONN_TYPE_AP_LISTENER)) { if(!connection_get_by_type(CONN_TYPE_AP_LISTENER)) {
connection_ap_create_listener(&local); connection_ap_create_listener(&bindaddr);
} }
} }
return 0; return 0;
} }
connection_t *connection_connect_to_router_as_op(routerinfo_t *router, uint16_t local_or_port) {
struct sockaddr_in local; /* local address */
if(learn_local(&local) < 0)
return NULL;
local.sin_port = htons(local_or_port);
return connection_or_connect_as_op(router, &local);
}
int connection_read_to_buf(connection_t *conn) { int connection_read_to_buf(connection_t *conn) {
int read_result; int read_result;
struct timeval now; struct timeval now;

View File

@ -205,7 +205,7 @@ int ap_handshake_establish_circuit(connection_t *conn, unsigned int *route, int
connection_stop_reading(conn); /* Stop listening for input from the AP! */ connection_stop_reading(conn); /* Stop listening for input from the AP! */
if(!n_conn) { /* launch the connection */ if(!n_conn) { /* launch the connection */
n_conn = connect_to_router_as_op(firsthop); n_conn = connection_or_connect_as_op(firsthop);
if(!n_conn) { /* connect failed, forget the whole thing */ if(!n_conn) { /* connect failed, forget the whole thing */
log(LOG_DEBUG,"ap_handshake_establish_circuit(): connect to firsthop failed. Closing."); log(LOG_DEBUG,"ap_handshake_establish_circuit(): connect to firsthop failed. Closing.");
circuit_close(circ); circuit_close(circ);
@ -393,9 +393,9 @@ int connection_ap_finished_flushing(connection_t *conn) {
} }
int connection_ap_create_listener(struct sockaddr_in *local) { int connection_ap_create_listener(struct sockaddr_in *bindaddr) {
log(LOG_DEBUG,"connection_create_ap_listener starting"); log(LOG_DEBUG,"connection_create_ap_listener starting");
return connection_create_listener(local, CONN_TYPE_AP_LISTENER); return connection_create_listener(bindaddr, CONN_TYPE_AP_LISTENER);
} }
int connection_ap_handle_listener_read(connection_t *conn) { int connection_ap_handle_listener_read(connection_t *conn) {

View File

@ -120,6 +120,7 @@ int connection_exit_process_data_cell(cell_t *cell, connection_t *conn) {
return -1; return -1;
} }
memcpy(&conn->addr, rent->h_addr,rent->h_length); memcpy(&conn->addr, rent->h_addr,rent->h_length);
conn->addr = ntohl(conn->addr); /* get it back to host order */
log(LOG_DEBUG,"connection_exit_process_data_cell(): addr is %s.",cell->payload); log(LOG_DEBUG,"connection_exit_process_data_cell(): addr is %s.",cell->payload);
} else if (!conn->port) { /* this cell contains the dest port */ } else if (!conn->port) { /* this cell contains the dest port */
if(!memchr(cell->payload,'\0',cell->length)) { if(!memchr(cell->payload,'\0',cell->length)) {
@ -143,7 +144,7 @@ int connection_exit_process_data_cell(cell_t *cell, connection_t *conn) {
memset((void *)&dest_addr,0,sizeof(dest_addr)); memset((void *)&dest_addr,0,sizeof(dest_addr));
dest_addr.sin_family = AF_INET; dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(conn->port); dest_addr.sin_port = htons(conn->port);
memcpy((void *)&dest_addr.sin_addr, &conn->addr, sizeof(uint32_t)); dest_addr.sin_addr.s_addr = htonl(conn->addr);
log(LOG_DEBUG,"connection_exit_process_data_cell(): Connecting to %s:%u.",conn->address,conn->port); log(LOG_DEBUG,"connection_exit_process_data_cell(): Connecting to %s:%u.",conn->address,conn->port);

View File

@ -110,9 +110,9 @@ int connection_op_finished_flushing(connection_t *conn) {
} }
int connection_op_create_listener(struct sockaddr_in *local) { int connection_op_create_listener(struct sockaddr_in *bindaddr) {
log(LOG_DEBUG,"connection_create_op_listener starting"); log(LOG_DEBUG,"connection_create_op_listener starting");
return connection_create_listener(local, CONN_TYPE_OP_LISTENER); return connection_create_listener(bindaddr, CONN_TYPE_OP_LISTENER);
} }
int connection_op_handle_listener_read(connection_t *conn) { int connection_op_handle_listener_read(connection_t *conn) {

View File

@ -142,8 +142,7 @@ void conn_or_init_crypto(connection_t *conn) {
* *result to 1 if connect() returned before completing, or to 2 * *result to 1 if connect() returned before completing, or to 2
* if it completed, and returns the new conn. * if it completed, and returns the new conn.
*/ */
connection_t *connection_or_connect(routerinfo_t *router, struct sockaddr_in *local, connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *result) {
uint16_t port, int *result) {
connection_t *conn; connection_t *conn;
struct sockaddr_in router_addr; struct sockaddr_in router_addr;
int s; int s;
@ -153,11 +152,11 @@ connection_t *connection_or_connect(routerinfo_t *router, struct sockaddr_in *lo
return NULL; return NULL;
/* set up conn so it's got all the data we need to remember */ /* set up conn so it's got all the data we need to remember */
conn->addr = router->addr, conn->port = router->or_port; /* NOTE we store or_port here always */ conn->addr = router->addr;
conn->port = router->or_port; /* NOTE we store or_port here always */
conn->bandwidth = router->bandwidth; conn->bandwidth = router->bandwidth;
conn->pkey = crypto_pk_dup_key(router->pkey); conn->pkey = crypto_pk_dup_key(router->pkey);
conn->address = strdup(router->address); conn->address = strdup(router->address);
memcpy(&conn->local,local,sizeof(struct sockaddr_in));
s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (s < 0) if (s < 0)
@ -171,9 +170,9 @@ connection_t *connection_or_connect(routerinfo_t *router, struct sockaddr_in *lo
memset((void *)&router_addr,0,sizeof(router_addr)); memset((void *)&router_addr,0,sizeof(router_addr));
router_addr.sin_family = AF_INET; router_addr.sin_family = AF_INET;
router_addr.sin_port = htons(port); router_addr.sin_port = htons(port);
router_addr.sin_addr.s_addr = router->addr; router_addr.sin_addr.s_addr = htonl(router->addr);
log(LOG_DEBUG,"connection_or_connect() : Trying to connect to %s:%u.",inet_ntoa(*(struct in_addr *)&router->addr),port); log(LOG_DEBUG,"connection_or_connect() : Trying to connect to %s:%u.",router->address,port);
if(connect(s,(struct sockaddr *)&router_addr,sizeof(router_addr)) < 0){ if(connect(s,(struct sockaddr *)&router_addr,sizeof(router_addr)) < 0){
if(errno != EINPROGRESS){ if(errno != EINPROGRESS){
@ -217,13 +216,13 @@ connection_t *connection_or_connect(routerinfo_t *router, struct sockaddr_in *lo
* *
*/ */
connection_t *connection_or_connect_as_op(routerinfo_t *router, struct sockaddr_in *local) { connection_t *connection_or_connect_as_op(routerinfo_t *router) {
connection_t *conn; connection_t *conn;
int result=0; /* so connection_or_connect() can tell us what happened */ int result=0; /* so connection_or_connect() can tell us what happened */
assert(router && local); assert(router);
if(router->addr == local->sin_addr.s_addr && router->or_port == ntohs(local->sin_port)) { if(router_is_me(router->addr, router->or_port)) {
/* this is me! don't connect to me. */ /* this is me! don't connect to me. */
log(LOG_WARNING,"connection_or_connect_as_op(): You just asked me to connect to myself."); log(LOG_WARNING,"connection_or_connect_as_op(): You just asked me to connect to myself.");
return NULL; return NULL;
@ -235,7 +234,7 @@ connection_t *connection_or_connect_as_op(routerinfo_t *router, struct sockaddr_
if(conn) if(conn)
return conn; return conn;
conn = connection_or_connect(router, local, router->op_port, &result); conn = connection_or_connect(router, router->op_port, &result);
if(!conn) if(!conn)
return NULL; return NULL;
@ -340,19 +339,19 @@ int or_handshake_op_finished_sending_keys(connection_t *conn) {
* *
*/ */
connection_t *connection_or_connect_as_or(routerinfo_t *router, struct sockaddr_in *local) { connection_t *connection_or_connect_as_or(routerinfo_t *router) {
connection_t *conn; connection_t *conn;
int result=0; /* so connection_or_connect() can tell us what happened */ int result=0; /* so connection_or_connect() can tell us what happened */
assert(router && local); assert(router);
if(router->addr == local->sin_addr.s_addr && router->or_port == ntohs(local->sin_port)) { if(router_is_me(router->addr, router->or_port)) {
/* this is me! don't connect to me. */ /* this is me! don't connect to me. */
log(LOG_DEBUG,"connection_or_connect_as_or(): This is me. Skipping."); log(LOG_DEBUG,"connection_or_connect_as_or(): This is me. Skipping.");
return NULL; return NULL;
} }
conn = connection_or_connect(router, local, router->or_port, &result); conn = connection_or_connect(router, router->or_port, &result);
if(!conn) if(!conn)
return NULL; return NULL;
@ -378,9 +377,13 @@ int or_handshake_client_send_auth(connection_t *conn) {
int retval; int retval;
char buf[44]; char buf[44];
char cipher[128]; char cipher[128];
struct sockaddr_in me; /* my router identity */
assert(conn); assert(conn);
if(learn_my_address(&me) < 0)
return -1;
/* generate random keys */ /* generate random keys */
if(crypto_cipher_generate_key(conn->f_crypto) || if(crypto_cipher_generate_key(conn->f_crypto) ||
crypto_cipher_generate_key(conn->b_crypto)) { crypto_cipher_generate_key(conn->b_crypto)) {
@ -390,8 +393,8 @@ int or_handshake_client_send_auth(connection_t *conn) {
log(LOG_DEBUG,"or_handshake_client_send_auth() : Generated DES keys."); log(LOG_DEBUG,"or_handshake_client_send_auth() : Generated DES keys.");
/* generate first message */ /* generate first message */
*(uint32_t*)buf = htonl(conn->local.sin_addr.s_addr); /* local address */ *(uint32_t*)buf = me.sin_addr.s_addr; /* local address, network order */
*(uint16_t*)(buf+4) = conn->local.sin_port; /* local port, already network order */ *(uint16_t*)(buf+4) = me.sin_port; /* local port, network order */
*(uint32_t*)(buf+6) = htonl(conn->addr); /* remote address */ *(uint32_t*)(buf+6) = htonl(conn->addr); /* remote address */
*(uint16_t*)(buf+10) = htons(conn->port); /* remote port */ *(uint16_t*)(buf+10) = htons(conn->port); /* remote port */
memcpy(buf+12,conn->f_crypto->key,8); /* keys */ memcpy(buf+12,conn->f_crypto->key,8); /* keys */
@ -440,9 +443,13 @@ int or_handshake_client_process_auth(connection_t *conn) {
char cipher[128]; char cipher[128];
uint32_t bandwidth; uint32_t bandwidth;
int retval; int retval;
struct sockaddr_in me; /* my router identity */
assert(conn); assert(conn);
if(learn_my_address(&me) < 0)
return -1;
if(conn->inbuf_datalen < 128) /* entire response available? */ if(conn->inbuf_datalen < 128) /* entire response available? */
return 0; /* not yet */ return 0; /* not yet */
@ -469,8 +476,8 @@ int or_handshake_client_process_auth(connection_t *conn) {
} }
log(LOG_DEBUG,"or_handshake_client_process_auth() : Decrypted response."); log(LOG_DEBUG,"or_handshake_client_process_auth() : Decrypted response.");
/* check validity */ /* check validity */
if ( (ntohl(*(uint32_t*)buf) != conn->local.sin_addr.s_addr) || /* local address */ if ( (*(uint32_t*)buf != me.sin_addr.s_addr) || /* local address, network order */
(*(uint16_t*)(buf+4) != conn->local.sin_port) || /* local port, keep network order */ (*(uint16_t*)(buf+4) != me.sin_port) || /* local port, network order */
(ntohl(*(uint32_t*)(buf+6)) != conn->addr) || /* remote address */ (ntohl(*(uint32_t*)(buf+6)) != conn->addr) || /* remote address */
(ntohs(*(uint16_t*)(buf+10)) != conn->port) || /* remote port */ (ntohs(*(uint16_t*)(buf+10)) != conn->port) || /* remote port */
(memcmp(conn->f_crypto->key, buf+12, 8)) || /* keys */ (memcmp(conn->f_crypto->key, buf+12, 8)) || /* keys */
@ -582,7 +589,7 @@ int or_handshake_server_process_auth(connection_t *conn) {
router = router_get_by_addr_port(addr,port); router = router_get_by_addr_port(addr,port);
if (!router) if (!router)
{ {
log(LOG_DEBUG,"or_handshake_server_process_auth() : Received a connection from an unknown router. Will drop."); log(LOG_DEBUG,"or_handshake_server_process_auth() : Received a connection from an unknown router '%s:%d'. Will drop.", conn->address, port);
return -1; return -1;
} }
log(LOG_DEBUG,"or_handshake_server_process_auth() : Router identified as %s:%u.", log(LOG_DEBUG,"or_handshake_server_process_auth() : Router identified as %s:%u.",
@ -664,9 +671,13 @@ int or_handshake_server_process_nonce(connection_t *conn) {
char buf[128]; char buf[128];
char cipher[128]; char cipher[128];
int retval; int retval;
struct sockaddr_in me; /* my router identity */
assert(conn); assert(conn);
if(learn_my_address(&me) < 0)
return -1;
if(conn->inbuf_datalen < 128) /* entire response available? */ if(conn->inbuf_datalen < 128) /* entire response available? */
return 0; /* not yet */ return 0; /* not yet */
@ -696,8 +707,8 @@ int or_handshake_server_process_nonce(connection_t *conn) {
/* check validity */ /* check validity */
if ((ntohl(*(uint32_t*)buf) != conn->addr) || /* remote address */ if ((ntohl(*(uint32_t*)buf) != conn->addr) || /* remote address */
(ntohs(*(uint16_t*)(buf+4)) != conn->port) || /* remote port */ (ntohs(*(uint16_t*)(buf+4)) != conn->port) || /* remote port */
(ntohl(*(uint32_t*)(buf+6)) != conn->local.sin_addr.s_addr) || /* local address */ (*(uint32_t*)(buf+6) != me.sin_addr.s_addr) || /* local address, network order */
(*(uint16_t*)(buf+10) != conn->local.sin_port) || /* local port, network order */ (*(uint16_t*)(buf+10) != me.sin_port) || /* local port, network order */
(memcmp(conn->nonce,buf+12,8))) /* nonce */ (memcmp(conn->nonce,buf+12,8))) /* nonce */
{ {
log(LOG_ERR,"Router %s:%u failed to authenticate. Either the key I have is obsolete or they're doing something they're not supposed to.",conn->address,conn->port); log(LOG_ERR,"Router %s:%u failed to authenticate. Either the key I have is obsolete or they're doing something they're not supposed to.",conn->address,conn->port);
@ -717,9 +728,9 @@ int or_handshake_server_process_nonce(connection_t *conn) {
/* ********************************** */ /* ********************************** */
int connection_or_create_listener(struct sockaddr_in *local) { int connection_or_create_listener(struct sockaddr_in *bindaddr) {
log(LOG_DEBUG,"connection_create_or_listener starting"); log(LOG_DEBUG,"connection_create_or_listener starting");
return connection_create_listener(local, CONN_TYPE_OR_LISTENER); return connection_create_listener(bindaddr, CONN_TYPE_OR_LISTENER);
} }
int connection_or_handle_listener_read(connection_t *conn) { int connection_or_handle_listener_read(connection_t *conn) {

View File

@ -54,9 +54,9 @@ void directory_initiate_fetch(routerinfo_t *router) {
memset((void *)&router_addr,0,sizeof(router_addr)); memset((void *)&router_addr,0,sizeof(router_addr));
router_addr.sin_family = AF_INET; router_addr.sin_family = AF_INET;
router_addr.sin_port = htons(router->dir_port); router_addr.sin_port = htons(router->dir_port);
router_addr.sin_addr.s_addr = router->addr; router_addr.sin_addr.s_addr = htonl(router->addr);
log(LOG_DEBUG,"directory_initiate_fetch(): Trying to connect to %s:%u.",inet_ntoa(*(struct in_addr *)&router->addr),router->dir_port); log(LOG_DEBUG,"directory_initiate_fetch(): Trying to connect to %s:%u.",router->address,router->dir_port);
if(connect(s,(struct sockaddr *)&router_addr,sizeof(router_addr)) < 0){ if(connect(s,(struct sockaddr *)&router_addr,sizeof(router_addr)) < 0){
if(errno != EINPROGRESS){ if(errno != EINPROGRESS){
@ -133,15 +133,11 @@ int connection_dir_process_inbuf(connection_t *conn) {
log(LOG_DEBUG,"connection_dir_process_inbuf(): Empty directory. Ignoring."); log(LOG_DEBUG,"connection_dir_process_inbuf(): Empty directory. Ignoring.");
return -1; return -1;
} }
if(router_get_list_from_string(the_directory, options.ORPort) < 0) { if(router_get_list_from_string(the_directory) < 0) {
log(LOG_DEBUG,"connection_dir_process_inbuf(): ...but parsing failed. Ignoring."); log(LOG_DEBUG,"connection_dir_process_inbuf(): ...but parsing failed. Ignoring.");
} }
if(options.Role & ROLE_OR_CONNECT_ALL) { /* connect to them all */ if(options.Role & ROLE_OR_CONNECT_ALL) { /* connect to them all */
struct sockaddr_in local; /* local address */ router_retry_connections();
if(learn_local(&local) < 0)
return -1;
local.sin_port = htons(options.ORPort);
router_retry_connections(&local);
} }
return -1; return -1;
} }
@ -277,9 +273,9 @@ int connection_dir_finished_flushing(connection_t *conn) {
return 0; return 0;
} }
int connection_dir_create_listener(struct sockaddr_in *local) { int connection_dir_create_listener(struct sockaddr_in *bindaddr) {
log(LOG_DEBUG,"connection_create_dir_listener starting"); log(LOG_DEBUG,"connection_create_dir_listener starting");
return connection_create_listener(local, CONN_TYPE_DIR_LISTENER); return connection_create_listener(bindaddr, CONN_TYPE_DIR_LISTENER);
} }
int connection_dir_handle_listener_read(connection_t *conn) { int connection_dir_handle_listener_read(connection_t *conn) {

View File

@ -162,11 +162,6 @@ connection_t *connection_get_by_type(int type) {
/* FIXME can we cut this function out? */
connection_t *connect_to_router_as_op(routerinfo_t *router) {
return connection_connect_to_router_as_op(router, options.ORPort);
}
void connection_watch_events(connection_t *conn, short events) { void connection_watch_events(connection_t *conn, short events) {
assert(conn && conn->poll_index < nfds); assert(conn && conn->poll_index < nfds);
@ -446,7 +441,7 @@ int do_main_loop(void) {
crypto_pk_env_t *prkey; crypto_pk_env_t *prkey;
/* load the routers file */ /* load the routers file */
if(router_get_list_from_file(options.RouterFile, options.ORPort) < 0) { if(router_get_list_from_file(options.RouterFile) < 0) {
log(LOG_ERR,"Error loading router list."); log(LOG_ERR,"Error loading router list.");
return -1; return -1;
} }
@ -478,7 +473,7 @@ int do_main_loop(void) {
} }
if(please_fetch_directory) { if(please_fetch_directory) {
if(options.Role & ROLE_DIR_SERVER) { if(options.Role & ROLE_DIR_SERVER) {
if(router_get_list_from_file(options.RouterFile, options.ORPort) < 0) { if(router_get_list_from_file(options.RouterFile) < 0) {
log(LOG_ERR,"Error reloading router list. Continuing with old list."); log(LOG_ERR,"Error reloading router list. Continuing with old list.");
} }
} else { } else {

View File

@ -29,6 +29,10 @@ int decide_aci_type(uint32_t local_addr, uint16_t local_port,
int process_onion(circuit_t *circ, connection_t *conn) { int process_onion(circuit_t *circ, connection_t *conn) {
aci_t aci_type; aci_t aci_type;
struct sockaddr_in me; /* my router identity */
if(learn_my_address(&me) < 0)
return -1;
if(!decrypt_onion((onion_layer_t *)circ->onion,circ->onionlen,getprivatekey())) { if(!decrypt_onion((onion_layer_t *)circ->onion,circ->onionlen,getprivatekey())) {
log(LOG_DEBUG,"command_process_create_cell(): decrypt_onion() failed, closing circuit."); log(LOG_DEBUG,"command_process_create_cell(): decrypt_onion() failed, closing circuit.");
@ -43,7 +47,7 @@ int process_onion(circuit_t *circ, connection_t *conn) {
return -1; return -1;
} }
aci_type = decide_aci_type(conn->local.sin_addr.s_addr, ntohs(conn->local.sin_port), aci_type = decide_aci_type(ntohl(me.sin_addr.s_addr), ntohs(me.sin_port),
((onion_layer_t *)circ->onion)->addr,((onion_layer_t *)circ->onion)->port); ((onion_layer_t *)circ->onion)->addr,((onion_layer_t *)circ->onion)->port);
if(circuit_init(circ, aci_type) < 0) { if(circuit_init(circ, aci_type) < 0) {

View File

@ -216,7 +216,7 @@ typedef struct
// struct timeval lastsend; /* time of last transmission to the client */ // struct timeval lastsend; /* time of last transmission to the client */
// struct timeval interval; /* transmission interval */ // struct timeval interval; /* transmission interval */
uint32_t addr; /* these two uniquely identify a router */ uint32_t addr; /* these two uniquely identify a router. Both in host order. */
uint16_t port; uint16_t port;
/* used by exit and ap: */ /* used by exit and ap: */
@ -228,15 +228,11 @@ typedef struct
char read_username; char read_username;
char *dest_addr; char *dest_addr;
uint16_t dest_port; uint16_t dest_port; /* host order */
char dest_tmp[512]; char dest_tmp[512];
int dest_tmplen; int dest_tmplen;
/* used by OR, to keep state while connect()ing: Kludge. */
struct sockaddr_in local;
#if 0 /* obsolete, we now use conn->bandwidth */ #if 0 /* obsolete, we now use conn->bandwidth */
/* link info */ /* link info */
uint32_t min; uint32_t min;
@ -255,7 +251,7 @@ typedef struct
{ {
char *address; char *address;
uint32_t addr; uint32_t addr; /* all host order */
uint16_t or_port; uint16_t or_port;
uint16_t op_port; uint16_t op_port;
uint16_t ap_port; uint16_t ap_port;
@ -462,15 +458,13 @@ connection_t *connection_new(int type);
void connection_free(connection_t *conn); void connection_free(connection_t *conn);
int connection_create_listener(struct sockaddr_in *local, int type); int connection_create_listener(struct sockaddr_in *bindaddr, int type);
int connection_handle_listener_read(connection_t *conn, int new_type, int new_state); int connection_handle_listener_read(connection_t *conn, int new_type, int new_state);
/* start all connections that should be up but aren't */ /* start all connections that should be up but aren't */
int learn_local(struct sockaddr_in *local);
int retry_all_connections(int role, uint16_t or_listenport, int retry_all_connections(int role, uint16_t or_listenport,
uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport); uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport);
connection_t *connection_connect_to_router_as_op(routerinfo_t *router, uint16_t local_or_port);
int connection_read_to_buf(connection_t *conn); int connection_read_to_buf(connection_t *conn);
@ -527,7 +521,7 @@ int connection_ap_process_data_cell(cell_t *cell, connection_t *conn);
int connection_ap_finished_flushing(connection_t *conn); int connection_ap_finished_flushing(connection_t *conn);
int connection_ap_create_listener(struct sockaddr_in *local); int connection_ap_create_listener(struct sockaddr_in *bindaddr);
int connection_ap_handle_listener_read(connection_t *conn); int connection_ap_handle_listener_read(connection_t *conn);
@ -549,7 +543,7 @@ int connection_op_process_inbuf(connection_t *conn);
int connection_op_finished_flushing(connection_t *conn); int connection_op_finished_flushing(connection_t *conn);
int connection_op_create_listener(struct sockaddr_in *local); int connection_op_create_listener(struct sockaddr_in *bindaddr);
int connection_op_handle_listener_read(connection_t *conn); int connection_op_handle_listener_read(connection_t *conn);
@ -569,11 +563,11 @@ int or_handshake_client_send_auth(connection_t *conn);
int or_handshake_server_process_auth(connection_t *conn); int or_handshake_server_process_auth(connection_t *conn);
int or_handshake_server_process_nonce(connection_t *conn); int or_handshake_server_process_nonce(connection_t *conn);
connection_t *connect_to_router_as_or(routerinfo_t *router, struct sockaddr_in *local); connection_t *connect_to_router_as_or(routerinfo_t *router);
connection_t *connection_or_connect_as_or(routerinfo_t *router, struct sockaddr_in *local); connection_t *connection_or_connect_as_or(routerinfo_t *router);
connection_t *connection_or_connect_as_op(routerinfo_t *router, struct sockaddr_in *local); connection_t *connection_or_connect_as_op(routerinfo_t *router);
int connection_or_create_listener(struct sockaddr_in *local); int connection_or_create_listener(struct sockaddr_in *bindaddr);
int connection_or_handle_listener_read(connection_t *conn); int connection_or_handle_listener_read(connection_t *conn);
/********************************* directory.c ***************************/ /********************************* directory.c ***************************/
@ -585,7 +579,7 @@ int connection_dir_process_inbuf(connection_t *conn);
int directory_handle_command(connection_t *conn); int directory_handle_command(connection_t *conn);
int directory_handle_reading(connection_t *conn); int directory_handle_reading(connection_t *conn);
int connection_dir_finished_flushing(connection_t *conn); int connection_dir_finished_flushing(connection_t *conn);
int connection_dir_create_listener(struct sockaddr_in *local); int connection_dir_create_listener(struct sockaddr_in *bindaddr);
int connection_dir_handle_listener_read(connection_t *conn); int connection_dir_handle_listener_read(connection_t *conn);
/********************************* main.c ***************************/ /********************************* main.c ***************************/
@ -601,8 +595,6 @@ connection_t *connection_exact_get_by_addr_port(uint32_t addr, uint16_t port);
connection_t *connection_get_by_type(int type); connection_t *connection_get_by_type(int type);
connection_t *connect_to_router_as_op(routerinfo_t *router);
void connection_watch_events(connection_t *conn, short events); void connection_watch_events(connection_t *conn, short events);
void connection_stop_reading(connection_t *conn); void connection_stop_reading(connection_t *conn);
void connection_start_reading(connection_t *conn); void connection_start_reading(connection_t *conn);
@ -665,14 +657,16 @@ crypto_cipher_env_t *create_onion_cipher(int cipher_type, char *key, char *iv, i
/********************************* routers.c ***************************/ /********************************* routers.c ***************************/
void router_retry_connections(struct sockaddr_in *local); int learn_my_address(struct sockaddr_in *me);
void router_retry_connections(void);
routerinfo_t *router_pick_directory_server(void); routerinfo_t *router_pick_directory_server(void);
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
unsigned int *router_new_route(int *routelen); unsigned int *router_new_route(int *routelen);
unsigned char *router_create_onion(unsigned int *route, int routelen, int *len, crypt_path_t **cpath); unsigned char *router_create_onion(unsigned int *route, int routelen, int *len, crypt_path_t **cpath);
int router_is_me(uint32_t addr, uint16_t port);
routerinfo_t *router_get_first_in_route(unsigned int *route, int routelen); routerinfo_t *router_get_first_in_route(unsigned int *route, int routelen);
void router_forget_router(uint32_t addr, uint16_t port); void router_forget_router(uint32_t addr, uint16_t port);
int router_get_list_from_file(char *routerfile, uint16_t or_listenport); int router_get_list_from_file(char *routerfile);
int router_get_list_from_string(char *s, uint16_t or_listenport); int router_get_list_from_string(char *s);
#endif #endif

View File

@ -26,7 +26,6 @@ extern routerinfo_t *my_routerinfo; /* from main.c */
/****************************************************************************/ /****************************************************************************/
/* static function prototypes */ /* static function prototypes */
static int router_is_me(uint32_t or_address, uint16_t or_listenport, uint16_t my_or_listenport);
static void routerlist_free(routerinfo_t *list); static void routerlist_free(routerinfo_t *list);
static routerinfo_t **make_rarray(routerinfo_t* list, int *len); static routerinfo_t **make_rarray(routerinfo_t* list, int *len);
static char *eat_whitespace(char *s); static char *eat_whitespace(char *s);
@ -35,7 +34,32 @@ static routerinfo_t *router_get_entry_from_string(char **s);
/****************************************************************************/ /****************************************************************************/
void router_retry_connections(struct sockaddr_in *local) { int learn_my_address(struct sockaddr_in *me) {
/* local host information */
char localhostname[512];
struct hostent *localhost;
/* obtain local host information */
if(gethostname(localhostname,512) < 0) {
log(LOG_ERR,"Error obtaining local hostname.");
return -1;
}
log(LOG_DEBUG,"learn_my_address(): localhostname is '%s'.",localhostname);
localhost = gethostbyname(localhostname);
if (!localhost) {
log(LOG_ERR,"Error obtaining local host info.");
return -1;
}
memset((void *)me,0,sizeof(struct sockaddr_in));
me->sin_family = AF_INET;
memcpy((void *)&me->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
me->sin_port = htons(options.ORPort);
log(LOG_DEBUG,"learn_my_address(): chose address as '%s'.",inet_ntoa(me->sin_addr));
return 0;
}
void router_retry_connections(void) {
int i; int i;
routerinfo_t *router; routerinfo_t *router;
@ -43,7 +67,7 @@ void router_retry_connections(struct sockaddr_in *local) {
router = router_array[i]; router = router_array[i];
if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */ if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */
log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,router->or_port); log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,router->or_port);
connection_or_connect_as_or(router, local); connection_or_connect_as_or(router);
} }
} }
} }
@ -94,9 +118,27 @@ unsigned char *router_create_onion(unsigned int *route, int routelen, int *len,
return create_onion(router_array,rarray_len,route,routelen,len,cpath); return create_onion(router_array,rarray_len,route,routelen,len,cpath);
} }
/* private function, to determine whether the current entry in the router list is actually us */ /* return 1 if addr and port corresponds to my addr and my or_listenport. else 0,
static int router_is_me(uint32_t or_address, uint16_t or_listenport, uint16_t my_or_listenport) * or -1 for failure.
*/
int router_is_me(uint32_t addr, uint16_t port)
{ {
struct sockaddr_in me; /* my router identity */
if(!ROLE_IS_OR(global_role)) {
/* we're not an OR. This obviously isn't us. */
return 0;
}
if(learn_my_address(&me) < 0)
return -1;
if(ntohl(me.sin_addr.s_addr) == addr && ntohs(me.sin_port) == port)
return 1;
return 0;
#if 0
/* local host information */ /* local host information */
char localhostname[512]; char localhostname[512];
struct hostent *localhost; struct hostent *localhost;
@ -106,11 +148,6 @@ static int router_is_me(uint32_t or_address, uint16_t or_listenport, uint16_t my
char *addr = NULL; char *addr = NULL;
int i = 0; int i = 0;
if(!ROLE_IS_OR(global_role)) {
/* we're not an OR. This obviously isn't us. */
return 0;
}
/* obtain local host information */ /* obtain local host information */
if (gethostname(localhostname,512) < 0) { if (gethostname(localhostname,512) < 0) {
log(LOG_ERR,"router_is_me(): Error obtaining local hostname."); log(LOG_ERR,"router_is_me(): Error obtaining local hostname.");
@ -144,8 +181,9 @@ static int router_is_me(uint32_t or_address, uint16_t or_listenport, uint16_t my
addr = localhost->h_addr_list[i++]; addr = localhost->h_addr_list[i++];
} }
return 0; return 0;
#endif
} }
/* delete a list of routers from memory */ /* delete a list of routers from memory */
@ -244,7 +282,7 @@ static routerinfo_t **make_rarray(routerinfo_t* list, int *len)
/* load the router list */ /* load the router list */
int router_get_list_from_file(char *routerfile, uint16_t or_listenport) int router_get_list_from_file(char *routerfile)
{ {
int fd; /* router file */ int fd; /* router file */
struct stat statbuf; struct stat statbuf;
@ -285,7 +323,7 @@ int router_get_list_from_file(char *routerfile, uint16_t or_listenport)
string[statbuf.st_size] = 0; /* null terminate it */ string[statbuf.st_size] = 0; /* null terminate it */
if(router_get_list_from_string(string, or_listenport) < 0) { if(router_get_list_from_string(string) < 0) {
log(LOG_ERR,"router_get_list_from_file(): The routerfile itself was corrupt."); log(LOG_ERR,"router_get_list_from_file(): The routerfile itself was corrupt.");
free(string); free(string);
return -1; return -1;
@ -295,7 +333,7 @@ int router_get_list_from_file(char *routerfile, uint16_t or_listenport)
return 0; return 0;
} }
int router_get_list_from_string(char *s, uint16_t or_listenport) { int router_get_list_from_string(char *s) {
routerinfo_t *routerlist=NULL; routerinfo_t *routerlist=NULL;
routerinfo_t *router; routerinfo_t *router;
routerinfo_t **new_router_array; routerinfo_t **new_router_array;
@ -309,12 +347,19 @@ int router_get_list_from_string(char *s, uint16_t or_listenport) {
routerlist_free(routerlist); routerlist_free(routerlist);
return -1; return -1;
} }
if(!router_is_me(router->addr, router->or_port, or_listenport)) { switch(router_is_me(router->addr, router->or_port)) {
router->next = routerlist; case 0: /* it's not me */
routerlist = router; router->next = routerlist;
} else { routerlist = router;
if(!my_routerinfo) /* save it, so we can use it for directories */ break;
my_routerinfo = router; case 1: /* it is me */
if(!my_routerinfo) /* save it, so we can use it for directories */
my_routerinfo = router;
break;
default:
log(LOG_ERR,"router_get_list_from_string(): router_is_me returned error.");
routerlist_free(routerlist);
return -1;
} }
s = eat_whitespace(s); s = eat_whitespace(s);
} }
@ -392,6 +437,7 @@ static routerinfo_t *router_get_entry_from_string(char **s) {
} }
assert(rent->h_length == 4); assert(rent->h_length == 4);
memcpy(&router->addr, rent->h_addr,rent->h_length); memcpy(&router->addr, rent->h_addr,rent->h_length);
router->addr = ntohl(router->addr); /* get it back into host order */
/* read router->or_port */ /* read router->or_port */
NEXT_TOKEN(s, next); NEXT_TOKEN(s, next);