+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.
deny-answer-aliases { "example.org"; }
except-from { "goodcname.example.net";
"gooddname.example.net"; };
+ allow-query {!10.53.0.8; any; };
};
zone "." {
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
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;
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;
disp = NULL;
result = dns_dispatch_getudp(dispatchmgr, socketmgr,
- taskmgr, &sa,
+ taskmgr, localaddr,
buffersize, maxbuffers, maxrequests,
buckets, increment,
attrs, attrmask, &disp);
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;
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) {
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
* 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.
*
#include <isc/mem.h>
#include <isc/sockaddr.h>
#include <isc/util.h>
+#include <isc/app.h>
+#include <isc/task.h>
+#include <isc/socket.h>
+#include <isc/timer.h>
#include <irs/resconf.h>
#include <irs/netdb.h>
fprintf(stderr, "resolve [-t RRtype] "
"[[-a algorithm] [-e] -k keyname -K keystring] "
"[-S domain:serveraddr_for_domain ] [-s server_address]"
- "hostname\n");
+ "[-b address[#port]] hostname\n");
exit(1);
}
isc_boolean_t is_sep = ISC_FALSE;
const char *port = "53";
isc_mem_t *mctx = NULL;
-
- while ((ch = getopt(argc, argv, "a:es:t:k:K:p:S:")) != -1) {
+ isc_appctx_t *actx = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+ struct in_addr in4;
+ struct in6_addr in6;
+ isc_sockaddr_t a4, a6;
+ isc_sockaddr_t *addr4 = NULL, *addr6 = NULL;
+
+ while ((ch = getopt(argc, argv, "a:b:es:t:k:K:p:S:")) != -1) {
switch (ch) {
case 't':
tr.base = optarg;
case 'a':
algname = optarg;
break;
+ case 'b':
+ if (inet_pton(AF_INET, optarg, &in4) == 1) {
+ if (addr4 != NULL) {
+ fprintf(stderr, "only one local "
+ "address per family "
+ "can be specified\n");
+ exit(1);
+ }
+ isc_sockaddr_fromin(&a4, &in4, 0);
+ addr4 = &a4;
+ } else if (inet_pton(AF_INET6, optarg, &in6) == 1) {
+ if (addr6 != NULL) {
+ fprintf(stderr, "only one local "
+ "address per family "
+ "can be specified\n");
+ exit(1);
+ }
+ isc_sockaddr_fromin6(&a6, &in6, 0);
+ addr6 = &a6;
+ } else {
+ fprintf(stderr, "invalid address %s\n", optarg);
+ exit(1);
+ }
case 'e':
is_sep = ISC_TRUE;
break;
exit(1);
}
+ result = isc_appctx_create(mctx, &actx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_app_ctxstart(actx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_socketmgr_createinctx(mctx, actx, &socketmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_timermgr_createinctx(mctx, actx, &timermgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
clientopt = 0;
- result = dns_client_create(&client, clientopt);
+ result = dns_client_createx2(mctx, actx, taskmgr, socketmgr, timermgr,
+ clientopt, &client, addr4, addr6);
if (result != ISC_R_SUCCESS) {
- fprintf(stderr, "dns_client_create failed: %d\n", result);
+ fprintf(stderr, "dns_client_create failed: %d, %s\n", result,
+ isc_result_totext(result));
exit(1);
}
result = dns_client_setservers(client, dns_rdataclass_in,
NULL, nameservers);
if (result != ISC_R_SUCCESS) {
+ irs_resconf_destroy(&resconf);
fprintf(stderr, "dns_client_setservers failed: %d\n",
result);
exit(1);
}
+ irs_resconf_destroy(&resconf);
} else {
addserver(client, server, port, NULL);
}
fprintf(stderr, "failed to convert qname: %d\n", result);
/* Perform resolution */
- resopt = 0;
+ resopt = DNS_CLIENTRESOPT_ALLOWRUN;
if (keynamestr == NULL)
resopt |= DNS_CLIENTRESOPT_NODNSSEC;
ISC_LIST_INIT(namelist);
dns_client_freeresanswer(client, &namelist);
/* Cleanup */
+cleanup:
dns_client_destroy(&client);
+
+ if (taskmgr != NULL)
+ isc_taskmgr_destroy(&taskmgr);
+ if (timermgr != NULL)
+ isc_timermgr_destroy(&timermgr);
+ if (socketmgr != NULL)
+ isc_socketmgr_destroy(&socketmgr);
+ if (actx != NULL)
+ isc_appctx_destroy(&actx);
+ isc_mem_detach(&mctx);
+
if (keynamestr != NULL)
isc_mem_destroy(&keymctx);
dns_lib_shutdown();