From da6e0993dc4a0037933a522e2f578c145f6538cc Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Sat, 31 Mar 2012 13:48:20 +0200 Subject: [PATCH 1/5] Generalize fmt_addr() to support IPv6 decorations. --- src/common/address.c | 4 ++-- src/common/address.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index 676c485897..62cf16c03c 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -991,11 +991,11 @@ tor_dup_addr(const tor_addr_t *addr) * fmt_addr invalidates the last result of the function. This * function is not thread-safe. */ const char * -fmt_addr(const tor_addr_t *addr) +fmt_addr_impl(const tor_addr_t *addr, int decorate) { static char buf[TOR_ADDR_BUF_LEN]; if (!addr) return ""; - if (tor_addr_to_str(buf, addr, sizeof(buf), 0)) + if (tor_addr_to_str(buf, addr, sizeof(buf), decorate)) return buf; else return "???"; diff --git a/src/common/address.h b/src/common/address.h index ede035d642..bdb14eb390 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -135,7 +135,9 @@ 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); +#define fmt_addr(a) fmt_addr_impl(a, 0) +#define fmt_and_decorate_addr(a) fmt_addr_impl(a, 1) +const char *fmt_addr_impl(const tor_addr_t *addr, int decorate); const char * fmt_addr32(uint32_t addr); int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr); From fedf76a2e6452124c38ecc51cea6567b9d5cc23d Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Sat, 31 Mar 2012 13:54:09 +0200 Subject: [PATCH 2/5] Introduce and use router_get_active_listener_port_by_type(). router_get_active_listener_port_by_type() iterates all connections, trying to find a listener of a specific type, and returns its TCP port. --- src/or/router.c | 35 +++++++++++++++++++++++------------ src/or/router.h | 1 + 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/or/router.c b/src/or/router.c index bf15689a15..67d26e13e0 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1216,6 +1216,20 @@ consider_publishable_server(int force) } } +/** Return the port of the first active listener of type + * listener_type. */ +uint16_t +router_get_active_listener_port_by_type(int listener_type) +{ + /* 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; + + return 0; +} + /** Return the port that we should advertise as our ORPort; this is either * the one configured in the ORPort option, or the one we actually bound to * if ORPort is "auto". @@ -1226,12 +1240,11 @@ router_get_advertised_or_port(const or_options_t *options) int port = get_primary_or_port(); (void)options; - if (port == CFG_AUTO_PORT) { - connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER); - if (c) - return c->port; - return 0; - } + /* 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 port; } @@ -1248,12 +1261,10 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) if (!dirport_configured) return dirport; - if (dirport_configured == CFG_AUTO_PORT) { - connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER); - if (c) - return c->port; - return 0; - } + + if (dirport_configured == CFG_AUTO_PORT) + return router_get_active_listener_port_by_type(CONN_TYPE_DIR_LISTENER); + return dirport_configured; } diff --git a/src/or/router.h b/src/or/router.h index fb914349f3..294736e70c 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -53,6 +53,7 @@ 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_advertised_or_port(const or_options_t *options); uint16_t router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport); From 10232dc0423792a8fb61b9ec136d7ffd5484216b Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Sat, 31 Mar 2012 14:04:58 +0200 Subject: [PATCH 3/5] Pass OR address to PT proxy, even with IPv6 or ORListenAddress. Introduce get_first_listener_addrport_for_pt() which returns a string containing the addrport of the first listener we could find. Use it to form the TOR_PT_ORPORT managed proxy protocol line. --- src/or/config.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ src/or/config.h | 2 ++ src/or/transports.c | 9 ++++---- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index 2a8c540968..5ea1f5edee 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -6026,6 +6026,59 @@ get_configured_ports(void) return configured_ports; } +/** Return an
: string representation of the address + * where the first listener_type listener waits for + * connections. Return NULL if we couldn't find a listener. The + * string is allocated on the heap and it's the responsibility of the + * caller to free it after use. + * + * This function is meant to be used by the pluggable transport proxy + * spawning code. */ +char * +get_first_listener_addrport_for_pt(int listener_type) +{ + static const char *ipv4_localhost = "127.0.0.1"; + static const char *ipv6_localhost = "[::1]"; + const char *address; + uint16_t port; + char *string = NULL; + + if (!configured_ports) + return NULL; + + SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) { + + if (cfg->type == listener_type && + tor_addr_family(&cfg->addr) != AF_UNSPEC) { + + /* We found the first listener of the type we are interested in! */ + + /* If a listener is listening on INADDR_ANY, assume that it's + also listening on 127.0.0.1, and point the transport proxy + there: */ + if (tor_addr_is_null(&cfg->addr)) + address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost; + else + address = fmt_and_decorate_addr(&cfg->addr); + + /* If a listener is configured with port 'auto', we are forced + 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); + else + port = cfg->port; + + tor_asprintf(&string, "%s:%u", address, port); + + return string; + } + + } SMARTLIST_FOREACH_END(cfg); + + return NULL; +} + /** Return the first advertised port of type listener_type in address_family. */ int diff --git a/src/or/config.h b/src/or/config.h index 0f7c618861..fd84d9b606 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -72,6 +72,8 @@ int get_first_advertised_port_by_type_af(int listener_type, #define get_primary_dir_port() \ (get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET)) +char *get_first_listener_addrport_for_pt(int listener_type); + int options_need_geoip_info(const or_options_t *options, const char **reason_out); diff --git a/src/or/transports.c b/src/or/transports.c index 564603e1fe..1f2149381e 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -957,8 +957,6 @@ get_bindaddr_for_server_proxy(const managed_proxy_t *mp) static process_environment_t * create_managed_proxy_environment(const managed_proxy_t *mp) { - const or_options_t *options = get_options(); - /* Environment variables to be added to or set in mp's environment. */ smartlist_t *envs = smartlist_new(); /* XXXX The next time someone touches this code, shorten the name of @@ -993,8 +991,11 @@ create_managed_proxy_environment(const managed_proxy_t *mp) } if (mp->is_server) { - smartlist_add_asprintf(envs, "TOR_PT_ORPORT=127.0.0.1:%s", - options->ORPort->value); + { + char *orport_tmp = get_first_listener_addrport_for_pt(CONN_TYPE_OR_LISTENER); + smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp); + tor_free(orport_tmp); + } { char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp); From b03f90b5383744593dc1e83fc5834c965573a4dc Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Sat, 31 Mar 2012 14:05:12 +0200 Subject: [PATCH 4/5] Add changes file for #4865. --- changes/bug4865 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/bug4865 diff --git a/changes/bug4865 b/changes/bug4865 new file mode 100644 index 0000000000..e165c41f71 --- /dev/null +++ b/changes/bug4865 @@ -0,0 +1,4 @@ + o Major bugfixes: + - Pass correct OR address to managed proxies, even when + ORListenAddress is used. Fixes bug #4865; bugfix on + 0.2.3.9-alpha. From 6d2898607bd831944c6c15b6e15200a426149811 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 12 Apr 2012 22:42:37 +0200 Subject: [PATCH 5/5] Fix issues found by nickm. * Document fmt_addr_impl() and friends. * Parenthesize macro arguments. * Rename get_first_listener_addrport_for_pt() to get_first_listener_addrport_string(). * Handle port_cfg_t with no_listen. * Handle failure of router_get_active_listener_port_by_type(). * Add an XXX to router_get_active_listener_port_by_type(). --- src/common/address.c | 13 +++++++++---- src/common/address.h | 9 +++++++-- src/or/config.c | 14 ++++++++++---- src/or/config.h | 2 +- src/or/router.c | 2 ++ src/or/transports.c | 2 +- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index 62cf16c03c..7f78d1e4d3 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -986,10 +986,15 @@ tor_dup_addr(const tor_addr_t *addr) } } -/** Return a string representing the address addr. This string is - * statically allocated, and must not be freed. Each call to - * fmt_addr invalidates the last result of the function. This - * function is not thread-safe. */ +/** Return a string representing the address addr. This string + * is statically allocated, and must not be freed. Each call to + * fmt_addr_impl invalidates the last result of the function. + * This function is not thread-safe. If decorate is set, add + * brackets to IPv6 addresses. + * + * It's better to use the wrapper macros of this function: + * fmt_addr() and fmt_and_decorate_addr(). + */ const char * fmt_addr_impl(const tor_addr_t *addr, int decorate) { diff --git a/src/common/address.h b/src/common/address.h index bdb14eb390..761eed661c 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -135,8 +135,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; -#define fmt_addr(a) fmt_addr_impl(a, 0) -#define fmt_and_decorate_addr(a) fmt_addr_impl(a, 1) + +/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6 + * addresses. */ +#define fmt_addr(a) fmt_addr_impl((a), 0) +/** Wrapper function of fmt_addr_impl(). It decorates IPv6 + * addresses. */ +#define fmt_and_decorate_addr(a) fmt_addr_impl((a), 1) const char *fmt_addr_impl(const tor_addr_t *addr, int decorate); const char * fmt_addr32(uint32_t addr); int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr); diff --git a/src/or/config.c b/src/or/config.c index 5ea1f5edee..3fc543c41f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -6033,9 +6033,10 @@ get_configured_ports(void) * caller to free it after use. * * This function is meant to be used by the pluggable transport proxy - * spawning code. */ + * spawning code, please make sure that it fits your purposes before + * using it. */ char * -get_first_listener_addrport_for_pt(int listener_type) +get_first_listener_addrport_string(int listener_type) { static const char *ipv4_localhost = "127.0.0.1"; static const char *ipv6_localhost = "[::1]"; @@ -6047,6 +6048,8 @@ get_first_listener_addrport_for_pt(int listener_type) return NULL; SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) { + if (cfg->no_listen) + continue; if (cfg->type == listener_type && tor_addr_family(&cfg->addr) != AF_UNSPEC) { @@ -6064,10 +6067,13 @@ get_first_listener_addrport_for_pt(int listener_type) /* If a listener is configured with port 'auto', we are forced to iterate all listener connections and find out in which 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); - else + if (!port) + return NULL; + } else { port = cfg->port; + } tor_asprintf(&string, "%s:%u", address, port); diff --git a/src/or/config.h b/src/or/config.h index fd84d9b606..0495186514 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -72,7 +72,7 @@ int get_first_advertised_port_by_type_af(int listener_type, #define get_primary_dir_port() \ (get_first_advertised_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET)) -char *get_first_listener_addrport_for_pt(int listener_type); +char *get_first_listener_addrport_string(int listener_type); int options_need_geoip_info(const or_options_t *options, const char **reason_out); diff --git a/src/or/router.c b/src/or/router.c index 67d26e13e0..3b97d28d0f 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1218,6 +1218,8 @@ consider_publishable_server(int force) /** Return the port of the first active listener of type * listener_type. */ +/** 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) { diff --git a/src/or/transports.c b/src/or/transports.c index 1f2149381e..897645021a 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -992,7 +992,7 @@ create_managed_proxy_environment(const managed_proxy_t *mp) if (mp->is_server) { { - char *orport_tmp = get_first_listener_addrport_for_pt(CONN_TYPE_OR_LISTENER); + char *orport_tmp = get_first_listener_addrport_string(CONN_TYPE_OR_LISTENER); smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp); tor_free(orport_tmp); }