From: Nick Mathewson Date: Wed, 11 Feb 2009 17:24:11 +0000 (+0000) Subject: New bind-to option to allow DNS clients to bind to arbitrary ports for their outgoing... X-Git-Tag: release-2.0.1-alpha~67 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77c80b8dcf26b2cef66bce03cb25835a9a939306;p=libevent New bind-to option to allow DNS clients to bind to arbitrary ports for their outgoing addresses. svn:r1119 --- diff --git a/ChangeLog b/ChangeLog index ecd3bcd0..3192bbff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -142,6 +142,7 @@ Changes in current version: o Change the semantics of timeouts in conjunction with EV_PERSIST; timeouts in that case will now repeat until deleted. o sendfile, mmap and memory reference support for evbuffers. o New evutil_make_listen_socket_reuseable() to abstract SO_REUSEADDR. + o New bind-to option to allow DNS clients to bind to an arbitrary port for outgoing requests. Changes in 1.4.0: o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. diff --git a/evdns.c b/evdns.c index 166a0caf..c868fc01 100644 --- a/evdns.c +++ b/evdns.c @@ -318,6 +318,11 @@ struct evdns_base { /* true iff we will use the 0x20 hack to prevent poisoning attacks. */ int global_randomize_case; + /** Port to bind to for outgoing DNS packets. */ + struct sockaddr_storage global_outgoing_address; + /** Socklen_t for global_outgoing_address. 0 if it isn't set. */ + socklen_t global_outgoing_addrlen; + struct search_state *global_search_state; }; @@ -2231,6 +2236,17 @@ _evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *addre ns->socket = socket(PF_INET, SOCK_DGRAM, 0); if (ns->socket < 0) { err = 1; goto out1; } evutil_make_socket_nonblocking(ns->socket); + + if (base->global_outgoing_addrlen) { + if (bind(ns->socket, + (struct sockaddr*)&base->global_outgoing_address, + base->global_outgoing_addrlen) < 0) { + log(EVDNS_LOG_WARN,"Couldn't bind to outgoing address"); + err = 2; + goto out2; + } + } + if (connect(ns->socket, address, addrlen) != 0) { err = 2; goto out2; @@ -2955,6 +2971,15 @@ evdns_base_set_option(struct evdns_base *base, int randcase = strtoint(val); if (!(flags & DNS_OPTION_MISC)) return 0; base->global_randomize_case = randcase; + } else if (!strncmp(option, "bind-to:", 8)) { + /* XXX This only applies to successive nameservers, not + * to already-configured ones. We might want to fix that. */ + int len = sizeof(base->global_outgoing_address); + if (!(flags & DNS_OPTION_NAMESERVERS)) return 0; + if (evutil_parse_sockaddr_port(val, + (struct sockaddr*)&base->global_outgoing_address, &len)) + return -1; + base->global_outgoing_addrlen = len; } return 0; } diff --git a/include/event2/dns.h b/include/event2/dns.h index b9b47e82..7920c3e9 100644 --- a/include/event2/dns.h +++ b/include/event2/dns.h @@ -395,7 +395,10 @@ void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req); The currently available configuration options are: - ndots, timeout, max-timeouts, max-inflight, attempts, randomize-case. + ndots, timeout, max-timeouts, max-inflight, attempts, randomize-case, + bind-to. + + The option name needs to end with a colon. @param base the evdns_base to which to apply this operation @param option the name of the configuration option to be modified