From eaa4ead2bd03bccaf97b84ada39867067b59a95a Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 13 Nov 2013 10:57:50 -0800 Subject: [PATCH] [v9_9] allow setting local addr in dns_client 3672. [func] Local address can now be specified when using dns_client API. [RT #34811] (cherry picked from commit 0618287859d99c2fc69790df28500fb37324d43d) --- CHANGES | 3 ++ bin/tests/system/resolver/ns1/named.conf | 1 + bin/tests/system/resolver/tests.sh | 16 +++++++ lib/dns/client.c | 53 ++++++++++++++++++------ lib/dns/include/dns/client.h | 13 ++++++ 5 files changed, 73 insertions(+), 13 deletions(-) mode change 100644 => 100755 bin/tests/system/resolver/tests.sh diff --git a/CHANGES b/CHANGES index ccf597fa74..ff2547fed6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3672. [func] Local address can now be specified when using + dns_client API. [RT #34811] + 3671. [bug] Don't allow dnssec-importkey overwrite a existing non-imported private key. diff --git a/bin/tests/system/resolver/ns1/named.conf b/bin/tests/system/resolver/ns1/named.conf index 65068655ea..bcbd63ee8c 100644 --- a/bin/tests/system/resolver/ns1/named.conf +++ b/bin/tests/system/resolver/ns1/named.conf @@ -34,6 +34,7 @@ options { deny-answer-aliases { "example.org"; } except-from { "goodcname.example.net"; "gooddname.example.net"; }; + allow-query {!10.53.0.8; any; }; }; zone "." { diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh old mode 100644 new mode 100755 index 9323f255ee..052b96401b --- a/bin/tests/system/resolver/tests.sh +++ b/bin/tests/system/resolver/tests.sh @@ -39,6 +39,22 @@ echo "I:checking non-cachable NXDOMAIN response handling using dns_client" status=`expr $status + $ret` fi +if [ -x ${RESOLVE} ] ; then +echo "I:checking that local bound address can be set (Can't query from a denied address)" + ret=0 + ${RESOLVE} -b 10.53.0.8 -p 5300 -t a -s 10.53.0.1 www.example.org 2> resolve.out || ret=1 + grep "resolution failed: failure" resolve.out > /dev/null || ret=1 + if [ $ret != 0 ]; then echo "I:failed"; fi + status=`expr $status + $ret` + +echo "I:checking that local bound address can be set (Can query from an allowed address)" + ret=0 + ${RESOLVE} -b 10.53.0.1 -p 5300 -t a -s 10.53.0.1 www.example.org > resolve.out || ret=1 + grep "www.example.org..*.192.0.2.1" resolve.out > /dev/null || ret=1 + if [ $ret != 0 ]; then echo "I:failed"; fi + status=`expr $status + $ret` +fi + echo "I:checking non-cachable NODATA response handling" ret=0 $DIG +tcp nodata.example.net @10.53.0.1 a -p 5300 > dig.out || ret=1 diff --git a/lib/dns/client.c b/lib/dns/client.c index e9e8bde28c..cee4fb268d 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -249,13 +249,14 @@ static isc_result_t send_update(updatectx_t *uctx); static isc_result_t getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, - isc_boolean_t is_shared, dns_dispatch_t **dispp) + isc_boolean_t is_shared, dns_dispatch_t **dispp, + isc_sockaddr_t *localaddr) { unsigned int attrs, attrmask; - isc_sockaddr_t sa; dns_dispatch_t *disp; unsigned buffersize, maxbuffers, maxrequests, buckets, increment; isc_result_t result; + isc_sockaddr_t anyaddr; attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; @@ -275,7 +276,10 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, attrmask |= DNS_DISPATCHATTR_IPV4; attrmask |= DNS_DISPATCHATTR_IPV6; - isc_sockaddr_anyofpf(&sa, family); + if (localaddr == NULL) { + localaddr = &anyaddr; + isc_sockaddr_anyofpf(localaddr, family); + } buffersize = 4096; maxbuffers = is_shared ? 1000 : 8; @@ -285,7 +289,7 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, disp = NULL; result = dns_dispatch_getudp(dispatchmgr, socketmgr, - taskmgr, &sa, + taskmgr, localaddr, buffersize, maxbuffers, maxrequests, buckets, increment, attrs, attrmask, &disp); @@ -421,6 +425,19 @@ isc_result_t dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, unsigned int options, dns_client_t **clientp) +{ + isc_result_t result; + result = dns_client_createx2(mctx, actx, taskmgr, socketmgr, timermgr, + options, clientp, NULL, NULL); + return (result); +} + +isc_result_t +dns_client_createx2(isc_mem_t *mctx, isc_appctx_t *actx, + isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, + isc_timermgr_t *timermgr, unsigned int options, + dns_client_t **clientp, isc_sockaddr_t *localaddr4, + isc_sockaddr_t *localaddr6) { dns_client_t *client; isc_result_t result; @@ -460,17 +477,27 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, goto cleanup; client->dispatchmgr = dispatchmgr; - /* TODO: whether to use dispatch v4 or v6 should be configurable */ + /* + * If only one address family is specified, use it. + * If neither family is specified, or if both are, use both. + */ client->dispatchv4 = NULL; + if (localaddr4 != NULL || localaddr6 == NULL) { + result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, + taskmgr, ISC_TRUE, + &dispatchv4, localaddr4); + if (result == ISC_R_SUCCESS) + client->dispatchv4 = dispatchv4; + } + client->dispatchv6 = NULL; - result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, - taskmgr, ISC_TRUE, &dispatchv4); - if (result == ISC_R_SUCCESS) - client->dispatchv4 = dispatchv4; - result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, - taskmgr, ISC_TRUE, &dispatchv6); - if (result == ISC_R_SUCCESS) - client->dispatchv6 = dispatchv6; + if (localaddr6 != NULL || localaddr4 == NULL) { + result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, + taskmgr, ISC_TRUE, + &dispatchv6, localaddr6); + if (result == ISC_R_SUCCESS) + client->dispatchv6 = dispatchv6; + } /* We need at least one of the dispatchers */ if (dispatchv4 == NULL && dispatchv6 == NULL) { diff --git a/lib/dns/include/dns/client.h b/lib/dns/include/dns/client.h index d21dff788d..d8fdccc188 100644 --- a/lib/dns/include/dns/client.h +++ b/lib/dns/include/dns/client.h @@ -149,6 +149,13 @@ isc_result_t dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, unsigned int options, dns_client_t **clientp); + +isc_result_t +dns_client_createx2(isc_mem_t *mctx, isc_appctx_t *actx, + isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, + isc_timermgr_t *timermgr, unsigned int options, + dns_client_t **clientp, + isc_sockaddr_t *localaddr4, isc_sockaddr_t *localaddr6); /*%< * Create a DNS client. These functions create a new client object with * minimal internal resources such as the default 'view' for the IN class and @@ -161,6 +168,12 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, * dns_client_create() is expected to be used by an application that only needs * simple synchronous services or by a thread-based application. * + * dns_client_createx2 takes two additional parameters, 'localaddr4' and + * 'localaddr6', to specify the local address to use for each family. If + * both are set to NULL, then wildcard addresses will be used for both + * families. If only one is NULL, then the other address will be used + * as the local address, and the other protocol family will not be used. + * * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options', * dns_client_create(x) will create a cache database with the view. *