diff --git a/src/or/connection.c b/src/or/connection.c index b30f5cb8a2..1a8ab8ae4e 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -148,7 +148,7 @@ void connection_free(connection_t *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; int s; 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)); - if(bind(s,(struct sockaddr *)local,sizeof(*local)) < 0) { + if(bind(s,(struct sockaddr *)bindaddr,sizeof(*bindaddr)) < 0) { 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; } - /* start local server */ 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; } @@ -189,10 +188,7 @@ int connection_create_listener(struct sockaddr_in *local, int type) { return -1; } - /* remember things so you can tell the baby sockets */ - memcpy(&conn->local,local,sizeof(struct sockaddr_in)); - - log(LOG_DEBUG,"connection_create_listener(): Listening on local port %u.",ntohs(local->sin_port)); + log(LOG_DEBUG,"connection_create_listener(): Listening on port %u.",ntohs(bindaddr->sin_port)); conn->state = LISTENER_STATE_READY; 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; } - /* 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 */ 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; } -/* 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, uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { /* 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) { - 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) { + bindaddr.sin_port = htons(or_listenport); if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) { - connection_or_create_listener(&local); + connection_or_create_listener(&bindaddr); } } 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)) { - connection_op_create_listener(&local); + connection_op_create_listener(&bindaddr); } } 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)) { - connection_dir_create_listener(&local); + connection_dir_create_listener(&bindaddr); } } if(role & ROLE_AP_LISTEN) { - local.sin_port = htons(ap_listenport); - inet_aton("127.0.0.1", &(local.sin_addr)); /* the AP listens only on localhost! */ + bindaddr.sin_port = htons(ap_listenport); + inet_aton("127.0.0.1", &(bindaddr.sin_addr)); /* the AP listens only on localhost! */ if(!connection_get_by_type(CONN_TYPE_AP_LISTENER)) { - connection_ap_create_listener(&local); + connection_ap_create_listener(&bindaddr); } } 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 read_result; struct timeval now; diff --git a/src/or/connection_ap.c b/src/or/connection_ap.c index 3751beae46..d268f5b782 100644 --- a/src/or/connection_ap.c +++ b/src/or/connection_ap.c @@ -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! */ 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 */ log(LOG_DEBUG,"ap_handshake_establish_circuit(): connect to firsthop failed. Closing."); 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"); - 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) { diff --git a/src/or/connection_exit.c b/src/or/connection_exit.c index b69cf3541b..cc3e5ffc99 100644 --- a/src/or/connection_exit.c +++ b/src/or/connection_exit.c @@ -120,6 +120,7 @@ int connection_exit_process_data_cell(cell_t *cell, connection_t *conn) { return -1; } 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); } else if (!conn->port) { /* this cell contains the dest port */ 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)); dest_addr.sin_family = AF_INET; 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); diff --git a/src/or/connection_op.c b/src/or/connection_op.c index 4f705f59c5..993646947a 100644 --- a/src/or/connection_op.c +++ b/src/or/connection_op.c @@ -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"); - 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) { diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 7c8b5304a2..3bb9c33b7f 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -142,8 +142,7 @@ void conn_or_init_crypto(connection_t *conn) { * *result to 1 if connect() returned before completing, or to 2 * if it completed, and returns the new conn. */ -connection_t *connection_or_connect(routerinfo_t *router, struct sockaddr_in *local, - uint16_t port, int *result) { +connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *result) { connection_t *conn; struct sockaddr_in router_addr; int s; @@ -153,11 +152,11 @@ connection_t *connection_or_connect(routerinfo_t *router, struct sockaddr_in *lo return NULL; /* 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->pkey = crypto_pk_dup_key(router->pkey); conn->address = strdup(router->address); - memcpy(&conn->local,local,sizeof(struct sockaddr_in)); s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); 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)); router_addr.sin_family = AF_INET; 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(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; 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. */ log(LOG_WARNING,"connection_or_connect_as_op(): You just asked me to connect to myself."); return NULL; @@ -235,7 +234,7 @@ connection_t *connection_or_connect_as_op(routerinfo_t *router, struct sockaddr_ if(conn) return conn; - conn = connection_or_connect(router, local, router->op_port, &result); + conn = connection_or_connect(router, router->op_port, &result); if(!conn) 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; 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. */ log(LOG_DEBUG,"connection_or_connect_as_or(): This is me. Skipping."); return NULL; } - conn = connection_or_connect(router, local, router->or_port, &result); + conn = connection_or_connect(router, router->or_port, &result); if(!conn) return NULL; @@ -378,9 +377,13 @@ int or_handshake_client_send_auth(connection_t *conn) { int retval; char buf[44]; char cipher[128]; + struct sockaddr_in me; /* my router identity */ assert(conn); + if(learn_my_address(&me) < 0) + return -1; + /* generate random keys */ if(crypto_cipher_generate_key(conn->f_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."); /* generate first message */ - *(uint32_t*)buf = htonl(conn->local.sin_addr.s_addr); /* local address */ - *(uint16_t*)(buf+4) = conn->local.sin_port; /* local port, already network order */ + *(uint32_t*)buf = me.sin_addr.s_addr; /* local address, network order */ + *(uint16_t*)(buf+4) = me.sin_port; /* local port, network order */ *(uint32_t*)(buf+6) = htonl(conn->addr); /* remote address */ *(uint16_t*)(buf+10) = htons(conn->port); /* remote port */ 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]; uint32_t bandwidth; int retval; + struct sockaddr_in me; /* my router identity */ assert(conn); + if(learn_my_address(&me) < 0) + return -1; + if(conn->inbuf_datalen < 128) /* entire response available? */ 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."); /* check validity */ - if ( (ntohl(*(uint32_t*)buf) != conn->local.sin_addr.s_addr) || /* local address */ - (*(uint16_t*)(buf+4) != conn->local.sin_port) || /* local port, keep network order */ + if ( (*(uint32_t*)buf != me.sin_addr.s_addr) || /* local address, network order */ + (*(uint16_t*)(buf+4) != me.sin_port) || /* local port, network order */ (ntohl(*(uint32_t*)(buf+6)) != conn->addr) || /* remote address */ (ntohs(*(uint16_t*)(buf+10)) != conn->port) || /* remote port */ (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); 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; } 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 cipher[128]; int retval; + struct sockaddr_in me; /* my router identity */ assert(conn); + if(learn_my_address(&me) < 0) + return -1; + if(conn->inbuf_datalen < 128) /* entire response available? */ return 0; /* not yet */ @@ -696,8 +707,8 @@ int or_handshake_server_process_nonce(connection_t *conn) { /* check validity */ if ((ntohl(*(uint32_t*)buf) != conn->addr) || /* remote address */ (ntohs(*(uint16_t*)(buf+4)) != conn->port) || /* remote port */ - (ntohl(*(uint32_t*)(buf+6)) != conn->local.sin_addr.s_addr) || /* local address */ - (*(uint16_t*)(buf+10) != conn->local.sin_port) || /* local port, network order */ + (*(uint32_t*)(buf+6) != me.sin_addr.s_addr) || /* local address, network order */ + (*(uint16_t*)(buf+10) != me.sin_port) || /* local port, network order */ (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); @@ -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"); - 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) { diff --git a/src/or/directory.c b/src/or/directory.c index 12e5f9dfac..fb87be00a4 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -54,9 +54,9 @@ void directory_initiate_fetch(routerinfo_t *router) { memset((void *)&router_addr,0,sizeof(router_addr)); router_addr.sin_family = AF_INET; 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(errno != EINPROGRESS){ @@ -133,15 +133,11 @@ int connection_dir_process_inbuf(connection_t *conn) { log(LOG_DEBUG,"connection_dir_process_inbuf(): Empty directory. Ignoring."); 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."); } if(options.Role & ROLE_OR_CONNECT_ALL) { /* connect to them all */ - struct sockaddr_in local; /* local address */ - if(learn_local(&local) < 0) - return -1; - local.sin_port = htons(options.ORPort); - router_retry_connections(&local); + router_retry_connections(); } return -1; } @@ -277,9 +273,9 @@ int connection_dir_finished_flushing(connection_t *conn) { 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"); - 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) { diff --git a/src/or/main.c b/src/or/main.c index 971a34b8b1..36df1f1a49 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -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) { assert(conn && conn->poll_index < nfds); @@ -446,7 +441,7 @@ int do_main_loop(void) { crypto_pk_env_t *prkey; /* 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."); return -1; } @@ -478,7 +473,7 @@ int do_main_loop(void) { } if(please_fetch_directory) { 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."); } } else { diff --git a/src/or/onion.c b/src/or/onion.c index 5dcfebe68c..3417645844 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -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) { 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())) { 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; } - 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); if(circuit_init(circ, aci_type) < 0) { diff --git a/src/or/or.h b/src/or/or.h index b16b00dd99..96ad9fb0c9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -216,7 +216,7 @@ typedef struct // struct timeval lastsend; /* time of last transmission to the client */ // 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; /* used by exit and ap: */ @@ -228,15 +228,11 @@ typedef struct char read_username; char *dest_addr; - uint16_t dest_port; + uint16_t dest_port; /* host order */ char dest_tmp[512]; 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 */ /* link info */ uint32_t min; @@ -255,7 +251,7 @@ typedef struct { char *address; - uint32_t addr; + uint32_t addr; /* all host order */ uint16_t or_port; uint16_t op_port; uint16_t ap_port; @@ -462,15 +458,13 @@ connection_t *connection_new(int type); 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); /* 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, 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); @@ -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_create_listener(struct sockaddr_in *local); +int connection_ap_create_listener(struct sockaddr_in *bindaddr); 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_create_listener(struct sockaddr_in *local); +int connection_op_create_listener(struct sockaddr_in *bindaddr); 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_nonce(connection_t *conn); -connection_t *connect_to_router_as_or(routerinfo_t *router, struct sockaddr_in *local); -connection_t *connection_or_connect_as_or(routerinfo_t *router, struct sockaddr_in *local); -connection_t *connection_or_connect_as_op(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); +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); /********************************* directory.c ***************************/ @@ -585,7 +579,7 @@ int connection_dir_process_inbuf(connection_t *conn); int directory_handle_command(connection_t *conn); int directory_handle_reading(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); /********************************* 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 *connect_to_router_as_op(routerinfo_t *router); - void connection_watch_events(connection_t *conn, short events); void connection_stop_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 ***************************/ -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_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); +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, uint16_t or_listenport); -int router_get_list_from_string(char *s, uint16_t or_listenport); +int router_get_list_from_file(char *routerfile); +int router_get_list_from_string(char *s); #endif diff --git a/src/or/routers.c b/src/or/routers.c index f40a5d889a..81a7cf34bb 100644 --- a/src/or/routers.c +++ b/src/or/routers.c @@ -26,7 +26,6 @@ extern routerinfo_t *my_routerinfo; /* from main.c */ /****************************************************************************/ /* 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 routerinfo_t **make_rarray(routerinfo_t* list, int *len); 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; routerinfo_t *router; @@ -43,7 +67,7 @@ void router_retry_connections(struct sockaddr_in *local) { router = router_array[i]; 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); - 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); } -/* private function, to determine whether the current entry in the router list is actually us */ -static int router_is_me(uint32_t or_address, uint16_t or_listenport, uint16_t my_or_listenport) +/* return 1 if addr and port corresponds to my addr and my or_listenport. else 0, + * 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 */ char localhostname[512]; 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; 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 */ if (gethostname(localhostname,512) < 0) { 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++]; } - + return 0; +#endif } /* 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 */ -int router_get_list_from_file(char *routerfile, uint16_t or_listenport) +int router_get_list_from_file(char *routerfile) { int fd; /* router file */ 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 */ - 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."); free(string); return -1; @@ -295,7 +333,7 @@ int router_get_list_from_file(char *routerfile, uint16_t or_listenport) 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 *router; routerinfo_t **new_router_array; @@ -309,12 +347,19 @@ int router_get_list_from_string(char *s, uint16_t or_listenport) { routerlist_free(routerlist); return -1; } - if(!router_is_me(router->addr, router->or_port, or_listenport)) { - router->next = routerlist; - routerlist = router; - } else { - if(!my_routerinfo) /* save it, so we can use it for directories */ - my_routerinfo = router; + switch(router_is_me(router->addr, router->or_port)) { + case 0: /* it's not me */ + router->next = routerlist; + routerlist = router; + break; + 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); } @@ -392,6 +437,7 @@ static routerinfo_t *router_get_entry_from_string(char **s) { } assert(rent->h_length == 4); memcpy(&router->addr, rent->h_addr,rent->h_length); + router->addr = ntohl(router->addr); /* get it back into host order */ /* read router->or_port */ NEXT_TOKEN(s, next);