diff options
author | Nick Mathewson <nickm@torproject.org> | 2008-08-05 20:08:19 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2008-08-05 20:08:19 +0000 |
commit | 960a0f0a994ba23480e14ffe5179160194fd9616 (patch) | |
tree | 250494775699fda2f0f543a350b02e89c5a77a03 /src/or/connection.c | |
parent | 750bb795ac1fcb5b76b6488690400c77fbff0a3f (diff) | |
download | tor-960a0f0a994ba23480e14ffe5179160194fd9616.tar.gz tor-960a0f0a994ba23480e14ffe5179160194fd9616.zip |
r17641@31-33-44: nickm | 2008-08-05 16:07:53 -0400
Initial conversion of uint32_t addr to tor_addr_t addr in connection_t and related types. Most of the Tor wire formats using these new types are in, but the code to generate and use it is not. This is a big patch. Let me know what it breaks for you.
svn:r16435
Diffstat (limited to 'src/or/connection.c')
-rw-r--r-- | src/or/connection.c | 140 |
1 files changed, 90 insertions, 50 deletions
diff --git a/src/or/connection.c b/src/or/connection.c index 8c7cca1ba9..c415af8989 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -907,24 +907,36 @@ connection_create_listener(struct sockaddr *listensockaddr, int type, /** Do basic sanity checking on a newly received socket. Return 0 * if it looks ok, else return -1. */ static int -check_sockaddr_in(struct sockaddr *sa, int len, int level) +check_sockaddr(struct sockaddr *sa, int len, int level) { int ok = 1; - struct sockaddr_in *sin=(struct sockaddr_in*)sa; - if (len != sizeof(struct sockaddr_in)) { - log_fn(level, LD_NET, "Length of address not as expected: %d vs %d", - len,(int)sizeof(struct sockaddr_in)); - ok = 0; - } - if (sa->sa_family != AF_INET) { - log_fn(level, LD_NET, "Family of address not as expected: %d vs %d", - sa->sa_family, AF_INET); - ok = 0; - } - if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) { - log_fn(level, LD_NET, - "Address for new connection has address/port equal to zero."); + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin=(struct sockaddr_in*)sa; + if (len != sizeof(struct sockaddr_in)) { + log_fn(level, LD_NET, "Length of address not as expected: %d vs %d", + len,(int)sizeof(struct sockaddr_in)); + ok = 0; + } + if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) { + log_fn(level, LD_NET, + "Address for new connection has address/port equal to zero."); + ok = 0; + } + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6=(struct sockaddr_in6*)sa; + if (len != sizeof(struct sockaddr_in6)) { + log_fn(level, LD_NET, "Length of address not as expected: %d vs %d", + len,(int)sizeof(struct sockaddr_in6)); + ok = 0; + } + if (tor_mem_is_zero((void*)sin6->sin6_addr.s6_addr, 16) || + sin6->sin6_port == 0) { + log_fn(level, LD_NET, + "Address for new connection has address/port equal to zero."); + ok = 0; + } + } else { ok = 0; } return ok ? 0 : -1; @@ -939,17 +951,16 @@ connection_handle_listener_read(connection_t *conn, int new_type) int news; /* the new socket */ connection_t *newconn; /* information about the remote peer when connecting to other routers */ - struct sockaddr_in remote; char addrbuf[256]; + struct sockaddr *remote = (struct sockaddr*)addrbuf; /* length of the remote address. Must be whatever accept() needs. */ socklen_t remotelen = (socklen_t)sizeof(addrbuf); - char tmpbuf[INET_NTOA_BUF_LEN]; or_options_t *options = get_options(); tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in)); memset(addrbuf, 0, sizeof(addrbuf)); - news = tor_accept_socket(conn->s,(struct sockaddr *)&addrbuf,&remotelen); + news = tor_accept_socket(conn->s,remote,&remotelen); if (news < 0) { /* accept() error */ int e = tor_socket_errno(conn->s); if (ERRNO_IS_ACCEPT_EAGAIN(e)) { @@ -974,30 +985,32 @@ connection_handle_listener_read(connection_t *conn, int new_type) if (options->ConstrainedSockets) set_constrained_socket_buffers(news, (int)options->ConstrainedSockSize); - if (((struct sockaddr*)addrbuf)->sa_family != conn->socket_family) { + if (remote->sa_family != conn->socket_family) { /* This is annoying, but can apparently happen on some Darwins. */ log_info(LD_BUG, "A listener connection returned a socket with a " "mismatched family. %s for addr_family %d gave us a socket " "with address family %d. Dropping.", conn_type_to_string(conn->type), (int)conn->socket_family, - (int)((struct sockaddr*)addrbuf)->sa_family); + (int)remote->sa_family); tor_close_socket(news); return 0; } - if (conn->socket_family == AF_INET) { - if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, LOG_INFO)<0) { + if (conn->socket_family == AF_INET || conn->socket_family == AF_INET6) { + tor_addr_t addr; + uint16_t port; + if (check_sockaddr(remote, remotelen, LOG_INFO)<0) { log_info(LD_NET, "accept() returned a strange address; trying getsockname()."); - remotelen=256; + remotelen=sizeof(addrbuf); memset(addrbuf, 0, sizeof(addrbuf)); - if (getsockname(news, (struct sockaddr*)addrbuf, &remotelen)<0) { + if (getsockname(news, remote, &remotelen)<0) { int e = tor_socket_errno(news); log_warn(LD_NET, "getsockname() for new connection failed: %s", tor_socket_strerror(e)); } else { - if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, + if (check_sockaddr((struct sockaddr*)addrbuf, remotelen, LOG_WARN) < 0) { log_warn(LD_NET,"Something's wrong with this conn. Closing it."); tor_close_socket(news); @@ -1005,26 +1018,43 @@ connection_handle_listener_read(connection_t *conn, int new_type) } } } - memcpy(&remote, addrbuf, sizeof(struct sockaddr_in)); + + /* Duplicate code. XXXX021 */ + if (remote->sa_family != conn->socket_family) { + /* This is annoying, but can apparently happen on some Darwins. */ + log_info(LD_BUG, "A listener connection returned a socket with a " + "mismatched family. %s for addr_family %d gave us a socket " + "with address family %d. Dropping.", + conn_type_to_string(conn->type), + (int)conn->socket_family, + (int)remote->sa_family); + tor_close_socket(news); + return 0; + } + + tor_addr_from_sockaddr(&addr, remote); + if (remote->sa_family == AF_INET) + port = ((struct sockaddr_in *)remote)->sin_port; + else + port = ((struct sockaddr_in6 *)remote)->sin6_port; + port = ntohs(port); /* process entrance policies here, before we even create the connection */ if (new_type == CONN_TYPE_AP) { /* check sockspolicy to see if we should accept it */ - if (socks_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) { - tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf)); + if (socks_policy_permits_address(&addr) == 0) { log_notice(LD_APP, "Denying socks connection from untrusted address %s.", - tmpbuf); + fmt_addr(&addr)); tor_close_socket(news); return 0; } } if (new_type == CONN_TYPE_DIR) { /* check dirpolicy to see if we should accept it */ - if (dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) { - tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf)); + if (dir_policy_permits_address(&addr) == 0) { log_notice(LD_DIRSERV,"Denying dir connection from address %s.", - tmpbuf); + fmt_addr(&addr)); tor_close_socket(news); return 0; } @@ -1034,9 +1064,9 @@ connection_handle_listener_read(connection_t *conn, int new_type) newconn->s = news; /* remember the remote address */ - newconn->addr = ntohl(remote.sin_addr.s_addr); - newconn->port = ntohs(remote.sin_port); - newconn->address = tor_dup_ip(newconn->addr); + tor_addr_copy(&newconn->addr, &addr); + newconn->port = port; + newconn->address = tor_dup_addr(&addr); } else if (conn->socket_family == AF_UNIX) { /* For now only control ports can be unix domain sockets @@ -1047,7 +1077,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) newconn->s = news; /* remember the remote address -- do we have anything sane to put here? */ - newconn->addr = 0; + tor_addr_make_unspec(&newconn->addr); newconn->port = 1; newconn->address = tor_strdup(conn->address); } else { @@ -1115,11 +1145,14 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type) */ int connection_connect(connection_t *conn, const char *address, - uint32_t addr, uint16_t port, int *socket_error) + const tor_addr_t *addr, uint16_t port, int *socket_error) { int s, inprogress = 0; - struct sockaddr_in dest_addr; + char addrbuf[256]; + struct sockaddr *dest_addr = (struct sockaddr*) addrbuf; + socklen_t dest_addr_len; or_options_t *options = get_options(); + int protocol_family; if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { int n_conns = get_n_open_sockets(); @@ -1130,7 +1163,12 @@ connection_connect(connection_t *conn, const char *address, return -1; } - s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); + if (tor_addr_family(addr) == AF_INET6) + protocol_family = PF_INET6; + else + protocol_family = PF_INET; + + s = tor_open_socket(protocol_family,SOCK_STREAM,IPPROTO_TCP); if (s < 0) { *socket_error = tor_socket_errno(-1); log_warn(LD_NET,"Error creating network socket: %s", @@ -1164,15 +1202,14 @@ connection_connect(connection_t *conn, const char *address, if (options->ConstrainedSockets) set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize); - memset(&dest_addr,0,sizeof(dest_addr)); - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); - dest_addr.sin_addr.s_addr = htonl(addr); + memset(addrbuf,0,sizeof(addrbuf)); + dest_addr = (struct sockaddr*) addrbuf; + dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf)); + tor_assert(dest_addr_len > 0); log_debug(LD_NET,"Connecting to %s:%u.",escaped_safe_str(address),port); - if (connect(s,(struct sockaddr *)&dest_addr, - (socklen_t)sizeof(dest_addr)) < 0) { + if (connect(s, dest_addr, dest_addr_len) < 0) { int e = tor_socket_errno(s); if (!ERRNO_IS_CONN_EINPROGRESS(e)) { /* yuck. kill it. */ @@ -1422,7 +1459,7 @@ retry_all_listeners(smartlist_t *replaced_conns, static int connection_is_rate_limited(connection_t *conn) { - if (conn->linked || is_internal_IP(conn->addr, 0)) + if (conn->linked || tor_addr_is_internal(&conn->addr, 0)) return 0; else return 1; @@ -2165,7 +2202,8 @@ connection_handle_write(connection_t *conn, int force) if (e) { /* some sort of error, but maybe just inprogress still */ if (!ERRNO_IS_CONN_EINPROGRESS(e)) { - log_info(LD_NET,"in-progress connect failed. Removing."); + log_info(LD_NET,"in-progress connect failed. Removing. (%s)", + tor_socket_strerror(e)); if (CONN_IS_EDGE(conn)) connection_edge_end_errno(TO_EDGE_CONN(conn)); if (conn->type == CONN_TYPE_OR) @@ -2400,13 +2438,15 @@ _connection_write_to_buf_impl(const char *string, size_t len, or_connection_t * connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port) { + /* XXXX021 IP6 make this take a tor_addr_t, or deprecate it. */ + or_connection_t *best=NULL; smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH(conns, connection_t *, conn, { if (conn->type == CONN_TYPE_OR && - conn->addr == addr && + tor_addr_eq_ipv4h(&conn->addr, addr) && conn->port == port && !conn->marked_for_close && (!best || best->_base.timestamp_created < conn->timestamp_created)) @@ -2419,14 +2459,14 @@ connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port) * or NULL if no such connection exists. */ connection_t * connection_get_by_type_addr_port_purpose(int type, - uint32_t addr, uint16_t port, + const tor_addr_t *addr, uint16_t port, int purpose) { smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH(conns, connection_t *, conn, { if (conn->type == type && - conn->addr == addr && + tor_addr_eq(&conn->addr, addr) && conn->port == port && conn->purpose == purpose && !conn->marked_for_close) |