Commit 960a0f0a authored by Nick Mathewson's avatar Nick Mathewson 🎨
Browse files

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
parent 750bb795
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
......
......@@ -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.)
......
......@@ -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.
......
......@@ -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);
......
......@@ -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 &&