Treat a changed IPv6 ORPort like an IPv4 one in retry_all_listeners()

Fix for bug 6026
This commit is contained in:
Nick Mathewson 2013-03-11 17:20:43 -04:00
parent 051b1e8ac4
commit 07e26005a6
5 changed files with 38 additions and 10 deletions

4
changes/bug6026 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes:
- Relays now treat a changed IPv6 ORPort as sufficient reason to
publish an updated descriptor. Fix for bug 6026; bugfix for
0.2.4.1-alpha.

View File

@ -5561,7 +5561,8 @@ get_first_listener_addrport_string(int listener_type)
to iterate all listener connections and find out in which to iterate all listener connections and find out in which
port it ended up listening: */ port it ended up listening: */
if (cfg->port == CFG_AUTO_PORT) { if (cfg->port == CFG_AUTO_PORT) {
port = router_get_active_listener_port_by_type(listener_type); port = router_get_active_listener_port_by_type_af(listener_type,
tor_addr_family(&cfg->addr));
if (!port) if (!port)
return NULL; return NULL;
} else { } else {

View File

@ -2054,6 +2054,8 @@ retry_all_listeners(smartlist_t *replaced_conns,
const or_options_t *options = get_options(); const or_options_t *options = get_options();
int retval = 0; int retval = 0;
const uint16_t old_or_port = router_get_advertised_or_port(options); const uint16_t old_or_port = router_get_advertised_or_port(options);
const uint16_t old_or_port_ipv6 =
router_get_advertised_or_port_by_af(options,AF_INET6);
const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0); const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
@ -2082,8 +2084,9 @@ retry_all_listeners(smartlist_t *replaced_conns,
smartlist_free(listeners); smartlist_free(listeners);
/* XXXprop186 should take all advertised ports into account */
if (old_or_port != router_get_advertised_or_port(options) || if (old_or_port != router_get_advertised_or_port(options) ||
old_or_port_ipv6 != router_get_advertised_or_port_by_af(options,
AF_INET6) ||
old_dir_port != router_get_advertised_dir_port(options, 0)) { old_dir_port != router_get_advertised_dir_port(options, 0)) {
/* Our chosen ORPort or DirPort is not what it used to be: the /* Our chosen ORPort or DirPort is not what it used to be: the
* descriptor we had (if any) should be regenerated. (We won't * descriptor we had (if any) should be regenerated. (We won't

View File

@ -1459,13 +1459,18 @@ consider_publishable_server(int force)
/** XXX not a very good interface. it's not reliable when there are /** XXX not a very good interface. it's not reliable when there are
multiple listeners. */ multiple listeners. */
uint16_t uint16_t
router_get_active_listener_port_by_type(int listener_type) router_get_active_listener_port_by_type_af(int listener_type,
sa_family_t family)
{ {
/* Iterate all connections, find one of the right kind and return /* Iterate all connections, find one of the right kind and return
the port. Not very sophisticated or fast, but effective. */ the port. Not very sophisticated or fast, but effective. */
const connection_t *c = connection_get_by_type(listener_type); smartlist_t *conns = get_connection_array();
if (c) SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
return c->port; if (conn->type == listener_type && !conn->marked_for_close &&
conn->socket_family == family) {
return conn->port;
}
} SMARTLIST_FOREACH_END(conn);
return 0; return 0;
} }
@ -1477,13 +1482,24 @@ router_get_active_listener_port_by_type(int listener_type)
uint16_t uint16_t
router_get_advertised_or_port(const or_options_t *options) router_get_advertised_or_port(const or_options_t *options)
{ {
int port = get_primary_or_port(); return router_get_advertised_or_port_by_af(options, AF_INET);
}
/** As router_get_advertised_or_port(), but allows an address family argument.
*/
uint16_t
router_get_advertised_or_port_by_af(const or_options_t *options,
sa_family_t family)
{
int port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
family);
(void)options; (void)options;
/* If the port is in 'auto' mode, we have to use /* If the port is in 'auto' mode, we have to use
router_get_listener_port_by_type(). */ router_get_listener_port_by_type(). */
if (port == CFG_AUTO_PORT) if (port == CFG_AUTO_PORT)
return router_get_active_listener_port_by_type(CONN_TYPE_OR_LISTENER); return router_get_active_listener_port_by_type_af(CONN_TYPE_OR_LISTENER,
family);
return port; return port;
} }
@ -1503,7 +1519,8 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
return dirport; return dirport;
if (dirport_configured == CFG_AUTO_PORT) if (dirport_configured == CFG_AUTO_PORT)
return router_get_active_listener_port_by_type(CONN_TYPE_DIR_LISTENER); return router_get_active_listener_port_by_type_af(CONN_TYPE_DIR_LISTENER,
AF_INET);
return dirport_configured; return dirport_configured;
} }

View File

@ -58,8 +58,11 @@ int authdir_mode_publishes_statuses(const or_options_t *options);
int authdir_mode_tests_reachability(const or_options_t *options); int authdir_mode_tests_reachability(const or_options_t *options);
int authdir_mode_bridge(const or_options_t *options); int authdir_mode_bridge(const or_options_t *options);
uint16_t router_get_active_listener_port_by_type(int listener_type); uint16_t router_get_active_listener_port_by_type_af(int listener_type,
sa_family_t family);
uint16_t router_get_advertised_or_port(const or_options_t *options); uint16_t router_get_advertised_or_port(const or_options_t *options);
uint16_t router_get_advertised_or_port_by_af(const or_options_t *options,
sa_family_t family);
uint16_t router_get_advertised_dir_port(const or_options_t *options, uint16_t router_get_advertised_dir_port(const or_options_t *options,
uint16_t dirport); uint16_t dirport);