From 462f64b6b993d46f5b61c7e2333cc526d15ba884 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 6 Jan 2009 20:50:55 +0000 Subject: [PATCH] Make outgoing DNS requests respect OutboundBindAddress. Fixes the bug part of bug 789. svn:r17983 --- ChangeLog | 4 +++- src/or/dns.c | 19 +++++++++++++++++++ src/or/dnsserv.c | 2 +- src/or/eventdns.c | 26 ++++++++++++++++++++++++++ src/or/eventdns.h | 1 + 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7681dd8d6..f04b6cb0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ Changes in version 0.2.1.11-alpha - 2009-01-?? - + o Minor bugfixes: + - Make outbound DNS packets respect the OutboundBindAddress setting. + Fixes the bug part of bug 798. Changes in version 0.2.1.10-alpha - 2009-01-06 o Major bugfixes: diff --git a/src/or/dns.c b/src/or/dns.c index 3266cf99d..f8191679b 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -1102,6 +1102,25 @@ configure_nameservers(int force) conf_fname = "/etc/resolv.conf"; #endif + if (options->OutboundBindAddress) { + tor_addr_t addr; + if (tor_addr_from_str(&addr, options->OutboundBindAddress) < 0) { + log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.", + options->OutboundBindAddress); + } else { + int socklen; + struct sockaddr_storage ss; + socklen = tor_addr_to_sockaddr(&addr, 0, + (struct sockaddr *)&ss, sizeof(ss)); + if (socklen < 0) { + log_warn(LD_BUG, "Couldn't convert outboung bind address to sockaddr." + " Ignoring."); + } else { + evdns_set_default_outgoing_bind_address((struct sockaddr *)&ss,socklen); + } + } + } + evdns_set_log_fn(evdns_log_cb); if (conf_fname) { if (stat(conf_fname, &st)) { diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index 11002e9d7..36d072110 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -294,7 +294,7 @@ void dnsserv_configure_listener(connection_t *conn) { tor_assert(conn); - tor_assert(conn->s); + tor_assert(conn->s >= 0); tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); conn->dns_server_port = evdns_add_server_port(conn->s, 0, diff --git a/src/or/eventdns.c b/src/or/eventdns.c index 60f08265c..6e4e5e25b 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -2203,6 +2203,23 @@ evdns_clear_nameservers_and_suspend(void) return 0; } +static struct sockaddr_storage global_bind_address; +static socklen_t global_bind_addrlen = 0; +static int global_bind_addr_is_set = 0; +void +evdns_set_default_outgoing_bind_address(const struct sockaddr *addr, + socklen_t addrlen) +{ + memset(&global_bind_address, 0, sizeof(global_bind_address)); + if (addr) { + assert(addrlen <= sizeof(global_bind_address)); + memcpy(&global_bind_address, addr, addrlen); + global_bind_addrlen = addrlen; + global_bind_addr_is_set = 1; + } else { + global_bind_addr_is_set = 0; + } +} /* exported function */ int @@ -2251,6 +2268,15 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, fcntl(ns->socket, F_SETFL, O_NONBLOCK); #endif + if (global_bind_addr_is_set) { + if (bind(ns->socket, (struct sockaddr *)&global_bind_address, + global_bind_addrlen) < 0) { + log(EVDNS_LOG_DEBUG, "Couldn't bind to outgoing address."); + err = 2; + goto out2; + } + } + if (connect(ns->socket, address, addrlen) != 0) { log(EVDNS_LOG_DEBUG, "Couldn't open socket to nameserver."); err = 2; diff --git a/src/or/eventdns.h b/src/or/eventdns.h index 8d9a0b8fb..d3d359d2f 100644 --- a/src/or/eventdns.h +++ b/src/or/eventdns.h @@ -264,6 +264,7 @@ int evdns_clear_nameservers_and_suspend(void); int evdns_resume(void); int evdns_nameserver_ip_add(const char *ip_as_string); int evdns_nameserver_sockaddr_add(const struct sockaddr *sa, socklen_t len); +void evdns_set_default_outgoing_bind_address(const struct sockaddr *addr, socklen_t addrlen); int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr); int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr); struct in_addr;