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 | |
parent | 750bb795ac1fcb5b76b6488690400c77fbff0a3f (diff) | |
download | tor-960a0f0a994ba23480e14ffe5179160194fd9616.tar tor-960a0f0a994ba23480e14ffe5179160194fd9616.tar.gz |
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
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | doc/TODO.021 | 20 | ||||
-rw-r--r-- | src/common/address.c | 165 | ||||
-rw-r--r-- | src/common/address.h | 21 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 100 | ||||
-rw-r--r-- | src/or/circuitlist.c | 9 | ||||
-rw-r--r-- | src/or/circuituse.c | 20 | ||||
-rw-r--r-- | src/or/command.c | 21 | ||||
-rw-r--r-- | src/or/config.c | 48 | ||||
-rw-r--r-- | src/or/connection.c | 140 | ||||
-rw-r--r-- | src/or/connection_edge.c | 95 | ||||
-rw-r--r-- | src/or/connection_or.c | 79 | ||||
-rw-r--r-- | src/or/cpuworker.c | 9 | ||||
-rw-r--r-- | src/or/directory.c | 66 | ||||
-rw-r--r-- | src/or/dirserv.c | 9 | ||||
-rw-r--r-- | src/or/dns.c | 10 | ||||
-rw-r--r-- | src/or/dnsserv.c | 26 | ||||
-rw-r--r-- | src/or/main.c | 2 | ||||
-rw-r--r-- | src/or/networkstatus.c | 12 | ||||
-rw-r--r-- | src/or/or.h | 51 | ||||
-rw-r--r-- | src/or/policies.c | 63 | ||||
-rw-r--r-- | src/or/relay.c | 51 | ||||
-rw-r--r-- | src/or/rendclient.c | 2 | ||||
-rw-r--r-- | src/or/rendcommon.c | 2 | ||||
-rw-r--r-- | src/or/rendservice.c | 22 | ||||
-rw-r--r-- | src/or/router.c | 12 | ||||
-rw-r--r-- | src/or/routerlist.c | 30 | ||||
-rw-r--r-- | src/or/routerparse.c | 12 | ||||
-rw-r--r-- | src/or/test.c | 12 |
29 files changed, 703 insertions, 413 deletions
@@ -1,3 +1,10 @@ +Changes in version 0.2.1.5-alpha - 2008-08-?? + o Major features [IPv6 support]: + - Convert many internal address representations to optionally hold + IPv6 addresses. + - Generate and accept IPv6 addresses in many protocol elements. + + Changes in version 0.2.1.4-alpha - 2008-08-04 o Major bugfixes: - The address part of exit policies was not correctly written diff --git a/doc/TODO.021 b/doc/TODO.021 index 82521e0f8..fbc3c1dea 100644 --- a/doc/TODO.021 +++ b/doc/TODO.021 @@ -180,14 +180,20 @@ R d Do we want to maintain our own set of entryguards that we use as - Proposal to supersede 117 by adding IPv6 support for exits and entries. - Internal code support for ipv6: o Clone ipv6 functions (inet_ntop, inet_pton) where they don't exist. - . Many address variables need to become tor_addr_t - - addr in connection_t - - n_addr in extend_info_t + o Many address variables need to become tor_addr_t + o addr in connection_t + o n_addr in extend_info_t - Teach resolving code how to handle ipv6. - . Teach exit policies about ipv6 (consider ipv4/ipv6 - interaction!) - - Generate END_REASON_EXITPOLICY cells and parse them right - - Generate new BEGIN cell types and parse them right + . Teach exit policies about ipv6 (consider ipv4/ipv6 interaction!) + o Use IPv6 in connect/connected/failed-exitpolicy cells + - accept ipv6 from socks + o Generate END_REASON_EXITPOLICY cells right + . ... and parse them right + . Generate new BEGIN cell types and parse them right + - Detect availability of ipv6 + - Advertise availability of ipv6. + - Geoip support, if only to add a zone called "ipv6" + - - 118: Listen on and advertise multiple ports: - Tor should be able to have a pool of outgoing IP addresses that it is able to rotate through. (maybe. Possible overlap with proposal 118.) diff --git a/src/common/address.c b/src/common/address.c index 3328f41f1..711dc16c3 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -8,7 +8,7 @@ const char address_c_id[] = /** * \file address.c - * \brief DOCDOC + * \brief Functions to use and manipulate the tor_addr_t structure. **/ /* This is required on rh7 to make strptime not complain. @@ -27,30 +27,12 @@ const char address_c_id[] = #include <windows.h> #endif -#ifdef HAVE_UNAME -#include <sys/utsname.h> -#endif #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif -#ifdef HAVE_SYS_FCNTL_H -#include <sys/fcntl.h> -#endif -#ifdef HAVE_PWD_H -#include <pwd.h> -#endif -#ifdef HAVE_GRP_H -#include <grp.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif #ifdef HAVE_ERRNO_H #include <errno.h> #endif @@ -60,11 +42,6 @@ const char address_c_id[] = #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif -#ifndef HAVE_GETTIMEOFDAY -#ifdef HAVE_FTIME -#include <sys/timeb.h> -#endif -#endif #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif @@ -79,24 +56,6 @@ const char address_c_id[] = #include <stdlib.h> #include <string.h> #include <assert.h> -#ifdef HAVE_PTHREAD_H -#include <pthread.h> -#endif -#ifdef HAVE_SIGNAL_H -#include <signal.h> -#endif -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_SYS_UTIME_H -#include <sys/utime.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#ifdef HAVE_SYS_SYSLIMITS_H -#include <sys/syslimits.h> -#endif /** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a * socklen object in *<b>sa_out</b> of object size <b>len</b>. If not enough @@ -113,9 +72,10 @@ tor_addr_to_sockaddr(const tor_addr_t *a, if (len < sizeof(struct sockaddr_in)) return -1; sin = (struct sockaddr_in *)sa_out; + sin->sin_len = sizeof(*sin); sin->sin_family = AF_INET; - sin->sin_port = port; - sin->sin_addr.s_addr = a->addr.in_addr.s_addr; + sin->sin_port = htons(port); + sin->sin_addr.s_addr = tor_addr_to_ipv4n(a); return sizeof(struct sockaddr_in); } else if (a->family == AF_INET6) { struct sockaddr_in6 *sin6; @@ -123,8 +83,9 @@ tor_addr_to_sockaddr(const tor_addr_t *a, return -1; sin6 = (struct sockaddr_in6 *)sa_out; memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_len = sizeof(sin6); sin6->sin6_family = AF_INET6; - sin6->sin6_port = port; + sin6->sin6_port = htons(port); memcpy(&sin6->sin6_addr, &a->addr.in6_addr, sizeof(struct in6_addr)); return sizeof(struct sockaddr_in6); } else { @@ -134,7 +95,7 @@ tor_addr_to_sockaddr(const tor_addr_t *a, /** Set the tor_addr_t in <b>a</b> to contain the socket address contained in * <b>sa</b>. */ -void +int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa) { tor_assert(a); @@ -150,7 +111,18 @@ tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa) memcpy(&a->addr.in6_addr, &sin6->sin6_addr, sizeof(struct in6_addr)); } else { a->family = AF_UNSPEC; + return -1; } + return 0; +} + +/** Set address <b>a</b> to the unspecified address. This address belongs to + * no family. */ +void +tor_addr_make_unspec(tor_addr_t *a) +{ + memset(a, 0, sizeof(*a)); + a->family = AF_UNSPEC; } /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set @@ -178,10 +150,14 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) return -1; } else if (tor_inet_pton(AF_INET, name, &iaddr)) { /* It's an IPv4 IP. */ + if (family == AF_INET6) + return -1; addr->family = AF_INET; memcpy(&addr->addr.in_addr, &iaddr, sizeof(struct in_addr)); return 0; } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) { + if (family == AF_INET) + return -1; addr->family = AF_INET6; memcpy(&addr->addr.in6_addr, &iaddr6, sizeof(struct in6_addr)); return 0; @@ -633,18 +609,27 @@ tor_addr_is_loopback(const tor_addr_t *addr) } } -/** Take a 32-bit host-order ipv4 address <b>v4addr</b> and store it in the - * tor_addr *<b>dest</b>. - */ -/* XXXX_IP6 Temporary, for use while 32-bit int addresses are still being - * passed around. */ +/** Set <b>dest</b> to equal the IPv4 address in <b>v4addr</b> (given in + * network order. */ void -tor_addr_from_ipv4h(tor_addr_t *dest, uint32_t v4addr) +tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr) { tor_assert(dest); memset(dest, 0, sizeof(dest)); dest->family = AF_INET; - dest->addr.in_addr.s_addr = htonl(v4addr); + dest->addr.in_addr.s_addr = v4addr; +} + +/** Set <b>dest</b> to equal the IPv6 address in the 16 bytes at + * <b>ipv6_bytes</b>. */ +void +tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *ipv6_bytes) +{ + tor_assert(dest); + tor_assert(ipv6_bytes); + memset(dest, 0, sizeof(dest)); + dest->family = AF_INET6; + memcpy(dest->addr.in6_addr.s6_addr, ipv6_bytes, 16); } /** Copy a tor_addr_t from <b>src</b> to <b>dest</b>. @@ -652,7 +637,8 @@ tor_addr_from_ipv4h(tor_addr_t *dest, uint32_t v4addr) void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src) { - tor_assert(src && dest); + tor_assert(src); + tor_assert(dest); memcpy(dest, src, sizeof(tor_addr_t)); } @@ -838,6 +824,19 @@ tor_dup_addr(const tor_addr_t *addr) return tor_strdup(buf); } +/** Return a string representing the address <b>addr</b>. This string is + * statically allocated, and must not be freed. Each call to + * <b>fmt_addr</b> invalidates the last result of the function. This + * function is not thread-safe. */ +const char * +fmt_addr(const tor_addr_t *addr) +{ + static char buf[TOR_ADDR_BUF_LEN]; + if (!addr) return "<null>"; + tor_addr_to_str(buf, addr, sizeof(buf), 0); + return buf; +} + /** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string * may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by * square brackets. @@ -865,6 +864,64 @@ tor_addr_from_str(tor_addr_t *addr, const char *src) return result; } +/** Parse an address or address-port combination from <b>s</b>, and put the + result in <b>addr_out</b? and (optionally) <b>port_out</b>. Return 0 on + success, negative on failure.*/ +int +tor_addr_port_parse(const char *s, tor_addr_t *addr_out, uint16_t *port_out) +{ + const char *port; + tor_addr_t addr; + uint16_t portval; + char *tmp = NULL; + + tor_assert(s); + tor_assert(addr_out); + + s = eat_whitespace(s); + + if (*s == '[') { + port = strstr(s, "]"); + if (!port) + goto err; + tmp = tor_strndup(s+1, port-s); + port = port+1; + if (*port == ':') + port++; + else + port = NULL; + } else { + port = strchr(s, ':'); + if (port) + tmp = tor_strndup(s, port-s); + else + tmp = tor_strdup(s); + if (port) + ++port; + } + + if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) < 0) + goto err; + tor_free(tmp); + + if (port) { + portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL); + if (!portval) + goto err; + } else { + portval = 0; + } + + if (*port_out) + *port_out = portval; + tor_addr_copy(addr_out, &addr); + + return 0; + err: + tor_free(tmp); + return -1; +} + /** Set *<b>addr</b> to the IP address (if any) of whatever interface * connects to the internet. This address should only be used in checking * whether our address has changed. Return 0 on success, -1 on failure. diff --git a/src/common/address.h b/src/common/address.h index b079f6945..133a9b192 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -40,7 +40,8 @@ static INLINE const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a); static INLINE int tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u); socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port, struct sockaddr *sa_out, socklen_t len); -void tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa); +int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa); +void tor_addr_make_unspec(tor_addr_t *a); static INLINE const struct in6_addr * tor_addr_to_in6(const tor_addr_t *a) @@ -88,9 +89,13 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u) int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out); char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC; +const char *fmt_addr(const tor_addr_t *addr); int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr); -/** DOCDOC */ +/** Flag to specify how to do a comparison between addresses. In an "exact" + * comparison, addresses are equivalent only if they are in the same family + * with the same value. In a "semantic" comparison, IPv4 addresses match all + * IPv6 encodings of those addresses. */ typedef enum { CMP_EXACT, CMP_SEMANTIC, @@ -100,10 +105,15 @@ int tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2, tor_addr_comparison_t how); int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2, maskbits_t mask, tor_addr_comparison_t how); +/** Return true iff a and b are the same address. The comparison is done + * "exactly". */ +#define tor_addr_eq(a,b) (0==tor_addr_compare((a),(b),CMP_EXACT)) unsigned int tor_addr_hash(const tor_addr_t *addr); int tor_addr_is_v4(const tor_addr_t *addr); int tor_addr_is_internal(const tor_addr_t *ip, int for_listening) ATTR_PURE; +int tor_addr_port_parse(const char *s, tor_addr_t *addr_out, + uint16_t *port_out); int tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out, maskbits_t *mask_out, uint16_t *port_min_out, uint16_t *port_max_out); @@ -111,7 +121,12 @@ const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate); int tor_addr_from_str(tor_addr_t *addr, const char *src); void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src); -void tor_addr_from_ipv4h(tor_addr_t *dest, uint32_t v4addr); +void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr); +/** Set <b>dest</b> to the IPv4 address encoded in <b>v4addr</b> in host + * order. */ +#define tor_addr_from_ipv4h(dest, v4addr) \ + tor_addr_from_ipv4n((dest), htonl(v4addr)) +void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *byets); int tor_addr_is_null(const tor_addr_t *addr); int tor_addr_is_loopback(const tor_addr_t *addr); diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index aac8b2a78..842ecbd1d 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -343,8 +343,6 @@ circuit_handle_first_hop(origin_circuit_t *circ) { crypt_path_t *firsthop; or_connection_t *n_conn; - char tmpbuf[INET_NTOA_BUF_LEN]; - struct in_addr in; int err_reason = 0; firsthop = onion_next_hop_in_cpath(circ->cpath); @@ -352,9 +350,8 @@ circuit_handle_first_hop(origin_circuit_t *circ) tor_assert(firsthop->extend_info); /* now see if we're already connected to the first OR in 'route' */ - in.s_addr = htonl(firsthop->extend_info->addr); - tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf)); - log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf, + log_debug(LD_CIRC,"Looking for firsthop '%s:%u'", + fmt_addr(&firsthop->extend_info->addr), firsthop->extend_info->port); n_conn = connection_or_get_by_identity_digest( @@ -370,7 +367,7 @@ circuit_handle_first_hop(origin_circuit_t *circ) if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */ if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); - n_conn = connection_or_connect(firsthop->extend_info->addr, + n_conn = connection_or_connect(&firsthop->extend_info->addr, firsthop->extend_info->port, firsthop->extend_info->identity_digest); if (!n_conn) { /* connect failed, forget the whole thing */ @@ -426,7 +423,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) if (tor_digest_is_zero(circ->n_hop->identity_digest)) { /* Look at addr/port. This is an unkeyed connection. */ - if (circ->n_hop->addr != or_conn->_base.addr || + if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) || circ->n_hop->port != or_conn->_base.port) continue; } else { @@ -662,7 +659,12 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) return 0; } - set_uint32(payload, htonl(hop->extend_info->addr)); + if (tor_addr_family(&hop->extend_info->addr) != AF_INET) { + log_warn(LD_BUG, "Trying to extend to a non-IPv4 address."); + return - END_CIRC_REASON_INTERNAL; + } + + set_uint32(payload, tor_addr_to_ipv4n(&hop->extend_info->addr)); set_uint16(payload+4, htons(hop->extend_info->port)); onionskin = payload+2+4; @@ -758,17 +760,16 @@ circuit_extend(cell_t *cell, circuit_t *circ) * connection without dropping it immediately... */ if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN || n_conn->_base.or_is_obsolete) { - struct in_addr in; - char tmpbuf[INET_NTOA_BUF_LEN]; - in.s_addr = htonl(n_addr); - tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf)); + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, n_addr); + log_debug(LD_CIRC|LD_OR,"Next router (%s:%d) not connected. Connecting.", - tmpbuf, (int)n_port); + fmt_addr(&addr), (int)n_port); circ->n_hop = extend_info_alloc(NULL /*nickname*/, id_digest, NULL /*onion_key*/, - n_addr, n_port); + &addr, n_port); circ->n_conn_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN); memcpy(circ->n_conn_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN); @@ -776,7 +777,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) if (! (n_conn && !n_conn->_base.or_is_obsolete)) { /* we should try to open a connection */ - n_conn = connection_or_connect(n_addr, n_port, id_digest); + n_conn = connection_or_connect(&addr, n_port, id_digest); if (!n_conn) { log_info(LD_CIRC,"Launching n_conn failed. Closing circuit."); circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); @@ -1015,7 +1016,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, circ->p_conn, &cell, CELL_DIRECTION_IN); log_debug(LD_CIRC,"Finished sending 'created' cell."); - if (!is_local_IP(circ->p_conn->_base.addr) && + if (!is_local_addr(&circ->p_conn->_base.addr) && !connection_or_nonopen_was_started_here(circ->p_conn)) { /* record that we could process create cells from a non-local conn * that we didn't initiate; presumably this means that create cells @@ -1589,7 +1590,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) for (i=0; i < smartlist_len(rl->routers); i++) { r = smartlist_get(rl->routers, i); - if (!fascist_firewall_allows_address_or(r->addr,r->or_port)) + if (!fascist_firewall_allows_or(r)) smartlist_add(excluded, r); } } @@ -1708,7 +1709,7 @@ onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice) extend_info_t * extend_info_alloc(const char *nickname, const char *digest, crypto_pk_env_t *onion_key, - uint32_t addr, uint16_t port) + const tor_addr_t *addr, uint16_t port) { extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t)); memcpy(info->identity_digest, digest, DIGEST_LEN); @@ -1716,7 +1717,7 @@ extend_info_alloc(const char *nickname, const char *digest, strlcpy(info->nickname, nickname, sizeof(info->nickname)); if (onion_key) info->onion_key = crypto_pk_dup_key(onion_key); - info->addr = addr; + tor_addr_copy(&info->addr, addr); info->port = port; return info; } @@ -1726,9 +1727,11 @@ extend_info_alloc(const char *nickname, const char *digest, extend_info_t * extend_info_from_router(routerinfo_t *r) { + tor_addr_t addr; tor_assert(r); + tor_addr_from_ipv4h(&addr, r->addr); return extend_info_alloc(r->nickname, r->cache_info.identity_digest, - r->onion_pkey, r->addr, r->or_port); + r->onion_pkey, &addr, r->or_port); } /** Release storage held by an extend_info_t struct. */ @@ -1888,7 +1891,7 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, return NULL; if (router_is_unreliable(r, need_uptime, need_capacity, 0)) return NULL; - if (!fascist_firewall_allows_address_or(r->addr,r->or_port)) + if (!fascist_firewall_allows_or(r)) return NULL; return r; } @@ -2781,8 +2784,8 @@ getinfo_helper_entry_guards(control_connection_t *conn, * ones in the torrc file, but one day we may be able to learn about new * bridges on our own, and remember them in the state file. */ typedef struct { - /** IPv4 address of the bridge. */ - uint32_t addr; + /** Address of the bridge. */ + tor_addr_t addr; /** TLS port for the bridge. */ uint16_t port; /** Expected identity digest, or all \0's if we don't know what the @@ -2814,15 +2817,17 @@ routerinfo_get_configured_bridge(routerinfo_t *ri) { if (!bridge_list) return NULL; - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { if (tor_digest_is_zero(bridge->identity) && - bridge->addr == ri->addr && bridge->port == ri->or_port) + tor_addr_eq_ipv4h(&bridge->addr, ri->addr) && + bridge->port == ri->or_port) return bridge; if (!memcmp(bridge->identity, ri->cache_info.identity_digest, DIGEST_LEN)) return bridge; - }); + } + SMARTLIST_FOREACH_END(bridge); return NULL; } @@ -2836,10 +2841,10 @@ routerinfo_is_a_configured_bridge(routerinfo_t *ri) /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> * is set, it tells us the identity key too. */ void -bridge_add_from_config(uint32_t addr, uint16_t port, char *digest) +bridge_add_from_config(const tor_addr_t *addr, uint16_t port, char *digest) { bridge_info_t *b = tor_malloc_zero(sizeof(bridge_info_t)); - b->addr = addr; + tor_addr_copy(&b->addr, addr); b->port = port; if (digest) memcpy(b->identity, digest, DIGEST_LEN); @@ -2874,7 +2879,7 @@ bridge_fetch_status_arrived(bridge_info_t *bridge, time_t now) /** If <b>digest</b> is one of our known bridges, return it. */ static bridge_info_t * -find_bridge_by_digest(char *digest) +find_bridge_by_digest(const char *digest) { SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, { @@ -2887,36 +2892,36 @@ find_bridge_by_digest(char *digest) /** We need to ask <b>bridge</b> for its server descriptor. <b>address</b> * is a helpful string describing this bridge. */ static void -launch_direct_bridge_descriptor_fetch(char *address, bridge_info_t *bridge) +launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) { + char *address; + if (connection_get_by_type_addr_port_purpose( - CONN_TYPE_DIR, bridge->addr, bridge->port, + CONN_TYPE_DIR, &bridge->addr, bridge->port, DIR_PURPOSE_FETCH_SERVERDESC)) return; /* it's already on the way */ - directory_initiate_command(address, bridge->addr, + + address = tor_dup_addr(&bridge->addr); + directory_initiate_command(address, &bridge->addr, bridge->port, 0, 0, /* does not matter */ 1, bridge->identity, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, 0, "authority.z", NULL, 0, 0); + tor_free(address); } /** Fetching the bridge descriptor from the bridge authority returned a * "not found". Fall back to trying a direct fetch. */ void -retry_bridge_descriptor_fetch_directly(char *digest) +retry_bridge_descriptor_fetch_directly(const char *digest) { bridge_info_t *bridge = find_bridge_by_digest(digest); - char address_buf[INET_NTOA_BUF_LEN+1]; - struct in_addr in; - if (!bridge) return; /* not found? oh well. */ - in.s_addr = htonl(bridge->addr); - tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); - launch_direct_bridge_descriptor_fetch(address_buf, bridge); + launch_direct_bridge_descriptor_fetch(bridge); } /** For each bridge in our list for which we don't currently have a @@ -2925,8 +2930,6 @@ retry_bridge_descriptor_fetch_directly(char *digest) void fetch_bridge_descriptors(time_t now) { - char address_buf[INET_NTOA_BUF_LEN+1]; - struct in_addr in; or_options_t *options = get_options(); int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY); int ask_bridge_directly; @@ -2935,7 +2938,7 @@ fetch_bridge_descriptors(time_t now) if (!bridge_list) return; - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { if (bridge->fetch_status.next_attempt_at > now) continue; /* don't bother, no need to retry yet */ @@ -2943,9 +2946,6 @@ fetch_bridge_descriptors(time_t now) /* schedule another fetch as if this one will fail, in case it does */ bridge_fetch_status_increment(bridge, now); - in.s_addr = htonl(bridge->addr); - tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); - can_use_bridge_authority = !tor_digest_is_zero(bridge->identity) && num_bridge_auths; ask_bridge_directly = !can_use_bridge_authority || @@ -2955,9 +2955,10 @@ fetch_bridge_descriptors(time_t now) !options->UpdateBridgesFromAuthority, !num_bridge_auths); if (ask_bridge_directly && - !fascist_firewall_allows_address_or(bridge->addr, bridge->port)) { + !fascist_firewall_allows_address_or(&bridge->addr, bridge->port)) { log_notice(LD_DIR, "Bridge at '%s:%d' isn't reachable by our " - "firewall policy. %s.", address_buf, bridge->port, + "firewall policy. %s.", fmt_addr(&bridge->addr), + bridge->port, can_use_bridge_authority ? "Asking bridge authority instead" : "Skipping"); if (can_use_bridge_authority) @@ -2968,7 +2969,7 @@ fetch_bridge_descriptors(time_t now) if (ask_bridge_directly) { /* we need to ask the bridge itself for its descriptor. */ - launch_direct_bridge_descriptor_fetch(address_buf, bridge); + launch_direct_bridge_descriptor_fetch(bridge); } else { /* We have a digest and we want to ask an authority. We could * combine all the requests into one, but that may give more @@ -2983,7 +2984,8 @@ fetch_bridge_descriptors(time_t now) directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, resource, 0); } - }); + } + SMARTLIST_FOREACH_END(bridge); } /** We just learned a descriptor for a bridge. See if that diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 8fedfca8e..2f19bbf2c 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -231,8 +231,7 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn) if (!circuits_pending_or_conns) return; - SMARTLIST_FOREACH(circuits_pending_or_conns, circuit_t *, circ, - { + SMARTLIST_FOREACH_BEGIN(circuits_pending_or_conns, circuit_t *, circ) { if (circ->marked_for_close) continue; if (!circ->n_hop) @@ -240,7 +239,7 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn) tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT); if (tor_digest_is_zero(circ->n_hop->identity_digest)) { /* Look at addr/port. This is an unkeyed connection. */ - if (circ->n_hop->addr != or_conn->_base.addr || + if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) || circ->n_hop->port != or_conn->_base.port) continue; } else { @@ -250,7 +249,7 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn) continue; } smartlist_add(out, circ); - }); + } SMARTLIST_FOREACH_END(circ); } /** Return the number of circuits in state OR_WAIT, waiting for the given @@ -573,7 +572,7 @@ circuit_dump_by_conn(connection_t *conn, int severity) } } if (!circ->n_conn && circ->n_hop && - circ->n_hop->addr == conn->addr && + tor_addr_eq(&circ->n_hop->addr, &conn->addr) && circ->n_hop->port == conn->port && conn->type == CONN_TYPE_OR && !memcmp(TO_OR_CONN(conn)->identity_digest, diff --git a/src/or/circuituse.c b/src/or/circuituse.c index ebba1cdfa..8dfc607c1 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -102,9 +102,10 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, return 0; /* this is a circuit to somewhere else */ if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ - struct in_addr in; - if (!tor_inet_aton(conn->socks_request->address, &in) || - build_state->chosen_exit->addr != ntohl(in.s_addr) || + tor_addr_t addr; + int r = tor_addr_from_str(&addr, conn->socks_request->address); + if (r < 0 || + !tor_addr_eq(&build_state->chosen_exit->addr, &addr) || build_state->chosen_exit->port != conn->socks_request->port) return 0; } @@ -1082,18 +1083,19 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, * we don't have a routerinfo about. Make up an extend_info. */ char digest[DIGEST_LEN]; char *hexdigest = conn->chosen_exit_name+1; - struct in_addr in; + tor_addr_t addr; if (strlen(hexdigest) < HEX_DIGEST_LEN || base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN)<0) { log_info(LD_DIR, "Broken exit digest on tunnel conn. Closing."); return -1; } - if (!tor_inet_aton(conn->socks_request->address, &in)) { - log_info(LD_DIR, "Broken address on tunnel conn. Closing."); + if (tor_addr_from_str(&addr, conn->socks_request->address) < 0) { + log_info(LD_DIR, "Broken address %s on tunnel conn. Closing.", + escaped_safe_str(conn->socks_request->address)); return -1; } extend_info = extend_info_alloc(conn->chosen_exit_name+1, - digest, NULL, ntohl(in.s_addr), + digest, NULL, &addr, conn->socks_request->port); } else { /* We will need an onion key for the router, and we @@ -1306,8 +1308,8 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) conn_age = (int)(time(NULL) - conn->_base.timestamp_created); if (conn_age >= get_options()->SocksTimeout) { - int severity = (!conn->_base.addr && !conn->_base.port) ? - LOG_INFO : LOG_NOTICE; + int severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) ? + LOG_INFO : LOG_NOTICE; log_fn(severity, LD_APP, "Tried for %d seconds to get a connection to %s:%d. Giving up.", conn_age, safe_str(conn->socks_request->address), diff --git a/src/or/command.c b/src/or/command.c index 89bc72ef1..476501ffc 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -576,22 +576,19 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) while (n_other_addrs && cp < end-2) { /* Consider all the other addresses; if any matches, this connection is * "canonical." */ - uint8_t other_addr_type = (uint8_t) *cp++; - uint8_t other_addr_len = (uint8_t) *cp++; - if (cp + other_addr_len >= end) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, - "Address too long in netinfo cell; closing connection."); + tor_addr_t addr; + const char *next = decode_address_from_payload(&addr, cp, end-cp); + if (next == NULL) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Bad ddress in netinfo cell; closing connection."); connection_mark_for_close(TO_CONN(conn)); return; } - if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) { - uint32_t addr = ntohl(get_uint32(cp)); - if (addr == conn->real_addr) { - conn->is_canonical = 1; - break; - } + if (tor_addr_eq(&addr, &conn->real_addr)) { + conn->is_canonical = 1; + break; } - cp += other_addr_len; + cp = next; --n_other_addrs; } diff --git a/src/or/config.c b/src/or/config.c index 1594c922b..201a621e6 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2365,26 +2365,31 @@ resolve_my_address(int warn_severity, or_options_t *options, return 0; } -/** Return true iff <b>ip</b> (in host order) is judged to be on the - * same network as us, or on a private network. +/** Return true iff <b>addr</b> is judged to be on the same network as us, or + * on a private network. */ int -is_local_IP(uint32_t ip) +is_local_addr(const tor_addr_t *addr) { - if (is_internal_IP(ip, 0)) + if (tor_addr_is_internal(addr, 0)) return 1; /* Check whether ip is on the same /24 as we are. */ if (get_options()->EnforceDistinctSubnets == 0) return 0; - /* It's possible that this next check will hit before the first time - * resolve_my_address actually succeeds. (For clients, it is likely that - * resolve_my_address will never be called at all). In those cases, - * last_resolved_addr will be 0, and so checking to see whether ip is on the - * same /24 as last_resolved_addr will be the same as checking whether it - * was on net 0, which is already done by is_internal_IP. - */ - if ((last_resolved_addr & 0xffffff00ul) == (ip & 0xffffff00ul)) - return 1; + if (tor_addr_family(addr) == AF_INET) { + /*XXXX021 IP6 what corresponds to an /24? */ + uint32_t ip = tor_addr_to_ipv4h(addr); + + /* It's possible that this next check will hit before the first time + * resolve_my_address actually succeeds. (For clients, it is likely that + * resolve_my_address will never be called at all). In those cases, + * last_resolved_addr will be 0, and so checking to see whether ip is on + * the same /24 as last_resolved_addr will be the same as checking whether + * it was on net 0, which is already done by is_internal_IP. + */ + if ((last_resolved_addr & 0xffffff00ul) == (ip & 0xffffff00ul)) + return 1; + } return 0; } @@ -4153,7 +4158,7 @@ parse_redirect_line(smartlist_t *result, config_line_t *line, char **msg) *msg = tor_strdup("Wrong number of elements in RedirectExit line"); goto err; } - if (parse_addr_and_port_range(smartlist_get(elements,0),&r->addr, + if (tor_addr_parse_mask_ports(smartlist_get(elements,0),&r->addr, &r->maskbits,&r->port_min,&r->port_max)) { *msg = tor_strdup("Error parsing source address in RedirectExit line"); goto err; @@ -4161,8 +4166,8 @@ parse_redirect_line(smartlist_t *result, config_line_t *line, char **msg) if (0==strcasecmp(smartlist_get(elements,1), "pass")) { r->is_redirect = 0; } else { - if (parse_addr_port(LOG_WARN, smartlist_get(elements,1),NULL, - &r->addr_dest, &r->port_dest)) { + if (tor_addr_port_parse(smartlist_get(elements,1), + &r->addr_dest, &r->port_dest)) { *msg = tor_strdup("Error parsing dest address in RedirectExit line"); goto err; } @@ -4196,8 +4201,8 @@ parse_bridge_line(const char *line, int validate_only) { smartlist_t *items = NULL; int r; - char *addrport=NULL, *address=NULL, *fingerprint=NULL; - uint32_t addr = 0; + char *addrport=NULL, *fingerprint=NULL; + tor_addr_t addr; uint16_t port = 0; char digest[DIGEST_LEN]; @@ -4210,7 +4215,7 @@ parse_bridge_line(const char *line, int validate_only) } addrport = smartlist_get(items, 0); smartlist_del_keeporder(items, 0); - if (parse_addr_port(LOG_WARN, addrport, &address, &addr, &port)<0) { + if (tor_addr_port_parse(addrport, &addr, &port)<0) { log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport); goto err; } @@ -4232,10 +4237,10 @@ parse_bridge_line(const char *line, int validate_only) } if (!validate_only) { - log_debug(LD_DIR, "Bridge at %s:%d (%s)", address, + log_debug(LD_DIR, "Bridge at %s:%d (%s)", fmt_addr(&addr), (int)port, fingerprint ? fingerprint : "no key listed"); - bridge_add_from_config(addr, port, fingerprint ? digest : NULL); + bridge_add_from_config(&addr, port, fingerprint ? digest : NULL); } r = 0; @@ -4248,7 +4253,6 @@ parse_bridge_line(const char *line, int validate_only) SMARTLIST_FOREACH(items, char*, s, tor_free(s)); smartlist_free(items); tor_free(addrport); - tor_free(address); tor_free(fingerprint); return r; } diff --git a/src/or/connection.c b/src/or/connection.c index 8c7cca1ba..c415af898 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) diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 5b1b5b824..123c011ff 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -207,9 +207,16 @@ connection_edge_end(edge_connection_t *conn, char reason) payload[0] = reason; if (reason == END_STREAM_REASON_EXITPOLICY && !connection_edge_is_rendezvous_stream(conn)) { - set_uint32(payload+1, htonl(conn->_base.addr)); - set_uint32(payload+5, htonl(dns_clip_ttl(conn->address_ttl))); - payload_len += 8; + int addrlen; + if (tor_addr_family(&conn->_base.addr) == AF_INET) { + set_uint32(payload+1, tor_addr_to_ipv4n(&conn->_base.addr)); + addrlen = 4; + } else { + memcpy(payload+1, tor_addr_to_in6_addr8(&conn->_base.addr), 16); + addrlen = 16; + } + set_uint32(payload+1+addrlen, htonl(dns_clip_ttl(conn->address_ttl))); + payload_len += 4+addrlen; } circ = circuit_get_by_edge_conn(conn); @@ -285,15 +292,12 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) { char valbuf[INET_NTOA_BUF_LEN]; connection_t *conn; - struct in_addr in; tor_assert(edge_conn); tor_assert(edge_conn->_base.type == CONN_TYPE_EXIT); conn = TO_CONN(edge_conn); tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING); - in.s_addr = htonl(conn->addr); - tor_inet_ntoa(&in,valbuf,sizeof(valbuf)); log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.", escaped_safe_str(conn->address),conn->port,safe_str(valbuf)); @@ -308,13 +312,22 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) RELAY_COMMAND_CONNECTED, NULL, 0) < 0) return 0; /* circuit is closed, don't continue */ } else { - char connected_payload[8]; - set_uint32(connected_payload, htonl(conn->addr)); - set_uint32(connected_payload+4, - htonl(dns_clip_ttl(edge_conn->address_ttl))); + char connected_payload[20]; + int connected_payload_len; + if (tor_addr_family(&conn->addr) == AF_INET) { + set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr)); + set_uint32(connected_payload+4, + htonl(dns_clip_ttl(edge_conn->address_ttl))); + connected_payload_len = 8; + } else { + memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16); + set_uint32(connected_payload+16, + htonl(dns_clip_ttl(edge_conn->address_ttl))); + connected_payload_len = 20; + } if (connection_edge_send_command(edge_conn, - RELAY_COMMAND_CONNECTED, - connected_payload, 8) < 0) + RELAY_COMMAND_CONNECTED, + connected_payload, connected_payload_len) < 0) return 0; /* circuit is closed, don't continue */ } tor_assert(edge_conn->package_window > 0); @@ -356,13 +369,12 @@ connection_ap_expire_beginning(void) int seconds_idle; smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH(conns, connection_t *, c, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, c) { if (c->type != CONN_TYPE_AP) continue; conn = TO_EDGE_CONN(c); /* if it's an internal linked connection, don't yell its status. */ - severity = (!conn->_base.addr && !conn->_base.port) + severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) ? LOG_INFO : LOG_NOTICE; seconds_idle = (int)( now - conn->_base.timestamp_lastread ); @@ -434,7 +446,7 @@ connection_ap_expire_beginning(void) if (!conn->_base.marked_for_close) connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); } - }); /* end foreach */ + } SMARTLIST_FOREACH_END(conn); } /** Tell any AP streams that are waiting for a new circuit to try again, @@ -472,8 +484,7 @@ connection_ap_fail_onehop(const char *failed_digest, edge_connection_t *edge_conn; char digest[DIGEST_LEN]; smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH(conns, connection_t *, conn, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->marked_for_close || conn->type != CONN_TYPE_AP || conn->state != AP_CONN_STATE_CIRCUIT_WAIT) @@ -486,11 +497,12 @@ connection_ap_fail_onehop(const char *failed_digest, continue; if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ - struct in_addr in; + tor_addr_t addr; if (!build_state || !build_state->chosen_exit || - !edge_conn->socks_request || !edge_conn->socks_request->address || - !tor_inet_aton(edge_conn->socks_request->address, &in) || - build_state->chosen_exit->addr != ntohl(in.s_addr) || + !edge_conn->socks_request || !edge_conn->socks_request->address) + continue; + if (tor_addr_from_str(&addr, edge_conn->socks_request->address)<0 || + !tor_addr_eq(&build_state->chosen_exit->addr, &addr) || build_state->chosen_exit->port != edge_conn->socks_request->port) continue; } @@ -498,7 +510,7 @@ connection_ap_fail_onehop(const char *failed_digest, "just failed.", edge_conn->chosen_exit_name, edge_conn->socks_request->address); connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_TIMEOUT); - }); + } SMARTLIST_FOREACH_END(conn); } /** A circuit failed to finish on its last hop <b>info</b>. If there @@ -2147,7 +2159,7 @@ connection_ap_make_link(char *address, uint16_t port, } conn->_base.address = tor_strdup("(Tor_internal)"); - conn->_base.addr = 0; + tor_addr_make_unspec(&conn->_base.addr); conn->_base.port = 0; if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */ @@ -2535,7 +2547,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) if (rh.command == RELAY_COMMAND_BEGIN_DIR) { tor_assert(or_circ); - if (or_circ->p_conn && or_circ->p_conn->_base.addr) + if (or_circ->p_conn && !tor_addr_is_null(&or_circ->p_conn->_base.addr)) n_stream->_base.addr = or_circ->p_conn->_base.addr; return connection_exit_connect_dir(n_stream); } @@ -2618,7 +2630,7 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) void connection_exit_connect(edge_connection_t *edge_conn) { - uint32_t addr; + const tor_addr_t *addr; uint16_t port; connection_t *conn = TO_CONN(edge_conn); int socket_error = 0; @@ -2633,23 +2645,20 @@ connection_exit_connect(edge_connection_t *edge_conn) return; } - addr = conn->addr; + addr = &conn->addr; port = conn->port; if (redirect_exit_list) { SMARTLIST_FOREACH(redirect_exit_list, exit_redirect_t *, r, { - if (!addr_mask_cmp_bits(addr, r->addr, r->maskbits) && + if (tor_addr_compare_masked(addr, &r->addr, r->maskbits, CMP_SEMANTIC) && (r->port_min <= port) && (port <= r->port_max)) { - struct in_addr in; if (r->is_redirect) { - char tmpbuf[INET_NTOA_BUF_LEN]; - addr = r->addr_dest; - port = r->port_dest; - in.s_addr = htonl(addr); - tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf)); + addr = &r->addr_dest; + if (r->port_dest) + port = r->port_dest; log_debug(LD_EXIT, "Redirecting connection from %s:%d to %s:%d", escaped_safe_str(conn->address), conn->port, - safe_str(tmpbuf), port); + fmt_addr(addr), port); } break; } @@ -2692,13 +2701,21 @@ connection_exit_connect(edge_connection_t *edge_conn) NULL, 0); } else { /* normal stream */ /* This must be the original address, not the redirected address. */ - char connected_payload[8]; - set_uint32(connected_payload, htonl(conn->addr)); - set_uint32(connected_payload+4, + char connected_payload[20]; + int connected_payload_len; + if (tor_addr_family(&conn->addr) == AF_INET) { + set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr)); + connected_payload_len = 4; + } else { + memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16); + connected_payload_len = 16; + } + set_uint32(connected_payload+connected_payload_len, htonl(dns_clip_ttl(edge_conn->address_ttl))); + connected_payload_len += 4; connection_edge_send_command(edge_conn, RELAY_COMMAND_CONNECTED, - connected_payload, 8); + connected_payload, connected_payload_len); } } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 1c6c85bd1..6c08a4e77 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -348,14 +348,9 @@ connection_or_finished_connecting(or_connection_t *or_conn) if (get_options()->HttpsProxy) { char buf[1024]; - char addrbuf[INET_NTOA_BUF_LEN]; - struct in_addr in; char *base64_authenticator=NULL; const char *authenticator = get_options()->HttpsProxyAuthenticator; - in.s_addr = htonl(conn->addr); - tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf)); - if (authenticator) { base64_authenticator = alloc_http_authenticator(authenticator); if (!base64_authenticator) @@ -363,12 +358,13 @@ connection_or_finished_connecting(or_connection_t *or_conn) } if (base64_authenticator) { tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n" - "Proxy-Authorization: Basic %s\r\n\r\n", addrbuf, + "Proxy-Authorization: Basic %s\r\n\r\n", + fmt_addr(&conn->addr), conn->port, base64_authenticator); tor_free(base64_authenticator); } else { tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n", - addrbuf, conn->port); + fmt_addr(&conn->addr), conn->port); } connection_write_to_buf(buf, strlen(buf), conn); conn->state = OR_CONN_STATE_PROXY_FLUSHING; @@ -388,7 +384,7 @@ connection_or_finished_connecting(or_connection_t *or_conn) * by checking to see if this describes a router we know. */ static void connection_or_init_conn_from_address(or_connection_t *conn, - uint32_t addr, uint16_t port, + const tor_addr_t *addr, uint16_t port, const char *id_digest, int started_here) { @@ -397,11 +393,13 @@ connection_or_init_conn_from_address(or_connection_t *conn, conn->bandwidthrate = (int)options->BandwidthRate; conn->read_bucket = conn->bandwidthburst = (int)options->BandwidthBurst; connection_or_set_identity_digest(conn, id_digest); - conn->_base.addr = addr; + conn->_base.port = port; - conn->real_addr = addr; + tor_addr_copy(&conn->_base.addr, addr); + tor_addr_copy(&conn->real_addr, addr); if (r) { - if (conn->_base.addr == r->addr) + /* XXXX021 proposal 118 will make this more complex. */ + if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr)) conn->is_canonical = 1; if (!started_here) { /* Override the addr/port, so our log messages will make sense. @@ -413,8 +411,8 @@ connection_or_init_conn_from_address(or_connection_t *conn, * we wanted to log what OR a connection was to, and if we logged the * right IP address and port 56244, that wouldn't be as helpful. now we * log the "right" port too, so we know if it's moria1 or moria2. - */ - conn->_base.addr = r->addr; + */ + tor_addr_from_ipv4h(&conn->_base.addr, r->addr); conn->_base.port = r->or_port; } conn->nickname = tor_strdup(r->nickname); @@ -434,7 +432,7 @@ connection_or_init_conn_from_address(or_connection_t *conn, conn->identity_digest, DIGEST_LEN); } tor_free(conn->_base.address); - conn->_base.address = tor_dup_ip(addr); + conn->_base.address = tor_dup_addr(addr); } } @@ -509,13 +507,17 @@ connection_or_get_by_identity_digest(const char *digest) * Return the launched conn, or NULL if it failed. */ or_connection_t * -connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest) +connection_or_connect(const tor_addr_t *_addr, uint16_t port, + const char *id_digest) { or_connection_t *conn; or_options_t *options = get_options(); int socket_error = 0; + tor_addr_t addr; + tor_assert(_addr); tor_assert(id_digest); + tor_addr_copy(&addr, _addr); if (server_mode(options) && router_digest_is_me(id_digest)) { log_info(LD_PROTOCOL,"Client asked me to connect to myself. Refusing."); @@ -525,18 +527,18 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest) conn = TO_OR_CONN(connection_new(CONN_TYPE_OR, AF_INET)); /* set up conn so it's got all the data we need to remember */ - connection_or_init_conn_from_address(conn, addr, port, id_digest, 1); + connection_or_init_conn_from_address(conn, &addr, port, id_digest, 1); conn->_base.state = OR_CONN_STATE_CONNECTING; control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0); if (options->HttpsProxy) { /* we shouldn't connect directly. use the https proxy instead. */ - addr = options->HttpsProxyAddr; + tor_addr_from_ipv4h(&addr, options->HttpsProxyAddr); port = options->HttpsProxyPort; } switch (connection_connect(TO_CONN(conn), conn->_base.address, - addr, port, &socket_error)) { + &addr, port, &socket_error)) { case -1: /* If the connection failed immediately, and we're using * an https proxy, our https proxy is down. Don't blame the @@ -846,7 +848,7 @@ connection_tls_finish_handshake(or_connection_t *conn) if (tor_tls_used_v1_handshake(conn->tls)) { conn->link_proto = 1; if (!started_here) { - connection_or_init_conn_from_address(conn,conn->_base.addr, + connection_or_init_conn_from_address(conn, &conn->_base.addr, conn->_base.port, digest_rcvd, 0); } return connection_or_set_state_open(conn); @@ -855,7 +857,7 @@ connection_tls_finish_handshake(or_connection_t *conn) if (connection_init_or_handshake_state(conn, started_here) < 0) return -1; if (!started_here) { - connection_or_init_conn_from_address(conn,conn->_base.addr, + connection_or_init_conn_from_address(conn, &conn->_base.addr, conn->_base.port, digest_rcvd, 0); } return connection_or_send_versions(conn); @@ -910,8 +912,13 @@ connection_or_set_state_open(or_connection_t *conn) router_set_status(conn->identity_digest, 1); } else { /* only report it to the geoip module if it's not a known router */ - if (!router_get_by_digest(conn->identity_digest)) - geoip_note_client_seen(GEOIP_CLIENT_CONNECT, TO_CONN(conn)->addr, now); + if (!router_get_by_digest(conn->identity_digest)) { + if (tor_addr_family(&TO_CONN(conn)->addr) == AF_INET) { + /*XXXX021 IP6 support ipv6 geoip.*/ + uint32_t a = tor_addr_to_ipv4h(&TO_CONN(conn)->addr); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, a, now); + } + } } if (conn->handshake_state) { or_handshake_state_free(conn->handshake_state); @@ -1086,24 +1093,34 @@ connection_or_send_netinfo(or_connection_t *conn) cell_t cell; time_t now = time(NULL); routerinfo_t *me; + int len; + char *out; memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_NETINFO; - /* Their address. */ + /* Timestamp. */ set_uint32(cell.payload, htonl((uint32_t)now)); - cell.payload[4] = RESOLVED_TYPE_IPV4; - cell.payload[5] = 4; - set_uint32(cell.payload+6, htonl(conn->_base.addr)); + + /* Their address. */ + out = cell.payload + 4; + len = append_address_to_payload(out, &conn->_base.addr); + if (len<0) + return -1; + out += len; /* My address. */ if ((me = router_get_my_routerinfo())) { - cell.payload[10] = 1; /* only one address is supported. */ - cell.payload[11] = RESOLVED_TYPE_IPV4; - cell.payload[12] = 4; - set_uint32(cell.payload+13, htonl(me->addr)); + tor_addr_t my_addr; + *out++ = 1; /* only one address is supported. */ + + tor_addr_from_ipv4h(&my_addr, me->addr); + len = append_address_to_payload(out, &my_addr); + if (len < 0) + return -1; + out += len; } else { - cell.payload[10] = 0; + *out++ = 0; } connection_or_write_cell_to_buf(&cell, conn); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index e56d2787f..77e15c748 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -63,9 +63,10 @@ connection_cpu_finished_flushing(connection_t *conn) /** Pack addr,port,and circ_id; set *tag to the result. (See note on * cpuworker_main for wire format.) */ static void -tag_pack(char *tag, uint32_t addr, uint16_t port, circid_t circ_id) +tag_pack(char *tag, const tor_addr_t *addr, uint16_t port, circid_t circ_id) { - *(uint32_t *)tag = addr; + /*XXXX RETHINK THIS WHOLE MESS !!!! !NM NM NM NM*/ + *(uint32_t *)tag = tor_addr_to_ipv4h(addr); *(uint16_t *)(tag+4) = port; *(uint16_t *)(tag+6) = circ_id; } @@ -161,6 +162,8 @@ connection_cpu_process_inbuf(connection_t *conn) /* (Here we use connection_or_exact_get_by_addr_port rather than * get_by_identity_digest: we want a specific port here in * case there are multiple connections.) */ + /* XXXX021 This is dumb. We don't want just any connection with a matching + * IP and port: we want the exact one that sent us this CREATE cell. */ p_conn = connection_or_exact_get_by_addr_port(addr,port); if (p_conn) circ = circuit_get_by_circid_orconn(circ_id, p_conn); @@ -468,7 +471,7 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, tor_free(onionskin); return -1; } - tag_pack(tag, circ->p_conn->_base.addr, circ->p_conn->_base.port, + tag_pack(tag, &circ->p_conn->_base.addr, circ->p_conn->_base.port, circ->p_circ_id); cpuworker->state = CPUWORKER_STATE_BUSY_ONION; diff --git a/src/or/directory.c b/src/or/directory.c index febdced84..8dacc9c71 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -243,10 +243,10 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, /* This tries dirservers which we believe to be down, but ultimately, that's * harmless, and we may as well err on the side of getting things uploaded. */ - SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds, - { + SMARTLIST_FOREACH_BEGIN(dirservers, trusted_dir_server_t *, ds) { routerstatus_t *rs = &(ds->fake_status); size_t upload_len = payload_len; + tor_addr_t ds_addr; if ((type & ds->type) == 0) continue; @@ -260,13 +260,14 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, log_info(LD_DIR, "Uploading an extrainfo (length %d)", (int) extrainfo_len); } + tor_addr_from_ipv4h(&ds_addr, ds->addr); post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) || - !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port); + !fascist_firewall_allows_address_dir(&ds_addr, ds->dir_port); directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, post_via_tor, NULL, payload, upload_len, 0); - }); + } SMARTLIST_FOREACH_END(ds); if (!found) { char *s = authority_type_to_string(type); log_warn(LD_DIR, "Publishing server descriptor to directory authorities " @@ -344,7 +345,9 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, * so, for now, never assume the server supports that. */ routerinfo_t *ri = choose_random_entry(NULL); if (ri) { - directory_initiate_command(ri->address, ri->addr, + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, ri->addr); + directory_initiate_command(ri->address, &addr, ri->or_port, 0, 0, /* don't use conditional consensus url */ 1, ri->cache_info.identity_digest, @@ -459,6 +462,7 @@ directory_initiate_command_routerstatus(routerstatus_t *status, char address_buf[INET_NTOA_BUF_LEN+1]; struct in_addr in; const char *address; + tor_addr_t addr; if ((router = router_get_by_digest(status->identity_digest))) { address = router->address; } else { @@ -466,7 +470,8 @@ directory_initiate_command_routerstatus(routerstatus_t *status, tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); address = address_buf; } - directory_initiate_command(address, status->addr, + tor_addr_from_ipv4h(&addr, status->addr); + directory_initiate_command(address, &addr, status->or_port, status->dir_port, status->version_supports_conditional_consensus, status->version_supports_begindir, @@ -487,7 +492,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn) routerinfo_t *me = router_get_my_routerinfo(); if (me && router_digest_is_me(conn->identity_digest) && - me->addr == conn->_base.addr && + tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX021 prop 118*/ me->dir_port == conn->_base.port) return 1; } @@ -626,7 +631,8 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status) * 3) Else yes. */ static int -directory_command_should_use_begindir(or_options_t *options, uint32_t addr, +directory_command_should_use_begindir(or_options_t *options, + const tor_addr_t *addr, int or_port, uint8_t router_purpose, int anonymized_connection) { @@ -648,7 +654,7 @@ directory_command_should_use_begindir(or_options_t *options, uint32_t addr, * <b>supports_begindir</b>, and whose identity key digest is * <b>digest</b>. */ void -directory_initiate_command(const char *address, uint32_t addr, +directory_initiate_command(const char *address, const tor_addr_t *_addr, uint16_t or_port, uint16_t dir_port, int supports_conditional_consensus, int supports_begindir, const char *digest, @@ -661,14 +667,17 @@ directory_initiate_command(const char *address, uint32_t addr, or_options_t *options = get_options(); int socket_error = 0; int use_begindir = supports_begindir && - directory_command_should_use_begindir(options, addr, + directory_command_should_use_begindir(options, _addr, or_port, router_purpose, anonymized_connection); + tor_addr_t addr; tor_assert(address); - tor_assert(addr); + tor_assert(_addr); tor_assert(or_port || dir_port); tor_assert(digest); + tor_addr_copy(&addr, _addr); + log_debug(LD_DIR, "anonymized %d, use_begindir %d.", anonymized_connection, use_begindir); @@ -677,7 +686,7 @@ directory_initiate_command(const char *address, uint32_t addr, conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET)); /* set up conn so it's got all the data we need to remember */ - conn->_base.addr = addr; + tor_addr_copy(&conn->_base.addr, &addr); conn->_base.port = use_begindir ? or_port : dir_port; conn->_base.address = tor_strdup(address); memcpy(conn->identity_digest, digest, DIGEST_LEN); @@ -695,11 +704,11 @@ directory_initiate_command(const char *address, uint32_t addr, /* then we want to connect to dirport directly */ if (options->HttpProxy) { - addr = options->HttpProxyAddr; + tor_addr_from_ipv4h(&addr, options->HttpProxyAddr); dir_port = options->HttpProxyPort; } - switch (connection_connect(TO_CONN(conn), conn->_base.address, addr, + switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr, dir_port, &socket_error)) { case -1: connection_dir_request_failed(conn); /* retry if we want */ @@ -2092,7 +2101,7 @@ write_http_response_header_impl(dir_connection_t *conn, ssize_t length, tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type); cp += strlen(cp); } - if (!is_local_IP(conn->_base.addr)) { + if (!is_local_addr(&conn->_base.addr)) { /* Don't report the source address for a nearby/private connection. * Otherwise we tend to mis-report in cases where incoming ports are * being forwarded to a Tor server running behind the firewall. */ @@ -2541,19 +2550,26 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, { geoip_client_action_t act = is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2; - uint32_t addr = conn->_base.addr; - - if (conn->_base.linked_conn) { - connection_t *c = conn->_base.linked_conn; - if (c->type == CONN_TYPE_EXIT) { - circuit_t *circ = TO_EDGE_CONN(c)->on_circuit; - if (! CIRCUIT_IS_ORIGIN(circ)) { - or_connection_t *orconn = TO_OR_CIRCUIT(circ)->p_conn; - addr = orconn->_base.addr; + + if (tor_addr_family(&conn->_base.addr) == AF_INET) { + uint32_t addr = tor_addr_to_ipv4h(&conn->_base.addr); + + if (conn->_base.linked_conn) { + connection_t *c = conn->_base.linked_conn; + if (c->type == CONN_TYPE_EXIT) { + circuit_t *circ = TO_EDGE_CONN(c)->on_circuit; + if (! CIRCUIT_IS_ORIGIN(circ)) { + or_connection_t *orconn = TO_OR_CIRCUIT(circ)->p_conn; + if (tor_addr_family(&conn->_base.addr) == AF_INET) + addr = tor_addr_to_ipv4h(&orconn->_base.addr); + else + addr = 0; + } } } + if (addr) + geoip_note_client_seen(act, addr, time(NULL)); } - geoip_note_client_seen(act, addr, time(NULL)); } #endif diff --git a/src/or/dirserv.c b/src/or/dirserv.c index e43c57029..e59b84d90 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2770,8 +2770,9 @@ dirserv_test_reachability(time_t now, int try_all) static char ctr = 0; int bridge_auth = authdir_mode_bridge(get_options()); - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, { + SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, router) { const char *id_digest = router->cache_info.identity_digest; + tor_addr_t router_addr; if (router_is_me(router)) continue; if (bridge_auth && router->purpose != ROUTER_PURPOSE_BRIDGE) @@ -2784,10 +2785,10 @@ dirserv_test_reachability(time_t now, int try_all) /* Remember when we started trying to determine reachability */ if (!router->testing_since) router->testing_since = now; - connection_or_connect(router->addr, router->or_port, - id_digest); + tor_addr_from_ipv4h(&router_addr, router->addr); + connection_or_connect(&router_addr, router->or_port, id_digest); } - }); + } SMARTLIST_FOREACH_END(router); if (!try_all) /* increment ctr */ ctr = (ctr + 1) % 128; } diff --git a/src/or/dns.c b/src/or/dns.c index 5af868b27..16673e2d2 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -78,6 +78,7 @@ typedef struct cached_resolve_t { uint32_t magic; char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */ union { + /*XXXX021 Make this use a tor_addr_t OP6 */ uint32_t addr; /**< IPv4 addr for <b>address</b>. */ char *hostname; /**< Hostname for <b>address</b> (if a reverse lookup) */ } result; @@ -420,10 +421,11 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type) { case RESOLVED_TYPE_IPV4: buf[1] = 4; - set_uint32(buf+2, htonl(conn->_base.addr)); + set_uint32(buf+2, tor_addr_to_ipv4n(&conn->_base.addr)); set_uint32(buf+6, htonl(ttl)); buflen = 10; break; + /*XXXX021 IP6 need ipv6 implementation */ case RESOLVED_TYPE_ERROR_TRANSIENT: case RESOLVED_TYPE_ERROR: { @@ -644,7 +646,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, /* first check if exitconn->_base.address is an IP. If so, we already * know the answer. */ if (tor_inet_aton(exitconn->_base.address, &in) != 0) { - exitconn->_base.addr = ntohl(in.s_addr); + tor_addr_from_ipv4n(&exitconn->_base.addr, in.s_addr); exitconn->address_ttl = DEFAULT_DNS_TTL; return 1; } @@ -714,7 +716,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, tor_assert(is_resolve); *hostname_out = tor_strdup(resolve->result.hostname); } else { - exitconn->_base.addr = resolve->result.addr; + tor_addr_from_ipv4h(&exitconn->_base.addr, resolve->result.addr); } return 1; case CACHE_STATE_CACHED_FAILED: @@ -1017,7 +1019,7 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr, pendconn = pend->conn; /* don't pass complex things to the connection_mark_for_close macro */ assert_connection_ok(TO_CONN(pendconn),time(NULL)); - pendconn->_base.addr = addr; + tor_addr_from_ipv4h(&pendconn->_base.addr, addr); pendconn->address_ttl = ttl; if (outcome != DNS_RESOLVE_SUCCEEDED) { diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index 18623f6a4..5a1c02383 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -25,9 +25,9 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) struct evdns_server_question *q = NULL; struct sockaddr_storage addr; struct sockaddr *sa; - struct sockaddr_in *sin; int addrlen; - uint32_t ipaddr; + tor_addr_t tor_addr; + uint16_t port; int err = DNS_ERR_NONE; char *q_name; @@ -46,22 +46,24 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) } (void) addrlen; sa = (struct sockaddr*) &addr; - if (sa->sa_family != AF_INET) { - /* XXXX_IP6 Handle IPV6 */ - log_warn(LD_APP, "Requesting address wasn't ipv4."); + if (tor_addr_from_sockaddr(&tor_addr, sa)<0) { + log_warn(LD_APP, "Requesting address wasn't recognized."); evdns_server_request_respond(req, DNS_ERR_SERVERFAILED); return; - } else { - sin = (struct sockaddr_in*)&addr; - ipaddr = ntohl(sin->sin_addr.s_addr); } - if (!socks_policy_permits_address(ipaddr)) { + if (!socks_policy_permits_address(&tor_addr)) { log_warn(LD_APP, "Rejecting DNS request from disallowed IP."); evdns_server_request_respond(req, DNS_ERR_REFUSED); return; } + if (sa->sa_family == AF_INET) + port = ((struct sockaddr_in *)sa)->sin_port; + else + port = ((struct sockaddr_in6 *)sa)->sin6_port; + port = ntohs(port); + /* Now, let's find the first actual question of a type we can answer in this * DNS request. It makes us a little noncompliant to act like this; we * should fix that eventually if it turns out to make a difference for @@ -116,9 +118,9 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; conn->is_dns_request = 1; - TO_CONN(conn)->addr = ntohl(sin->sin_addr.s_addr); - TO_CONN(conn)->port = ntohs(sin->sin_port); - TO_CONN(conn)->address = tor_dup_ip(TO_CONN(conn)->addr); + tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr); + TO_CONN(conn)->port = port; + TO_CONN(conn)->address = tor_dup_addr(&tor_addr); if (q->type == EVDNS_TYPE_A) conn->socks_request->command = SOCKS_COMMAND_RESOLVE; diff --git a/src/or/main.c b/src/or/main.c index f2457c420..8e054f277 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1896,7 +1896,7 @@ tor_free_all(int postfork) smartlist_free(closeable_connection_lst); smartlist_free(active_linked_connection_lst); tor_free(timeout_event); - /* Stuff in util.c */ + /* Stuff in util.c and address.c*/ if (!postfork) { escaped(NULL); esc_router_info(NULL); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 1c685b64c..35b65cf10 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1002,15 +1002,18 @@ update_v2_networkstatus_cache_downloads(time_t now) if (authority) { /* An authority launches a separate connection for everybody. */ - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, - { + SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) + { char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */ + tor_addr_t addr; if (!(ds->type & V2_AUTHORITY)) continue; if (router_digest_is_me(ds->digest)) continue; + tor_addr_from_ipv4h(&addr, ds->addr); + /* Is this quite sensible with IPv6 or multiple addresses? */ if (connection_get_by_type_addr_port_purpose( - CONN_TYPE_DIR, ds->addr, ds->dir_port, + CONN_TYPE_DIR, &addr, ds->dir_port, DIR_PURPOSE_FETCH_NETWORKSTATUS)) { /* XXX020 the above dir_port won't be accurate if we're * doing a tunneled conn. In that case it should be or_port. @@ -1031,7 +1034,8 @@ update_v2_networkstatus_cache_downloads(time_t now) resource, NULL, 0 /* No payload. */, 0 /* No I-M-S. */); - }); + } + SMARTLIST_FOREACH_END(ds); } else { /* A non-authority cache launches one connection to a random authority. */ /* (Check whether we're currently fetching network-status objects.) */ diff --git a/src/or/or.h b/src/or/or.h index 61c98a7df..40b9efae9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -870,8 +870,8 @@ typedef struct connection_t { int socket_family; /**< Address family of this connection's socket. Usually * AF_INET, but it can also be AF_UNIX, or in the future * AF_INET6 */ - uint32_t addr; /**< IP of the other side of the connection; used to identify - * routers, along with port. */ + tor_addr_t addr; /**< IP of the other side of the connection; used to + * identify routers, along with port. */ uint16_t port; /**< If non-zero, port on the other end * of the connection. */ uint16_t marked_for_close; /**< Should we close this conn on the next @@ -922,7 +922,7 @@ typedef struct or_connection_t { * recent, we can rate limit it further. */ time_t client_used; - uint32_t real_addr; /**< The actual address that this connection came from + tor_addr_t real_addr; /**< The actual address that this connection came from * or went to. The <b>addr</b> field is prone to * getting overridden by the address from the router * descriptor matching <b>identity_digest</b>. */ @@ -1629,7 +1629,7 @@ typedef struct extend_info_t { * display. */ char identity_digest[DIGEST_LEN]; /**< Hash of this router's identity key. */ uint16_t port; /**< OR port. */ - uint32_t addr; /**< IP address in host order. */ + tor_addr_t addr; /**< IP address. */ crypto_pk_env_t *onion_key; /**< Current onionskin key. */ } extend_info_t; @@ -1997,14 +1997,12 @@ static INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x) /** An entry specifying a set of addresses and ports that should be remapped * to another address and port before exiting this exit node. */ typedef struct exit_redirect_t { - /* XXXX_IP6 make this whole mess ipv6-capable. (Does anybody use it? */ - - uint32_t addr; + tor_addr_t addr; uint16_t port_min; uint16_t port_max; maskbits_t maskbits; - uint32_t addr_dest; + tor_addr_t addr_dest; uint16_t port_dest; unsigned int is_redirect:1; } exit_redirect_t; @@ -2591,7 +2589,7 @@ int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info); void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop); extend_info_t *extend_info_alloc(const char *nickname, const char *digest, crypto_pk_env_t *onion_key, - uint32_t addr, uint16_t port); + const tor_addr_t *addr, uint16_t port); extend_info_t *extend_info_from_router(routerinfo_t *r); extend_info_t *extend_info_dup(extend_info_t *info); void extend_info_free(extend_info_t *info); @@ -2611,8 +2609,9 @@ int getinfo_helper_entry_guards(control_connection_t *conn, void clear_bridge_list(void); int routerinfo_is_a_configured_bridge(routerinfo_t *ri); -void bridge_add_from_config(uint32_t addr, uint16_t port, char *digest); -void retry_bridge_descriptor_fetch_directly(char *digest); +void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, + char *digest); +void retry_bridge_descriptor_fetch_directly(const char *digest); void fetch_bridge_descriptors(time_t now); void learned_bridge_descriptor(routerinfo_t *ri, int from_cache); int any_bridge_descriptors_known(void); @@ -2739,7 +2738,7 @@ int options_trial_assign(config_line_t *list, int use_defaults, int clear_first, char **msg); int resolve_my_address(int warn_severity, or_options_t *options, uint32_t *addr, char **hostname_out); -int is_local_IP(uint32_t ip) ATTR_PURE; +int is_local_addr(const tor_addr_t *addr) ATTR_PURE; void options_init(or_options_t *options); int options_init_from_torrc(int argc, char **argv); setopt_err_t options_init_from_string(const char *cf, @@ -2794,7 +2793,8 @@ void _connection_mark_for_close(connection_t *conn,int line, const char *file); void connection_expire_held_open(void); -int connection_connect(connection_t *conn, const char *address, uint32_t addr, +int connection_connect(connection_t *conn, const char *address, + const tor_addr_t *addr, uint16_t port, int *socket_error); int retry_all_listeners(smartlist_t *replaced_conns, smartlist_t *new_conns); @@ -2835,7 +2835,8 @@ edge_connection_t *connection_get_by_global_id(uint32_t id); connection_t *connection_get_by_type(int type); connection_t *connection_get_by_type_purpose(int type, int purpose); -connection_t *connection_get_by_type_addr_port_purpose(int type, uint32_t addr, +connection_t *connection_get_by_type_addr_port_purpose(int type, + const tor_addr_t *addr, uint16_t port, int purpose); connection_t *connection_get_by_type_state(int type, int state); connection_t *connection_get_by_type_state_rendquery(int type, int state, @@ -2948,8 +2949,8 @@ int connection_or_flushed_some(or_connection_t *conn); int connection_or_finished_flushing(or_connection_t *conn); int connection_or_finished_connecting(or_connection_t *conn); -or_connection_t *connection_or_connect(uint32_t addr, uint16_t port, - const char *id_digest); +or_connection_t *connection_or_connect(const tor_addr_t *addr, uint16_t port, + const char *id_digest); int connection_tls_start_handshake(or_connection_t *conn, int receiving); int connection_tls_continue_handshake(or_connection_t *conn); @@ -3144,7 +3145,7 @@ int connection_dir_process_inbuf(dir_connection_t *conn); int connection_dir_finished_flushing(dir_connection_t *conn); int connection_dir_finished_connecting(dir_connection_t *conn); void connection_dir_request_failed(dir_connection_t *conn); -void directory_initiate_command(const char *address, uint32_t addr, +void directory_initiate_command(const char *address, const tor_addr_t *addr, uint16_t or_port, uint16_t dir_port, int supports_conditional_consensus, int supports_begindir, const char *digest, @@ -3606,10 +3607,11 @@ typedef enum { } addr_policy_result_t; int firewall_is_fascist_or(void); -int fascist_firewall_allows_address_or(uint32_t addr, uint16_t port); -int fascist_firewall_allows_address_dir(uint32_t addr, uint16_t port); -int dir_policy_permits_address(uint32_t addr); -int socks_policy_permits_address(uint32_t addr); +int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port); +int fascist_firewall_allows_or(routerinfo_t *ri); +int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port); +int dir_policy_permits_address(const tor_addr_t *addr); +int socks_policy_permits_address(const tor_addr_t *addr); int authdir_policy_permits_address(uint32_t addr, uint16_t port); int authdir_policy_valid_address(uint32_t addr, uint16_t port); int authdir_policy_baddir_address(uint32_t addr, uint16_t port); @@ -3621,6 +3623,8 @@ int policies_parse_from_options(or_options_t *options); addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent); int cmp_addr_policies(smartlist_t *a, smartlist_t *b); +addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr, + uint16_t port, smartlist_t *policy); addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr, uint16_t port, smartlist_t *policy); int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, @@ -3693,6 +3697,11 @@ void assert_active_circuits_ok(or_connection_t *orconn); void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn); void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn); +int append_address_to_payload(char *payload_out, const tor_addr_t *addr); +const char *decode_address_from_payload(tor_addr_t *addr_out, + const char *payload, + int payload_len); + /********************************* rephist.c ***************************/ void rep_hist_init(void); diff --git a/src/or/policies.c b/src/or/policies.c index 60320a6b5..e7acdbba5 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -197,11 +197,11 @@ firewall_is_fascist_or(void) * connection to <b>addr</b>:<b>port</b>. */ static int -addr_policy_permits_address(uint32_t addr, uint16_t port, +addr_policy_permits_tor_addr(const tor_addr_t *addr, uint16_t port, smartlist_t *policy) { addr_policy_result_t p; - p = compare_addr_to_addr_policy(addr, port, policy); + p = compare_tor_addr_to_addr_policy(addr, port, policy); switch (p) { case ADDR_POLICY_PROBABLY_ACCEPTED: case ADDR_POLICY_ACCEPTED: @@ -215,40 +215,60 @@ addr_policy_permits_address(uint32_t addr, uint16_t port, } } +/* DOCDOC XXXX021 deprecate? */ +static int +addr_policy_permits_address(uint32_t addr, uint16_t port, + smartlist_t *policy) +{ + tor_addr_t a; + tor_addr_from_ipv4h(&a, addr); + return addr_policy_permits_tor_addr(&a, port, policy); +} + /** Return true iff we think our firewall will let us make an OR connection to * addr:port. */ int -fascist_firewall_allows_address_or(uint32_t addr, uint16_t port) +fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port) { - return addr_policy_permits_address(addr, port, + return addr_policy_permits_tor_addr(addr, port, reachable_or_addr_policy); } +/** DOCDOC */ +int +fascist_firewall_allows_or(routerinfo_t *ri) +{ + /* XXXX021 proposal 118 */ + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, ri->addr); + return fascist_firewall_allows_address_or(&addr, ri->or_port); +} + /** Return true iff we think our firewall will let us make a directory * connection to addr:port. */ int -fascist_firewall_allows_address_dir(uint32_t addr, uint16_t port) +fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port) { - return addr_policy_permits_address(addr, port, - reachable_dir_addr_policy); + return addr_policy_permits_tor_addr(addr, port, + reachable_dir_addr_policy); } /** Return 1 if <b>addr</b> is permitted to connect to our dir port, * based on <b>dir_policy</b>. Else return 0. */ int -dir_policy_permits_address(uint32_t addr) +dir_policy_permits_address(const tor_addr_t *addr) { - return addr_policy_permits_address(addr, 1, dir_policy); + return addr_policy_permits_tor_addr(addr, 1, dir_policy); } /** Return 1 if <b>addr</b> is permitted to connect to our socks port, * based on <b>socks_policy</b>. Else return 0. */ int -socks_policy_permits_address(uint32_t addr) +socks_policy_permits_address(const tor_addr_t *addr) { - return addr_policy_permits_address(addr, 1, socks_policy); + return addr_policy_permits_tor_addr(addr, 1, socks_policy); } /** Return 1 if <b>addr</b>:<b>port</b> is permitted to publish to our @@ -505,6 +525,16 @@ addr_policy_get_canonical_entry(addr_policy_t *e) return found->policy; } +/** DOCDOC */ +addr_policy_result_t +compare_addr_to_addr_policy(uint32_t addr, uint16_t port, smartlist_t *policy) +{ + /*XXXX021 deprecate this function? */ + tor_addr_t a; + tor_addr_from_ipv4h(&a, addr); + return compare_tor_addr_to_addr_policy(&a, port, policy); +} + /** Decide whether a given addr:port is definitely accepted, * definitely rejected, probably accepted, or probably rejected by a * given policy. If <b>addr</b> is 0, we don't know the IP of the @@ -523,8 +553,8 @@ addr_policy_get_canonical_entry(addr_policy_t *e) * addresses (127.0.0.1, and so on). But we'll try this for now. */ addr_policy_result_t -compare_addr_to_addr_policy(uint32_t _addr, uint16_t port, - smartlist_t *policy) +compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port, + smartlist_t *policy) { int maybe_reject = 0; int maybe_accept = 0; @@ -532,10 +562,7 @@ compare_addr_to_addr_policy(uint32_t _addr, uint16_t port, int maybe = 0; int i, len; int addr_is_unknown; - tor_addr_t addr; - /*XXXX021 ipv6 this function should take a tor_addr_t, not a uint32_t. */ - tor_addr_from_ipv4h(&addr, _addr); - addr_is_unknown = tor_addr_is_null(&addr); + addr_is_unknown = tor_addr_is_null(addr); len = policy ? smartlist_len(policy) : 0; @@ -558,7 +585,7 @@ compare_addr_to_addr_policy(uint32_t _addr, uint16_t port, } } else { /* Address is known */ - if (!tor_addr_compare_masked(&addr, &tmpe->addr, tmpe->maskbits, + if (!tor_addr_compare_masked(addr, &tmpe->addr, tmpe->maskbits, CMP_SEMANTIC)) { if (port >= tmpe->prt_min && port <= tmpe->prt_max) { /* Exact match for the policy */ diff --git a/src/or/relay.c b/src/or/relay.c index 155f06669..8b68c8cf7 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1839,6 +1839,57 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, } } +/** DOCDOC */ +int +append_address_to_payload(char *payload_out, const tor_addr_t *addr) +{ + uint32_t a; + switch (tor_addr_family(addr)) { + case AF_INET: + payload_out[0] = RESOLVED_TYPE_IPV4; + payload_out[1] = 4; + a = tor_addr_to_ipv4n(addr); + memcpy(payload_out+2, &a, 4); + return 6; + case AF_INET6: + payload_out[0] = RESOLVED_TYPE_IPV6; + payload_out[1] = 16; + memcpy(payload_out+2, tor_addr_to_in6_addr8(addr), 16); + return 18; + case AF_UNSPEC: + default: + return -1; + } +} + +/** DODOC */ +const char * +decode_address_from_payload(tor_addr_t *addr_out, const char *payload, + int payload_len) +{ + if (payload_len < 2) + return NULL; + if (payload_len < 2+(uint8_t)payload[1]) + return NULL; + + switch (payload[0]) { + case RESOLVED_TYPE_IPV4: + if (payload[1] != 4) + return NULL; + tor_addr_from_ipv4n(addr_out, get_uint32(payload+2)); + break; + case RESOLVED_TYPE_IPV6: + if (payload[1] != 16) + return NULL; + tor_addr_from_ipv6_bytes(addr_out, payload+2); + break; + default: + tor_addr_make_unspec(addr_out); + break; + } + return payload + 2 + (uint8_t)payload[1]; +} + /** Fail with an assert if the active circuits ring on <b>orconn</b> is * corrupt. */ void diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 394e0eca8..e05fef90e 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -124,7 +124,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, int klen; tmp[0] = 2; /* version 2 of the cell format */ /* nul pads */ - set_uint32(tmp+1, htonl(extend_info->addr)); + set_uint32(tmp+1, tor_addr_to_ipv4h(&extend_info->addr)); set_uint16(tmp+5, htons(extend_info->port)); memcpy(tmp+7, extend_info->identity_digest, DIGEST_LEN); klen = crypto_pk_asn1_encode(extend_info->onion_key, tmp+7+DIGEST_LEN+2, diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index b9e2e81f0..7361903ac 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -200,7 +200,7 @@ rend_encode_v2_intro_points(char **ipos_base64, goto done; } /* Assemble everything for this introduction point. */ - address = tor_dup_ip(info->addr); + address = tor_dup_addr(&info->addr); res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written, "introduction-point %s\n" "ip-address %s\n" diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 6cf4d591a..431d87224 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -22,7 +22,7 @@ static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro, typedef struct rend_service_port_config_t { uint16_t virtual_port; uint16_t real_port; - uint32_t real_addr; + tor_addr_t real_addr; } rend_service_port_config_t; /** Try to maintain this many intro points per service if possible. */ @@ -121,7 +121,6 @@ rend_add_service(rend_service_t *service) { int i; rend_service_port_config_t *p; - struct in_addr addr; service->intro_nodes = smartlist_create(); @@ -152,12 +151,9 @@ rend_add_service(rend_service_t *service) log_debug(LD_REND,"Configuring service with directory \"%s\"", service->directory); for (i = 0; i < smartlist_len(service->ports); ++i) { - char addrbuf[INET_NTOA_BUF_LEN]; p = smartlist_get(service->ports, i); - addr.s_addr = htonl(p->real_addr); - tor_inet_ntoa(&addr, addrbuf, sizeof(addrbuf)); log_debug(LD_REND,"Service maps port %d to %s:%d", - p->virtual_port, addrbuf, p->real_port); + p->virtual_port, fmt_addr(&p->real_addr), p->real_port); } } } @@ -176,7 +172,7 @@ parse_port_config(const char *string) int virtport; int realport; uint16_t p; - uint32_t addr; + tor_addr_t addr; const char *addrport; rend_service_port_config_t *result = NULL; @@ -198,11 +194,11 @@ parse_port_config(const char *string) if (smartlist_len(sl) == 1) { /* No addr:port part; use default. */ realport = virtport; - addr = 0x7F000001u; /* 127.0.0.1 */ + tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */ } else { addrport = smartlist_get(sl,1); if (strchr(addrport, ':') || strchr(addrport, '.')) { - if (parse_addr_port(LOG_WARN, addrport, NULL, &addr, &p)<0) { + if (tor_addr_port_parse(addrport, &addr, &p)<0) { log_warn(LD_CONFIG,"Unparseable address in hidden service port " "configuration."); goto err; @@ -216,14 +212,14 @@ parse_port_config(const char *string) "service port configuration.", escaped(addrport)); goto err; } - addr = 0x7F000001u; /* Default to 127.0.0.1 */ + tor_addr_from_ipv4h(&addr, 0x7F000001u); /* Default to 127.0.0.1 */ } } result = tor_malloc(sizeof(rend_service_port_config_t)); result->virtual_port = virtport; result->real_port = realport; - result->real_addr = addr; + tor_addr_copy(&result->real_addr, &addr); err: SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); @@ -538,7 +534,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request, /* Version 2 INTRODUCE2 cell. */ int klen; extend_info = tor_malloc_zero(sizeof(extend_info_t)); - extend_info->addr = ntohl(get_uint32(buf+1)); + tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf+1)); extend_info->port = ntohs(get_uint16(buf+5)); memcpy(extend_info->identity_digest, buf+7, DIGEST_LEN); extend_info->nickname[0] = '$'; @@ -1415,7 +1411,7 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, chosen_port = smartlist_choose(matching_ports); smartlist_free(matching_ports); if (chosen_port) { - conn->_base.addr = chosen_port->real_addr; + tor_addr_copy(&conn->_base.addr, &chosen_port->real_addr); conn->_base.port = chosen_port->real_port; return 0; } diff --git a/src/or/router.c b/src/or/router.c index bd8cb8351..842cb7b52 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -736,6 +736,7 @@ consider_testing_reachability(int test_or, int test_dir) { routerinfo_t *me = router_get_my_routerinfo(); int orport_reachable = check_whether_orport_reachable(); + tor_addr_t addr; if (!me) return; @@ -750,12 +751,13 @@ consider_testing_reachability(int test_or, int test_dir) me->address, me->or_port); } + tor_addr_from_ipv4h(&addr, me->addr); if (test_dir && !check_whether_dirport_reachable() && !connection_get_by_type_addr_port_purpose( - CONN_TYPE_DIR, me->addr, me->dir_port, + CONN_TYPE_DIR, &addr, me->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)) { /* ask myself, via tor, for my server descriptor. */ - directory_initiate_command(me->address, me->addr, + directory_initiate_command(me->address, &addr, me->or_port, me->dir_port, 0, /* does not matter */ 0, me->cache_info.identity_digest, @@ -1111,10 +1113,10 @@ router_compare_to_my_exit_policy(edge_connection_t *conn) /* make sure it's resolved to something. this way we can't get a 'maybe' below. */ - if (!conn->_base.addr) + if (tor_addr_is_null(&conn->_base.addr)) return -1; - return compare_addr_to_addr_policy(conn->_base.addr, conn->_base.port, + return compare_tor_addr_to_addr_policy(&conn->_base.addr, conn->_base.port, desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; } @@ -1543,7 +1545,7 @@ router_new_address_suggestion(const char *suggestion, /* Don't believe anybody who says our IP is, say, 127.0.0.1. */ return; } - if (addr == d_conn->_base.addr) { + if (tor_addr_eq_ipv4h(&d_conn->_base.addr, addr)) { /* Don't believe anybody who says our IP is their IP. */ log_debug(LD_DIR, "A directory server told us our IP address is %s, " "but he's just reporting his own IP address. Ignoring.", diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 66e80f2dc..bce675ce0 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -994,10 +994,11 @@ router_pick_directory_server_impl(authority_type_t type, int flags) overloaded_tunnel = smartlist_create(); /* Find all the running dirservers we know about. */ - SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, status, - { + SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, + status) { int is_trusted; int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now; + tor_addr_t addr; if (!status->is_running || !status->dir_port || !status->is_valid) continue; if (status->is_bad_directory) @@ -1016,18 +1017,21 @@ router_pick_directory_server_impl(authority_type_t type, int flags) if ((type & EXTRAINFO_CACHE) && !router_supports_extrainfo(status->identity_digest, 0)) continue; + + /* XXXX021 IP6 proposal 118 */ + tor_addr_from_ipv4h(&addr, status->addr); + if (prefer_tunnel && status->version_supports_begindir && (!fascistfirewall || - fascist_firewall_allows_address_or(status->addr, status->or_port))) + fascist_firewall_allows_address_or(&addr, status->or_port))) smartlist_add(is_trusted ? trusted_tunnel : is_overloaded ? overloaded_tunnel : tunnel, status); else if (!fascistfirewall || - fascist_firewall_allows_address_dir(status->addr, - status->dir_port)) + fascist_firewall_allows_address_dir(&addr, status->dir_port)) smartlist_add(is_trusted ? trusted_direct : is_overloaded ? overloaded_direct : direct, status); - }); + } SMARTLIST_FOREACH_END(status); if (smartlist_len(tunnel)) { result = routerstatus_sl_choose_by_bandwidth(tunnel); @@ -1078,10 +1082,11 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags) overloaded_direct = smartlist_create(); overloaded_tunnel = smartlist_create(); - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d, + SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, d) { int is_overloaded = d->fake_status.last_dir_503_at + DIR_503_TIMEOUT > now; + tor_addr_t addr; if (!d->is_running) continue; if ((type & d->type) == 0) continue; @@ -1090,17 +1095,22 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags) continue; if (requireother && me && router_digest_is_me(d->digest)) continue; + + /* XXXX021 IP6 proposal 118 */ + tor_addr_from_ipv4h(&addr, d->addr); + if (prefer_tunnel && d->or_port && (!fascistfirewall || - fascist_firewall_allows_address_or(d->addr, d->or_port))) + fascist_firewall_allows_address_or(&addr, d->or_port))) smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, &d->fake_status); else if (!fascistfirewall || - fascist_firewall_allows_address_dir(d->addr, d->dir_port)) + fascist_firewall_allows_address_dir(&addr, d->dir_port)) smartlist_add(is_overloaded ? overloaded_direct : direct, &d->fake_status); - }); + } + SMARTLIST_FOREACH_END(d); if (smartlist_len(tunnel)) { result = smartlist_choose(tunnel); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 811e276a7..d86c6f05a 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -3548,7 +3548,6 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, directory_token_t *tok; rend_intro_point_t *intro; extend_info_t *info; - struct in_addr ip; int result, num_ok=1; memarea_t *area = NULL; tor_assert(parsed); @@ -3621,12 +3620,17 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, info->identity_digest, DIGEST_LEN); /* Parse IP address. */ tok = find_first_by_keyword(tokens, R_IPO_IP_ADDRESS); - if (tor_inet_aton(tok->args[0], &ip) == 0) { - log_warn(LD_REND, "Could not parse IP address."); + if (tor_addr_from_str(&info->addr, tok->args[0])<0) { + log_warn(LD_REND, "Could not parse introduction point address."); rend_intro_point_free(intro); goto err; } - info->addr = ntohl(ip.s_addr); + if (tor_addr_family(&info->addr) != AF_INET) { + log_warn(LD_REND, "Introduction point address was not ipv4."); + rend_intro_point_free(intro); + goto err; + } + /* Parse onion port. */ tok = find_first_by_keyword(tokens, R_IPO_ONION_PORT); info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535, diff --git a/src/or/test.c b/src/or/test.c index a3aa9906f..0f19e5b01 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -1336,13 +1336,13 @@ test_util_ip6_helpers(void) test_eq(sizeof(struct sockaddr_in), tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage, sizeof(sa_storage))); - test_eq(1234, sin->sin_port); + test_eq(1234, ntohs(sin->sin_port)); test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr)); memset(&sa_storage, 0, sizeof(sa_storage)); sin6 = (struct sockaddr_in6 *)&sa_storage; sin6->sin6_family = AF_INET6; - sin6->sin6_port = 7070; + sin6->sin6_port = htons(7070); sin6->sin6_addr.s6_addr[0] = 128; tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6); test_eq(tor_addr_family(&t1), AF_INET6); @@ -1354,7 +1354,7 @@ test_util_ip6_helpers(void) tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage, sizeof(sa_storage))); test_eq(AF_INET6, sin6->sin6_family); - test_eq(9999, sin6->sin6_port); + test_eq(9999, ntohs(sin6->sin6_port)); test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0])); /* ==== tor_addr_lookup: static cases. (Can't test dns without knowing we @@ -3901,8 +3901,8 @@ test_rend_fns_v2(void) base16_encode(intro->extend_info->nickname + 1, sizeof(intro->extend_info->nickname) - 1, intro->extend_info->identity_digest, DIGEST_LEN); - intro->extend_info->addr = crypto_rand_int(65536); /* Does not cover all - * IP addresses. */ + /* Does not cover all IP addresses. */ + tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536)); intro->extend_info->port = crypto_rand_int(65536); intro->intro_key = crypto_pk_dup_key(pk2); smartlist_add(generated->intro_nodes, intro); @@ -3940,7 +3940,7 @@ test_rend_fns_v2(void) test_memeq(gen_info->identity_digest, par_info->identity_digest, DIGEST_LEN); test_streq(gen_info->nickname, par_info->nickname); - test_eq(gen_info->addr, par_info->addr); + test_assert(tor_addr_eq(&gen_info->addr, &par_info->addr)); test_eq(gen_info->port, par_info->port); } tor_free(intro_points_encrypted); |