From 07e26005a6cb7e47f1f90fcf6a377dfaaaa56789 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Mar 2013 17:20:43 -0400 Subject: [PATCH] Treat a changed IPv6 ORPort like an IPv4 one in retry_all_listeners() Fix for bug 6026 --- changes/bug6026 | 4 ++++ src/or/config.c | 3 ++- src/or/connection.c | 5 ++++- src/or/router.c | 31 ++++++++++++++++++++++++------- src/or/router.h | 5 ++++- 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 changes/bug6026 diff --git a/changes/bug6026 b/changes/bug6026 new file mode 100644 index 0000000000..de5d6ead01 --- /dev/null +++ b/changes/bug6026 @@ -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. diff --git a/src/or/config.c b/src/or/config.c index 15138f9d7b..1c48c66167 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -5561,7 +5561,8 @@ get_first_listener_addrport_string(int listener_type) to iterate all listener connections and find out in which port it ended up listening: */ 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) return NULL; } else { diff --git a/src/or/connection.c b/src/or/connection.c index c659e65fe5..5812d83163 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -2054,6 +2054,8 @@ retry_all_listeners(smartlist_t *replaced_conns, const or_options_t *options = get_options(); int retval = 0; 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); SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { @@ -2082,8 +2084,9 @@ retry_all_listeners(smartlist_t *replaced_conns, smartlist_free(listeners); - /* XXXprop186 should take all advertised ports into account */ 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)) { /* Our chosen ORPort or DirPort is not what it used to be: the * descriptor we had (if any) should be regenerated. (We won't diff --git a/src/or/router.c b/src/or/router.c index 422fe5db2e..91de221b28 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1459,13 +1459,18 @@ consider_publishable_server(int force) /** XXX not a very good interface. it's not reliable when there are multiple listeners. */ 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 the port. Not very sophisticated or fast, but effective. */ - const connection_t *c = connection_get_by_type(listener_type); - if (c) - return c->port; + smartlist_t *conns = get_connection_array(); + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { + if (conn->type == listener_type && !conn->marked_for_close && + conn->socket_family == family) { + return conn->port; + } + } SMARTLIST_FOREACH_END(conn); return 0; } @@ -1477,13 +1482,24 @@ router_get_active_listener_port_by_type(int listener_type) uint16_t 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; /* If the port is in 'auto' mode, we have to use router_get_listener_port_by_type(). */ 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; } @@ -1503,7 +1519,8 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) return dirport; 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; } diff --git a/src/or/router.h b/src/or/router.h index fd2076af01..dc894d1a1f 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -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_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_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 dirport);