2009-09-01 00:22:28 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2009-09-01 00:22:28 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2020-09-14 16:20:40 -07:00
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
2009-09-01 00:22:28 +00:00
|
|
|
*/
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2010-05-19 07:13:15 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
#include <isc/app.h>
|
2014-02-16 13:03:17 -08:00
|
|
|
#include <isc/buffer.h>
|
2019-12-20 11:37:11 -08:00
|
|
|
#include <isc/md.h>
|
2009-09-01 00:22:28 +00:00
|
|
|
#include <isc/mem.h>
|
|
|
|
#include <isc/mutex.h>
|
2019-03-08 13:13:32 +01:00
|
|
|
#include <isc/portset.h>
|
2019-08-06 17:35:20 +02:00
|
|
|
#include <isc/refcount.h>
|
2015-08-17 18:26:44 -07:00
|
|
|
#include <isc/safe.h>
|
2009-09-01 00:22:28 +00:00
|
|
|
#include <isc/sockaddr.h>
|
|
|
|
#include <isc/socket.h>
|
|
|
|
#include <isc/task.h>
|
|
|
|
#include <isc/timer.h>
|
|
|
|
#include <isc/util.h>
|
|
|
|
|
|
|
|
#include <dns/adb.h>
|
|
|
|
#include <dns/client.h>
|
|
|
|
#include <dns/db.h>
|
|
|
|
#include <dns/dispatch.h>
|
|
|
|
#include <dns/events.h>
|
|
|
|
#include <dns/forward.h>
|
|
|
|
#include <dns/keytable.h>
|
|
|
|
#include <dns/message.h>
|
|
|
|
#include <dns/name.h>
|
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdatalist.h>
|
|
|
|
#include <dns/rdataset.h>
|
|
|
|
#include <dns/rdatasetiter.h>
|
|
|
|
#include <dns/rdatastruct.h>
|
2020-02-12 13:59:18 +01:00
|
|
|
#include <dns/rdatatype.h>
|
2009-09-01 00:22:28 +00:00
|
|
|
#include <dns/request.h>
|
|
|
|
#include <dns/resolver.h>
|
|
|
|
#include <dns/result.h>
|
|
|
|
#include <dns/tsec.h>
|
|
|
|
#include <dns/tsig.h>
|
|
|
|
#include <dns/view.h>
|
|
|
|
|
|
|
|
#include <dst/dst.h>
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define DNS_CLIENT_MAGIC ISC_MAGIC('D', 'N', 'S', 'c')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define DNS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, DNS_CLIENT_MAGIC)
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define RCTX_MAGIC ISC_MAGIC('R', 'c', 't', 'x')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define RCTX_VALID(c) ISC_MAGIC_VALID(c, RCTX_MAGIC)
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC)
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
#define MAX_RESTARTS 16
|
|
|
|
|
2014-02-18 22:36:14 -08:00
|
|
|
#ifdef TUNE_LARGE
|
|
|
|
#define RESOLVER_NTASKS 523
|
2020-02-13 21:48:23 +01:00
|
|
|
#else /* ifdef TUNE_LARGE */
|
2014-02-18 22:36:14 -08:00
|
|
|
#define RESOLVER_NTASKS 31
|
|
|
|
#endif /* TUNE_LARGE */
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#define CHECK(r) \
|
|
|
|
do { \
|
|
|
|
result = (r); \
|
2019-09-18 19:45:20 -07:00
|
|
|
if (result != ISC_R_SUCCESS) \
|
2020-02-12 13:59:18 +01:00
|
|
|
goto cleanup; \
|
2019-09-18 19:45:20 -07:00
|
|
|
} while (0)
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
/*%
|
|
|
|
* DNS client object
|
|
|
|
*/
|
|
|
|
struct dns_client {
|
|
|
|
/* Unlocked */
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
|
|
|
unsigned int attributes;
|
|
|
|
isc_mutex_t lock;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_appctx_t *actx;
|
|
|
|
isc_taskmgr_t *taskmgr;
|
|
|
|
isc_task_t *task;
|
|
|
|
isc_socketmgr_t *socketmgr;
|
|
|
|
isc_timermgr_t *timermgr;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_dispatchmgr_t *dispatchmgr;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatch_t *dispatchv4;
|
|
|
|
dns_dispatch_t *dispatchv6;
|
2020-02-12 13:59:18 +01:00
|
|
|
|
|
|
|
unsigned int find_timeout;
|
|
|
|
unsigned int find_udpretries;
|
|
|
|
|
|
|
|
isc_refcount_t references;
|
2019-08-06 17:35:20 +02:00
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
/* Locked */
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_viewlist_t viewlist;
|
|
|
|
ISC_LIST(struct resctx) resctxs;
|
2009-09-01 00:22:28 +00:00
|
|
|
};
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define DEF_FIND_TIMEOUT 5
|
2020-02-12 13:59:18 +01:00
|
|
|
#define DEF_FIND_UDPRETRIES 3
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
/*%
|
|
|
|
* Internal state for a single name resolution procedure
|
|
|
|
*/
|
|
|
|
typedef struct resctx {
|
|
|
|
/* Unlocked */
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
|
|
|
isc_mutex_t lock;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_client_t *client;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool want_dnssec;
|
|
|
|
bool want_validation;
|
|
|
|
bool want_cdflag;
|
|
|
|
bool want_tcp;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
/* Locked */
|
2020-02-12 13:59:18 +01:00
|
|
|
ISC_LINK(struct resctx) link;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_task_t *task;
|
|
|
|
dns_view_t *view;
|
|
|
|
unsigned int restarts;
|
|
|
|
dns_fixedname_t name;
|
|
|
|
dns_rdatatype_t type;
|
|
|
|
dns_fetch_t *fetch;
|
|
|
|
dns_namelist_t namelist;
|
|
|
|
isc_result_t result;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_clientresevent_t *event;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool canceled;
|
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
dns_rdataset_t *sigrdataset;
|
2009-09-01 00:22:28 +00:00
|
|
|
} resctx_t;
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Argument of an internal event for synchronous name resolution.
|
|
|
|
*/
|
|
|
|
typedef struct resarg {
|
|
|
|
/* Unlocked */
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_appctx_t *actx;
|
|
|
|
dns_client_t *client;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mutex_t lock;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
/* Locked */
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
isc_result_t vresult;
|
|
|
|
dns_namelist_t *namelist;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_clientrestrans_t *trans;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool canceled;
|
2009-09-01 00:22:28 +00:00
|
|
|
} resarg_t;
|
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
client_resfind(resctx_t *rctx, dns_fetchevent_t *event);
|
2021-08-12 13:51:47 -07:00
|
|
|
static void
|
|
|
|
cancelresolve(dns_clientrestrans_t *trans);
|
|
|
|
static void
|
|
|
|
destroyrestrans(dns_clientrestrans_t **transp);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2019-03-08 13:13:32 +01:00
|
|
|
/*
|
|
|
|
* Try honoring the operating system's preferred ephemeral port range.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
setsourceports(isc_mem_t *mctx, dns_dispatchmgr_t *manager) {
|
2019-03-08 13:13:32 +01:00
|
|
|
isc_portset_t *v4portset = NULL, *v6portset = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t udpport_low, udpport_high;
|
|
|
|
isc_result_t result;
|
2019-03-08 13:13:32 +01:00
|
|
|
|
|
|
|
result = isc_portset_create(mctx, &v4portset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
isc_portset_addrange(v4portset, udpport_low, udpport_high);
|
|
|
|
|
|
|
|
result = isc_portset_create(mctx, &v6portset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
isc_portset_addrange(v6portset, udpport_low, udpport_high);
|
|
|
|
|
|
|
|
result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup:
|
2019-03-08 13:13:32 +01:00
|
|
|
if (v4portset != NULL) {
|
|
|
|
isc_portset_destroy(mctx, &v4portset);
|
|
|
|
}
|
|
|
|
if (v6portset != NULL) {
|
|
|
|
isc_portset_destroy(mctx, &v6portset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
static isc_result_t
|
|
|
|
getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
|
|
|
|
isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
|
Dispatch API simplification
- Many dispatch attributes can be set implicitly instead of being passed
in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from
whether we're calling dns_dispatch_createtcp() or _createudp(). we
can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or
the socket that were passed in.
- We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket'
parameter has been removed from dns_dispatch_createudp(), along with
the code implementing it. also removed isc_socket_dup() since it no
longer has any callers.
- The 'buffersize' parameter was ignored and has now been removed;
buffersize is now fixed at 4096.
- Maxbuffers and maxrequests don't need to be passed in on every call to
dns_dispatch_createtcp() and _createudp().
In all current uses, the value for mgr->maxbuffers will either be
raised once from its default of 20000 to 32768, or else left
alone. (passing in a value lower than 20000 does not lower it.) there
isn't enough difference between these values for there to be any need
to configure this.
The value for disp->maxrequests controls both the quota of concurrent
requests for a dispatch and also the size of the dispatch socket
memory pool. it's not clear that this quota is necessary at all. the
memory pool size currently starts at 32768, but is sometimes lowered
to 4096, which is definitely unnecessary.
This commit sets both values permanently to 32768.
- Previously TCP dispatches allocated their own separate QID table,
which didn't incorporate a port table. this commit removes
per-dispatch QID tables and shares the same table between all
dispatches. since dispatches are created for each TCP socket, this may
speed up the dispatch allocation process. there may be a slight
increase in lock contention since all dispatches are sharing a single
QID table, but since TCP sockets are used less often than UDP
sockets (which were already sharing a QID table), it should not be a
substantial change.
- The dispatch port table was being used to determine whether a port was
already in use; if so, then a UDP socket would be bound with
REUSEADDR. this commit removes the port table, and always binds UDP
sockets that way.
2020-12-17 00:43:00 -08:00
|
|
|
dns_dispatch_t **dispp, const isc_sockaddr_t *localaddr) {
|
2020-12-16 01:32:06 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
isc_sockaddr_t anyaddr;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2013-11-13 10:52:22 -08:00
|
|
|
if (localaddr == NULL) {
|
2016-12-30 15:45:08 +11:00
|
|
|
isc_sockaddr_anyofpf(&anyaddr, family);
|
2013-11-13 10:52:22 -08:00
|
|
|
localaddr = &anyaddr;
|
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2020-12-16 01:32:06 -08:00
|
|
|
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
Dispatch API simplification
- Many dispatch attributes can be set implicitly instead of being passed
in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from
whether we're calling dns_dispatch_createtcp() or _createudp(). we
can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or
the socket that were passed in.
- We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket'
parameter has been removed from dns_dispatch_createudp(), along with
the code implementing it. also removed isc_socket_dup() since it no
longer has any callers.
- The 'buffersize' parameter was ignored and has now been removed;
buffersize is now fixed at 4096.
- Maxbuffers and maxrequests don't need to be passed in on every call to
dns_dispatch_createtcp() and _createudp().
In all current uses, the value for mgr->maxbuffers will either be
raised once from its default of 20000 to 32768, or else left
alone. (passing in a value lower than 20000 does not lower it.) there
isn't enough difference between these values for there to be any need
to configure this.
The value for disp->maxrequests controls both the quota of concurrent
requests for a dispatch and also the size of the dispatch socket
memory pool. it's not clear that this quota is necessary at all. the
memory pool size currently starts at 32768, but is sometimes lowered
to 4096, which is definitely unnecessary.
This commit sets both values permanently to 32768.
- Previously TCP dispatches allocated their own separate QID table,
which didn't incorporate a port table. this commit removes
per-dispatch QID tables and shares the same table between all
dispatches. since dispatches are created for each TCP socket, this may
speed up the dispatch allocation process. there may be a slight
increase in lock contention since all dispatches are sharing a single
QID table, but since TCP sockets are used less often than UDP
sockets (which were already sharing a QID table), it should not be a
substantial change.
- The dispatch port table was being used to determine whether a port was
already in use; if so, then a UDP socket would be bound with
REUSEADDR. this commit removes the port table, and always binds UDP
sockets that way.
2020-12-17 00:43:00 -08:00
|
|
|
localaddr, 0, &disp);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2009-09-01 00:22:28 +00:00
|
|
|
*dispp = disp;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2020-04-22 13:26:19 +02:00
|
|
|
createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_taskmgr_t *taskmgr,
|
|
|
|
unsigned int ntasks, isc_socketmgr_t *socketmgr,
|
|
|
|
isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr,
|
|
|
|
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
|
|
|
|
dns_view_t **viewp) {
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_view_t *view = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
result = dns_view_create(mctx, rdclass, DNS_CLIENTVIEW_NAME, &view);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-09-03 21:45:46 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-03 21:45:46 +00:00
|
|
|
|
2009-10-27 22:46:13 +00:00
|
|
|
/* Initialize view security roots */
|
|
|
|
result = dns_view_initsecroots(view, mctx);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_view_detach(&view);
|
|
|
|
return (result);
|
2009-09-03 21:45:46 +00:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_view_createresolver(view, taskmgr, ntasks, 1, socketmgr,
|
|
|
|
timermgr, 0, dispatchmgr, dispatchv4,
|
|
|
|
dispatchv6);
|
2009-09-01 00:22:28 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_view_detach(&view);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2020-04-22 13:26:19 +02:00
|
|
|
result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache,
|
2009-09-01 00:22:28 +00:00
|
|
|
rdclass, 0, NULL, &view->cachedb);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_view_detach(&view);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
*viewp = view;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2021-03-22 18:16:28 -07:00
|
|
|
dns_client_create(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,
|
|
|
|
const isc_sockaddr_t *localaddr4,
|
|
|
|
const isc_sockaddr_t *localaddr6) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2021-03-22 18:16:28 -07:00
|
|
|
dns_client_t *client = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_dispatchmgr_t *dispatchmgr = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatch_t *dispatchv4 = NULL;
|
|
|
|
dns_dispatch_t *dispatchv6 = NULL;
|
|
|
|
dns_view_t *view = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(taskmgr != NULL);
|
|
|
|
REQUIRE(timermgr != NULL);
|
|
|
|
REQUIRE(socketmgr != NULL);
|
|
|
|
REQUIRE(clientp != NULL && *clientp == NULL);
|
|
|
|
|
2020-04-22 13:26:19 +02:00
|
|
|
UNUSED(options);
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
client = isc_mem_get(mctx, sizeof(*client));
|
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&client->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
client->actx = actx;
|
|
|
|
client->taskmgr = taskmgr;
|
|
|
|
client->socketmgr = socketmgr;
|
|
|
|
client->timermgr = timermgr;
|
|
|
|
|
|
|
|
client->task = NULL;
|
2018-11-21 09:50:50 +00:00
|
|
|
result = isc_task_create(client->taskmgr, 0, &client->task);
|
2019-08-06 17:35:20 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup_lock;
|
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2018-04-22 14:56:28 +02:00
|
|
|
result = dns_dispatchmgr_create(mctx, &dispatchmgr);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2019-08-06 17:35:20 +02:00
|
|
|
goto cleanup_task;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
client->dispatchmgr = dispatchmgr;
|
2019-03-08 13:13:32 +01:00
|
|
|
(void)setsourceports(mctx, dispatchmgr);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2013-11-13 10:52:22 -08:00
|
|
|
/*
|
|
|
|
* If only one address family is specified, use it.
|
|
|
|
* If neither family is specified, or if both are, use both.
|
|
|
|
*/
|
2010-04-13 19:06:48 +00:00
|
|
|
client->dispatchv4 = NULL;
|
2013-11-13 10:52:22 -08:00
|
|
|
if (localaddr4 != NULL || localaddr6 == NULL) {
|
|
|
|
result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
|
Dispatch API simplification
- Many dispatch attributes can be set implicitly instead of being passed
in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from
whether we're calling dns_dispatch_createtcp() or _createudp(). we
can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or
the socket that were passed in.
- We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket'
parameter has been removed from dns_dispatch_createudp(), along with
the code implementing it. also removed isc_socket_dup() since it no
longer has any callers.
- The 'buffersize' parameter was ignored and has now been removed;
buffersize is now fixed at 4096.
- Maxbuffers and maxrequests don't need to be passed in on every call to
dns_dispatch_createtcp() and _createudp().
In all current uses, the value for mgr->maxbuffers will either be
raised once from its default of 20000 to 32768, or else left
alone. (passing in a value lower than 20000 does not lower it.) there
isn't enough difference between these values for there to be any need
to configure this.
The value for disp->maxrequests controls both the quota of concurrent
requests for a dispatch and also the size of the dispatch socket
memory pool. it's not clear that this quota is necessary at all. the
memory pool size currently starts at 32768, but is sometimes lowered
to 4096, which is definitely unnecessary.
This commit sets both values permanently to 32768.
- Previously TCP dispatches allocated their own separate QID table,
which didn't incorporate a port table. this commit removes
per-dispatch QID tables and shares the same table between all
dispatches. since dispatches are created for each TCP socket, this may
speed up the dispatch allocation process. there may be a slight
increase in lock contention since all dispatches are sharing a single
QID table, but since TCP sockets are used less often than UDP
sockets (which were already sharing a QID table), it should not be a
substantial change.
- The dispatch port table was being used to determine whether a port was
already in use; if so, then a UDP socket would be bound with
REUSEADDR. this commit removes the port table, and always binds UDP
sockets that way.
2020-12-17 00:43:00 -08:00
|
|
|
taskmgr, &dispatchv4, localaddr4);
|
2019-08-06 17:35:20 +02:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2013-11-13 10:52:22 -08:00
|
|
|
client->dispatchv4 = dispatchv4;
|
2019-08-06 17:35:20 +02:00
|
|
|
}
|
2013-11-13 10:52:22 -08:00
|
|
|
}
|
|
|
|
|
2010-04-13 19:06:48 +00:00
|
|
|
client->dispatchv6 = NULL;
|
2013-11-13 10:52:22 -08:00
|
|
|
if (localaddr6 != NULL || localaddr4 == NULL) {
|
|
|
|
result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
|
Dispatch API simplification
- Many dispatch attributes can be set implicitly instead of being passed
in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from
whether we're calling dns_dispatch_createtcp() or _createudp(). we
can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or
the socket that were passed in.
- We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket'
parameter has been removed from dns_dispatch_createudp(), along with
the code implementing it. also removed isc_socket_dup() since it no
longer has any callers.
- The 'buffersize' parameter was ignored and has now been removed;
buffersize is now fixed at 4096.
- Maxbuffers and maxrequests don't need to be passed in on every call to
dns_dispatch_createtcp() and _createudp().
In all current uses, the value for mgr->maxbuffers will either be
raised once from its default of 20000 to 32768, or else left
alone. (passing in a value lower than 20000 does not lower it.) there
isn't enough difference between these values for there to be any need
to configure this.
The value for disp->maxrequests controls both the quota of concurrent
requests for a dispatch and also the size of the dispatch socket
memory pool. it's not clear that this quota is necessary at all. the
memory pool size currently starts at 32768, but is sometimes lowered
to 4096, which is definitely unnecessary.
This commit sets both values permanently to 32768.
- Previously TCP dispatches allocated their own separate QID table,
which didn't incorporate a port table. this commit removes
per-dispatch QID tables and shares the same table between all
dispatches. since dispatches are created for each TCP socket, this may
speed up the dispatch allocation process. there may be a slight
increase in lock contention since all dispatches are sharing a single
QID table, but since TCP sockets are used less often than UDP
sockets (which were already sharing a QID table), it should not be a
substantial change.
- The dispatch port table was being used to determine whether a port was
already in use; if so, then a UDP socket would be bound with
REUSEADDR. this commit removes the port table, and always binds UDP
sockets that way.
2020-12-17 00:43:00 -08:00
|
|
|
taskmgr, &dispatchv6, localaddr6);
|
2019-08-06 17:35:20 +02:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2013-11-13 10:52:22 -08:00
|
|
|
client->dispatchv6 = dispatchv6;
|
2019-08-06 17:35:20 +02:00
|
|
|
}
|
2013-11-13 10:52:22 -08:00
|
|
|
}
|
2010-04-13 19:06:48 +00:00
|
|
|
|
|
|
|
/* We need at least one of the dispatchers */
|
|
|
|
if (dispatchv4 == NULL && dispatchv6 == NULL) {
|
|
|
|
INSIST(result != ISC_R_SUCCESS);
|
2019-08-06 17:35:20 +02:00
|
|
|
goto cleanup_dispatchmgr;
|
2010-04-13 19:06:48 +00:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2019-08-06 17:35:20 +02:00
|
|
|
isc_refcount_init(&client->references, 1);
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
/* Create the default view for class IN */
|
2020-04-22 13:26:19 +02:00
|
|
|
result = createview(mctx, dns_rdataclass_in, taskmgr, RESOLVER_NTASKS,
|
|
|
|
socketmgr, timermgr, dispatchmgr, dispatchv4,
|
|
|
|
dispatchv6, &view);
|
2019-08-06 17:35:20 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup_references;
|
|
|
|
}
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
ISC_LIST_INIT(client->viewlist);
|
|
|
|
ISC_LIST_APPEND(client->viewlist, view, link);
|
|
|
|
|
|
|
|
dns_view_freeze(view); /* too early? */
|
|
|
|
|
|
|
|
ISC_LIST_INIT(client->resctxs);
|
|
|
|
|
|
|
|
client->mctx = NULL;
|
|
|
|
isc_mem_attach(mctx, &client->mctx);
|
|
|
|
|
|
|
|
client->find_timeout = DEF_FIND_TIMEOUT;
|
|
|
|
client->find_udpretries = DEF_FIND_UDPRETRIES;
|
2013-04-03 17:27:40 +11:00
|
|
|
client->attributes = 0;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
client->magic = DNS_CLIENT_MAGIC;
|
|
|
|
|
|
|
|
*clientp = client;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_references:
|
2019-12-05 13:29:45 +11:00
|
|
|
isc_refcount_decrementz(&client->references);
|
2019-08-06 17:35:20 +02:00
|
|
|
isc_refcount_destroy(&client->references);
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_dispatchmgr:
|
2019-08-06 17:35:20 +02:00
|
|
|
if (dispatchv4 != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_dispatch_detach(&dispatchv4);
|
2019-08-06 17:35:20 +02:00
|
|
|
}
|
|
|
|
if (dispatchv6 != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_dispatch_detach(&dispatchv6);
|
2019-08-06 17:35:20 +02:00
|
|
|
}
|
|
|
|
dns_dispatchmgr_destroy(&dispatchmgr);
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_task:
|
2019-08-06 17:35:20 +02:00
|
|
|
isc_task_detach(&client->task);
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_lock:
|
2019-08-06 17:35:20 +02:00
|
|
|
isc_mutex_destroy(&client->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_mem_put(mctx, client, sizeof(*client));
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
destroyclient(dns_client_t *client) {
|
2021-08-12 13:51:47 -07:00
|
|
|
dns_view_t *view = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2019-08-06 17:35:20 +02:00
|
|
|
isc_refcount_destroy(&client->references);
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
while ((view = ISC_LIST_HEAD(client->viewlist)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(client->viewlist, view, link);
|
|
|
|
dns_view_detach(&view);
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (client->dispatchv4 != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_dispatch_detach(&client->dispatchv4);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (client->dispatchv6 != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_dispatch_detach(&client->dispatchv6);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
dns_dispatchmgr_destroy(&client->dispatchmgr);
|
|
|
|
|
|
|
|
isc_task_detach(&client->task);
|
|
|
|
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&client->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
client->magic = 0;
|
2009-09-02 23:48:03 +00:00
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-08-12 13:51:47 -07:00
|
|
|
dns_client_detach(dns_client_t **clientp) {
|
|
|
|
dns_client_t *client = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(clientp != NULL);
|
2021-08-12 13:51:47 -07:00
|
|
|
REQUIRE(DNS_CLIENT_VALID(*clientp));
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
client = *clientp;
|
2019-08-06 17:35:20 +02:00
|
|
|
*clientp = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2019-08-06 17:35:20 +02:00
|
|
|
if (isc_refcount_decrement(&client->references) == 1) {
|
|
|
|
destroyclient(client);
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
const dns_name_t *name_space, isc_sockaddrlist_t *addrs) {
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_view_t *view = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
|
|
|
REQUIRE(addrs != NULL);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name_space == NULL) {
|
2017-07-21 11:52:24 +10:00
|
|
|
name_space = dns_rootname;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
LOCK(&client->lock);
|
|
|
|
result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
|
|
|
|
rdclass, &view);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
UNLOCK(&client->lock);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
UNLOCK(&client->lock);
|
|
|
|
|
2017-07-21 11:52:24 +10:00
|
|
|
result = dns_fwdtable_add(view->fwdtable, name_space, addrs,
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_fwdpolicy_only);
|
|
|
|
|
|
|
|
dns_view_detach(&view);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
|
2020-02-13 14:44:37 -08:00
|
|
|
const dns_name_t *name_space) {
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_view_t *view = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name_space == NULL) {
|
2017-07-21 11:52:24 +10:00
|
|
|
name_space = dns_rootname;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
LOCK(&client->lock);
|
|
|
|
result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
|
|
|
|
rdclass, &view);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
UNLOCK(&client->lock);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
UNLOCK(&client->lock);
|
|
|
|
|
2017-07-21 11:52:24 +10:00
|
|
|
result = dns_fwdtable_delete(view->fwdtable, name_space);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
dns_view_detach(&view);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
|
|
|
|
|
|
|
|
rdataset = isc_mem_get(mctx, sizeof(*rdataset));
|
|
|
|
|
|
|
|
dns_rdataset_init(rdataset);
|
|
|
|
|
|
|
|
*rdatasetp = rdataset;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
putrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
|
|
|
|
REQUIRE(rdatasetp != NULL);
|
|
|
|
rdataset = *rdatasetp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*rdatasetp = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
REQUIRE(rdataset != NULL);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dns_rdataset_isassociated(rdataset)) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataset_disassociate(rdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
isc_mem_put(mctx, rdataset, sizeof(*rdataset));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
fetch_done(isc_task_t *task, isc_event_t *event) {
|
|
|
|
resctx_t *rctx = event->ev_arg;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_fetchevent_t *fevent;
|
|
|
|
|
|
|
|
REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
|
|
|
|
REQUIRE(RCTX_VALID(rctx));
|
|
|
|
REQUIRE(rctx->task == task);
|
|
|
|
fevent = (dns_fetchevent_t *)event;
|
|
|
|
|
|
|
|
client_resfind(rctx, fevent);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
start_fetch(resctx_t *rctx) {
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
int fopts = 0;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The caller must be holding the rctx's lock.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(rctx->fetch == NULL);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!rctx->want_cdflag) {
|
2014-02-16 13:03:17 -08:00
|
|
|
fopts |= DNS_FETCHOPT_NOCDFLAG;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (!rctx->want_validation) {
|
2014-02-16 13:03:17 -08:00
|
|
|
fopts |= DNS_FETCHOPT_NOVALIDATE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (rctx->want_tcp) {
|
2014-11-21 09:37:04 -08:00
|
|
|
fopts |= DNS_FETCHOPT_TCP;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-02-16 13:03:17 -08:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_resolver_createfetch(
|
|
|
|
rctx->view->resolver, dns_fixedname_name(&rctx->name),
|
|
|
|
rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL,
|
|
|
|
rctx->task, fetch_done, rctx, rctx->rdataset, rctx->sigrdataset,
|
|
|
|
&rctx->fetch);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
view_find(resctx_t *rctx, dns_db_t **dbp, dns_dbnode_t **nodep,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *foundname) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_name_t *name = dns_fixedname_name(&rctx->name);
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdatatype_t type;
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rctx->type == dns_rdatatype_rrsig) {
|
2009-09-01 00:22:28 +00:00
|
|
|
type = dns_rdatatype_any;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2009-09-01 00:22:28 +00:00
|
|
|
type = rctx->type;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_view_find(rctx->view, name, type, 0, 0, false, false, dbp,
|
|
|
|
nodep, foundname, rctx->rdataset,
|
2009-09-01 00:22:28 +00:00
|
|
|
rctx->sigrdataset);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_result_t tresult, result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t vresult = ISC_R_SUCCESS;
|
|
|
|
bool want_restart;
|
|
|
|
bool send_event = false;
|
|
|
|
dns_name_t *name, *prefix;
|
|
|
|
dns_fixedname_t foundname, fixed;
|
|
|
|
dns_rdataset_t *trdataset;
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
|
unsigned int nlabels;
|
|
|
|
int order;
|
|
|
|
dns_namereln_t namereln;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdata_cname_t cname;
|
|
|
|
dns_rdata_dname_t dname;
|
|
|
|
|
|
|
|
REQUIRE(RCTX_VALID(rctx));
|
|
|
|
|
|
|
|
LOCK(&rctx->lock);
|
|
|
|
|
|
|
|
mctx = rctx->view->mctx;
|
|
|
|
|
|
|
|
name = dns_fixedname_name(&rctx->name);
|
|
|
|
|
|
|
|
do {
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *fname = NULL;
|
|
|
|
dns_name_t *ansname = NULL;
|
|
|
|
dns_db_t *db = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_dbnode_t *node = NULL;
|
|
|
|
|
|
|
|
rctx->restarts++;
|
2018-04-17 08:29:14 -07:00
|
|
|
want_restart = false;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
if (event == NULL && !rctx->canceled) {
|
2018-03-28 14:38:09 +02:00
|
|
|
fname = dns_fixedname_initname(&foundname);
|
2009-09-01 00:22:28 +00:00
|
|
|
INSIST(!dns_rdataset_isassociated(rctx->rdataset));
|
|
|
|
INSIST(rctx->sigrdataset == NULL ||
|
|
|
|
!dns_rdataset_isassociated(rctx->sigrdataset));
|
|
|
|
result = view_find(rctx, &db, &node, fname);
|
|
|
|
if (result == ISC_R_NOTFOUND) {
|
|
|
|
/*
|
|
|
|
* We don't know anything about the name.
|
|
|
|
* Launch a fetch.
|
|
|
|
*/
|
|
|
|
if (node != NULL) {
|
|
|
|
INSIST(db != NULL);
|
|
|
|
dns_db_detachnode(db, &node);
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (db != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_db_detach(&db);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
result = start_fetch(rctx);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
putrdataset(mctx, &rctx->rdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rctx->sigrdataset != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
putrdataset(mctx,
|
|
|
|
&rctx->sigrdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
send_event = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
} else {
|
2011-03-11 06:11:27 +00:00
|
|
|
INSIST(event != NULL);
|
2009-09-01 00:22:28 +00:00
|
|
|
INSIST(event->fetch == rctx->fetch);
|
|
|
|
dns_resolver_destroyfetch(&rctx->fetch);
|
|
|
|
db = event->db;
|
|
|
|
node = event->node;
|
|
|
|
result = event->result;
|
|
|
|
vresult = event->vresult;
|
|
|
|
fname = dns_fixedname_name(&event->foundname);
|
|
|
|
INSIST(event->rdataset == rctx->rdataset);
|
|
|
|
INSIST(event->sigrdataset == rctx->sigrdataset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we've been canceled, forget about the result.
|
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rctx->canceled) {
|
2009-09-01 00:22:28 +00:00
|
|
|
result = ISC_R_CANCELED;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2009-09-01 00:22:28 +00:00
|
|
|
/*
|
|
|
|
* Otherwise, get some resource for copying the
|
|
|
|
* result.
|
|
|
|
*/
|
2019-10-12 00:15:51 +02:00
|
|
|
dns_name_t *aname = dns_fixedname_name(&rctx->name);
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
ansname = isc_mem_get(mctx, sizeof(*ansname));
|
2019-10-12 00:15:51 +02:00
|
|
|
dns_name_init(ansname, NULL);
|
|
|
|
|
2019-11-01 08:31:13 -05:00
|
|
|
dns_name_dup(aname, mctx, ansname);
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
case ISC_R_SUCCESS:
|
2018-04-17 08:29:14 -07:00
|
|
|
send_event = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
/*
|
|
|
|
* This case is handled in the main line below.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
case DNS_R_CNAME:
|
|
|
|
/*
|
|
|
|
* Add the CNAME to the answer list.
|
|
|
|
*/
|
|
|
|
trdataset = rctx->rdataset;
|
|
|
|
ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
|
|
|
|
rctx->rdataset = NULL;
|
|
|
|
if (rctx->sigrdataset != NULL) {
|
|
|
|
ISC_LIST_APPEND(ansname->list,
|
|
|
|
rctx->sigrdataset, link);
|
|
|
|
rctx->sigrdataset = NULL;
|
|
|
|
}
|
|
|
|
ISC_LIST_APPEND(rctx->namelist, ansname, link);
|
|
|
|
ansname = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the CNAME's target into the lookup's
|
|
|
|
* query name and start over.
|
|
|
|
*/
|
|
|
|
tresult = dns_rdataset_first(trdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataset_current(trdataset, &rdata);
|
|
|
|
tresult = dns_rdata_tostruct(&rdata, &cname, NULL);
|
|
|
|
dns_rdata_reset(&rdata);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(&cname.cname, name);
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdata_freestruct(&cname);
|
2019-09-27 08:37:26 +02:00
|
|
|
want_restart = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
|
|
|
case DNS_R_DNAME:
|
|
|
|
/*
|
|
|
|
* Add the DNAME to the answer list.
|
|
|
|
*/
|
|
|
|
trdataset = rctx->rdataset;
|
|
|
|
ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
|
|
|
|
rctx->rdataset = NULL;
|
|
|
|
if (rctx->sigrdataset != NULL) {
|
|
|
|
ISC_LIST_APPEND(ansname->list,
|
|
|
|
rctx->sigrdataset, link);
|
|
|
|
rctx->sigrdataset = NULL;
|
|
|
|
}
|
|
|
|
ISC_LIST_APPEND(rctx->namelist, ansname, link);
|
|
|
|
ansname = NULL;
|
|
|
|
|
|
|
|
namereln = dns_name_fullcompare(name, fname, &order,
|
|
|
|
&nlabels);
|
|
|
|
INSIST(namereln == dns_namereln_subdomain);
|
|
|
|
/*
|
|
|
|
* Get the target name of the DNAME.
|
|
|
|
*/
|
|
|
|
tresult = dns_rdataset_first(trdataset);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
dns_rdataset_current(trdataset, &rdata);
|
|
|
|
tresult = dns_rdata_tostruct(&rdata, &dname, NULL);
|
|
|
|
dns_rdata_reset(&rdata);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Construct the new query name and start over.
|
|
|
|
*/
|
2018-03-28 14:38:09 +02:00
|
|
|
prefix = dns_fixedname_initname(&fixed);
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_name_split(name, nlabels, prefix, NULL);
|
|
|
|
tresult = dns_name_concatenate(prefix, &dname.dname,
|
2020-02-12 13:59:18 +01:00
|
|
|
name, NULL);
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdata_freestruct(&dname);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
want_restart = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2009-09-01 00:22:28 +00:00
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
|
|
|
case DNS_R_NCACHENXDOMAIN:
|
|
|
|
case DNS_R_NCACHENXRRSET:
|
|
|
|
ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
|
|
|
|
ISC_LIST_APPEND(rctx->namelist, ansname, link);
|
|
|
|
ansname = NULL;
|
|
|
|
rctx->rdataset = NULL;
|
|
|
|
/* What about sigrdataset? */
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rctx->sigrdataset != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
putrdataset(mctx, &rctx->sigrdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
send_event = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
|
|
|
default:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rctx->rdataset != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
putrdataset(mctx, &rctx->rdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (rctx->sigrdataset != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
putrdataset(mctx, &rctx->sigrdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
send_event = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rctx->type == dns_rdatatype_any) {
|
2020-02-13 14:44:37 -08:00
|
|
|
int n = 0;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdatasetiter_t *rdsiter = NULL;
|
|
|
|
|
|
|
|
tresult = dns_db_allrdatasets(db, node, NULL, 0,
|
|
|
|
&rdsiter);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
tresult = dns_rdatasetiter_first(rdsiter);
|
|
|
|
while (tresult == ISC_R_SUCCESS) {
|
|
|
|
dns_rdatasetiter_current(rdsiter,
|
|
|
|
rctx->rdataset);
|
|
|
|
if (rctx->rdataset->type != 0) {
|
|
|
|
ISC_LIST_APPEND(ansname->list,
|
2020-02-12 13:59:18 +01:00
|
|
|
rctx->rdataset, link);
|
2009-09-01 00:22:28 +00:00
|
|
|
n++;
|
|
|
|
rctx->rdataset = NULL;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We're not interested in this
|
|
|
|
* rdataset.
|
|
|
|
*/
|
|
|
|
dns_rdataset_disassociate(
|
|
|
|
rctx->rdataset);
|
|
|
|
}
|
|
|
|
tresult = dns_rdatasetiter_next(rdsiter);
|
|
|
|
|
|
|
|
if (tresult == ISC_R_SUCCESS &&
|
|
|
|
rctx->rdataset == NULL) {
|
|
|
|
tresult = getrdataset(mctx,
|
|
|
|
&rctx->rdataset);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2011-03-11 06:11:27 +00:00
|
|
|
POST(result);
|
2009-09-01 00:22:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 00:13:14 +10:00
|
|
|
if (rctx->rdataset != NULL) {
|
|
|
|
putrdataset(mctx, &rctx->rdataset);
|
|
|
|
}
|
|
|
|
if (rctx->sigrdataset != NULL) {
|
|
|
|
putrdataset(mctx, &rctx->sigrdataset);
|
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
if (n == 0) {
|
|
|
|
/*
|
|
|
|
* We didn't match any rdatasets (which means
|
|
|
|
* something went wrong in this
|
|
|
|
* implementation).
|
|
|
|
*/
|
|
|
|
result = DNS_R_SERVFAIL; /* better code? */
|
2011-03-11 06:11:27 +00:00
|
|
|
POST(result);
|
2009-09-01 00:22:28 +00:00
|
|
|
} else {
|
|
|
|
ISC_LIST_APPEND(rctx->namelist, ansname, link);
|
|
|
|
ansname = NULL;
|
|
|
|
}
|
|
|
|
dns_rdatasetiter_destroy(&rdsiter);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tresult != ISC_R_NOMORE) {
|
2009-09-01 00:22:28 +00:00
|
|
|
result = DNS_R_SERVFAIL; /* ditto */
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2009-09-01 00:22:28 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
goto done;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* This is the "normal" case -- an ordinary question
|
|
|
|
* to which we've got the answer.
|
|
|
|
*/
|
|
|
|
ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
|
|
|
|
rctx->rdataset = NULL;
|
|
|
|
if (rctx->sigrdataset != NULL) {
|
|
|
|
ISC_LIST_APPEND(ansname->list,
|
|
|
|
rctx->sigrdataset, link);
|
|
|
|
rctx->sigrdataset = NULL;
|
|
|
|
}
|
|
|
|
ISC_LIST_APPEND(rctx->namelist, ansname, link);
|
|
|
|
ansname = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
/*
|
|
|
|
* Free temporary resources
|
|
|
|
*/
|
|
|
|
if (ansname != NULL) {
|
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
while ((rdataset = ISC_LIST_HEAD(ansname->list)) !=
|
|
|
|
NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
ISC_LIST_UNLINK(ansname->list, rdataset, link);
|
|
|
|
putrdataset(mctx, &rdataset);
|
|
|
|
}
|
|
|
|
dns_name_free(ansname, mctx);
|
|
|
|
isc_mem_put(mctx, ansname, sizeof(*ansname));
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (node != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_db_detachnode(db, &node);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (db != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_db_detach(&db);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (event != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_event_free(ISC_EVENT_PTR(&event));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Limit the number of restarts.
|
|
|
|
*/
|
|
|
|
if (want_restart && rctx->restarts == MAX_RESTARTS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
want_restart = false;
|
2009-09-01 00:22:28 +00:00
|
|
|
result = ISC_R_QUOTA;
|
2018-04-17 08:29:14 -07:00
|
|
|
send_event = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare further find with new resources
|
|
|
|
*/
|
|
|
|
if (want_restart) {
|
|
|
|
INSIST(rctx->rdataset == NULL &&
|
|
|
|
rctx->sigrdataset == NULL);
|
|
|
|
|
|
|
|
result = getrdataset(mctx, &rctx->rdataset);
|
|
|
|
if (result == ISC_R_SUCCESS && rctx->want_dnssec) {
|
|
|
|
result = getrdataset(mctx, &rctx->sigrdataset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
putrdataset(mctx, &rctx->rdataset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
want_restart = false;
|
|
|
|
send_event = true;
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (want_restart);
|
|
|
|
|
|
|
|
if (send_event) {
|
|
|
|
isc_task_t *task;
|
|
|
|
|
|
|
|
while ((name = ISC_LIST_HEAD(rctx->namelist)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(rctx->namelist, name, link);
|
|
|
|
ISC_LIST_APPEND(rctx->event->answerlist, name, link);
|
|
|
|
}
|
|
|
|
|
|
|
|
rctx->event->result = result;
|
|
|
|
rctx->event->vresult = vresult;
|
|
|
|
task = rctx->event->ev_sender;
|
|
|
|
rctx->event->ev_sender = rctx;
|
|
|
|
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&rctx->event));
|
|
|
|
}
|
|
|
|
|
|
|
|
UNLOCK(&rctx->lock);
|
|
|
|
}
|
|
|
|
|
2013-05-09 08:41:24 +10:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
suspend(isc_task_t *task, isc_event_t *event) {
|
2013-05-09 08:41:24 +10:00
|
|
|
isc_appctx_t *actx = event->ev_arg;
|
|
|
|
|
|
|
|
UNUSED(task);
|
|
|
|
|
|
|
|
isc_app_ctxsuspend(actx);
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
resolve_done(isc_task_t *task, isc_event_t *event) {
|
|
|
|
resarg_t *resarg = event->ev_arg;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
|
2021-08-12 13:51:47 -07:00
|
|
|
dns_name_t *name = NULL;
|
|
|
|
dns_client_t *client = resarg->client;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
UNUSED(task);
|
|
|
|
|
|
|
|
LOCK(&resarg->lock);
|
|
|
|
|
|
|
|
resarg->result = rev->result;
|
|
|
|
resarg->vresult = rev->vresult;
|
|
|
|
while ((name = ISC_LIST_HEAD(rev->answerlist)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(rev->answerlist, name, link);
|
|
|
|
ISC_LIST_APPEND(*resarg->namelist, name, link);
|
|
|
|
}
|
|
|
|
|
2021-08-12 13:51:47 -07:00
|
|
|
destroyrestrans(&resarg->trans);
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_event_free(&event);
|
2021-08-12 13:51:47 -07:00
|
|
|
resarg->client = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
if (!resarg->canceled) {
|
|
|
|
UNLOCK(&resarg->lock);
|
|
|
|
|
2013-05-09 08:41:24 +10:00
|
|
|
/*
|
|
|
|
* We may or may not be running. isc__appctx_onrun will
|
|
|
|
* fail if we are currently running otherwise we post a
|
|
|
|
* action to call isc_app_ctxsuspend when we do start
|
|
|
|
* running.
|
|
|
|
*/
|
2021-08-12 13:51:47 -07:00
|
|
|
result = isc_app_ctxonrun(resarg->actx, client->mctx, task,
|
|
|
|
suspend, resarg->actx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_ALREADYRUNNING) {
|
2013-05-09 08:41:24 +10:00
|
|
|
isc_app_ctxsuspend(resarg->actx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We have already exited from the loop (due to some
|
|
|
|
* unexpected event). Just clean the arg up.
|
|
|
|
*/
|
|
|
|
UNLOCK(&resarg->lock);
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&resarg->lock);
|
2021-08-12 13:51:47 -07:00
|
|
|
isc_mem_put(client->mctx, resarg, sizeof(*resarg));
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
2021-08-12 13:51:47 -07:00
|
|
|
|
|
|
|
dns_client_detach(&client);
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_client_resolve(dns_client_t *client, const dns_name_t *name,
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int options, dns_namelist_t *namelist) {
|
|
|
|
isc_result_t result;
|
2021-08-12 13:51:47 -07:00
|
|
|
resarg_t *resarg = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
2021-03-22 18:16:28 -07:00
|
|
|
REQUIRE(client->actx != NULL);
|
2009-09-01 00:22:28 +00:00
|
|
|
REQUIRE(namelist != NULL && ISC_LIST_EMPTY(*namelist));
|
|
|
|
|
|
|
|
resarg = isc_mem_get(client->mctx, sizeof(*resarg));
|
|
|
|
|
2021-03-22 18:16:28 -07:00
|
|
|
*resarg = (resarg_t){
|
|
|
|
.actx = client->actx,
|
|
|
|
.client = client,
|
|
|
|
.result = DNS_R_SERVFAIL,
|
|
|
|
.namelist = namelist,
|
|
|
|
};
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2021-04-19 14:32:40 +10:00
|
|
|
isc_mutex_init(&resarg->lock);
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
result = dns_client_startresolve(client, name, rdclass, type, options,
|
|
|
|
client->task, resolve_done, resarg,
|
|
|
|
&resarg->trans);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&resarg->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_mem_put(client->mctx, resarg, sizeof(*resarg));
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Start internal event loop. It blocks until the entire process
|
|
|
|
* is completed.
|
|
|
|
*/
|
2021-03-22 18:16:28 -07:00
|
|
|
result = isc_app_ctxrun(client->actx);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
LOCK(&resarg->lock);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) {
|
2009-09-01 00:22:28 +00:00
|
|
|
result = resarg->result;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
if (result != ISC_R_SUCCESS && resarg->vresult != ISC_R_SUCCESS) {
|
|
|
|
/*
|
|
|
|
* If this lookup failed due to some error in DNSSEC
|
|
|
|
* validation, return the validation error code.
|
2009-09-02 23:48:03 +00:00
|
|
|
* XXX: or should we pass the validation result separately?
|
2009-09-01 00:22:28 +00:00
|
|
|
*/
|
|
|
|
result = resarg->vresult;
|
|
|
|
}
|
|
|
|
if (resarg->trans != NULL) {
|
|
|
|
/*
|
|
|
|
* Unusual termination (perhaps due to signal). We need some
|
|
|
|
* tricky cleanup process.
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
resarg->canceled = true;
|
2021-08-12 13:51:47 -07:00
|
|
|
cancelresolve(resarg->trans);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
UNLOCK(&resarg->lock);
|
|
|
|
|
|
|
|
/* resarg will be freed in the event handler. */
|
|
|
|
} else {
|
|
|
|
UNLOCK(&resarg->lock);
|
|
|
|
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&resarg->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
isc_mem_put(client->mctx, resarg, sizeof(*resarg));
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
|
|
|
unsigned int options, isc_task_t *task,
|
|
|
|
isc_taskaction_t action, void *arg,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_clientrestrans_t **transp) {
|
|
|
|
dns_view_t *view = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_clientresevent_t *event = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
resctx_t *rctx = NULL;
|
|
|
|
isc_task_t *tclone = NULL;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdataset_t *rdataset, *sigrdataset;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool want_dnssec, want_validation, want_cdflag, want_tcp;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
|
|
|
REQUIRE(transp != NULL && *transp == NULL);
|
|
|
|
|
|
|
|
LOCK(&client->lock);
|
|
|
|
result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
|
|
|
|
rdclass, &view);
|
|
|
|
UNLOCK(&client->lock);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-09-01 00:22:28 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
mctx = client->mctx;
|
|
|
|
rdataset = NULL;
|
|
|
|
sigrdataset = NULL;
|
2018-10-11 11:57:57 +02:00
|
|
|
want_dnssec = ((options & DNS_CLIENTRESOPT_NODNSSEC) == 0);
|
|
|
|
want_validation = ((options & DNS_CLIENTRESOPT_NOVALIDATE) == 0);
|
|
|
|
want_cdflag = ((options & DNS_CLIENTRESOPT_NOCDFLAG) == 0);
|
|
|
|
want_tcp = ((options & DNS_CLIENTRESOPT_TCP) != 0);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare some intermediate resources
|
|
|
|
*/
|
2016-06-28 21:25:30 -04:00
|
|
|
tclone = NULL;
|
|
|
|
isc_task_attach(task, &tclone);
|
2020-02-12 13:59:18 +01:00
|
|
|
event = (dns_clientresevent_t *)isc_event_allocate(
|
|
|
|
mctx, tclone, DNS_EVENT_CLIENTRESDONE, action, arg,
|
|
|
|
sizeof(*event));
|
2009-09-01 00:22:28 +00:00
|
|
|
event->result = DNS_R_SERVFAIL;
|
|
|
|
ISC_LIST_INIT(event->answerlist);
|
|
|
|
|
|
|
|
rctx = isc_mem_get(mctx, sizeof(*rctx));
|
2020-01-30 19:41:32 +11:00
|
|
|
isc_mutex_init(&rctx->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
result = getrdataset(mctx, &rdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-09-01 00:22:28 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
rctx->rdataset = rdataset;
|
|
|
|
|
|
|
|
if (want_dnssec) {
|
|
|
|
result = getrdataset(mctx, &sigrdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-09-01 00:22:28 +00:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
rctx->sigrdataset = sigrdataset;
|
|
|
|
|
|
|
|
dns_fixedname_init(&rctx->name);
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(name, dns_fixedname_name(&rctx->name));
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
rctx->client = client;
|
|
|
|
ISC_LINK_INIT(rctx, link);
|
2018-04-17 08:29:14 -07:00
|
|
|
rctx->canceled = false;
|
2009-09-01 00:22:28 +00:00
|
|
|
rctx->task = client->task;
|
|
|
|
rctx->type = type;
|
|
|
|
rctx->view = view;
|
|
|
|
rctx->restarts = 0;
|
|
|
|
rctx->fetch = NULL;
|
|
|
|
rctx->want_dnssec = want_dnssec;
|
2014-02-16 13:03:17 -08:00
|
|
|
rctx->want_validation = want_validation;
|
|
|
|
rctx->want_cdflag = want_cdflag;
|
2014-11-21 09:37:04 -08:00
|
|
|
rctx->want_tcp = want_tcp;
|
2009-09-01 00:22:28 +00:00
|
|
|
ISC_LIST_INIT(rctx->namelist);
|
|
|
|
rctx->event = event;
|
|
|
|
|
|
|
|
rctx->magic = RCTX_MAGIC;
|
2019-08-06 17:35:20 +02:00
|
|
|
isc_refcount_increment(&client->references);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
LOCK(&client->lock);
|
|
|
|
ISC_LIST_APPEND(client->resctxs, rctx, link);
|
|
|
|
UNLOCK(&client->lock);
|
|
|
|
|
|
|
|
*transp = (dns_clientrestrans_t *)rctx;
|
2013-05-09 08:41:24 +10:00
|
|
|
client_resfind(rctx, NULL);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rdataset != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
putrdataset(client->mctx, &rdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (sigrdataset != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
putrdataset(client->mctx, &sigrdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-07-02 16:21:20 +10:00
|
|
|
isc_mutex_destroy(&rctx->lock);
|
|
|
|
isc_mem_put(mctx, rctx, sizeof(*rctx));
|
2020-02-05 16:11:11 +11:00
|
|
|
isc_event_free(ISC_EVENT_PTR(&event));
|
2016-06-28 21:25:30 -04:00
|
|
|
isc_task_detach(&tclone);
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_view_detach(&view);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2021-08-12 13:51:47 -07:00
|
|
|
/*%<
|
|
|
|
* Cancel an ongoing resolution procedure started via
|
|
|
|
* dns_client_startresolve().
|
|
|
|
*
|
|
|
|
* If the resolution procedure has not completed, post its CLIENTRESDONE
|
|
|
|
* event with a result code of #ISC_R_CANCELED.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cancelresolve(dns_clientrestrans_t *trans) {
|
|
|
|
resctx_t *rctx = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(trans != NULL);
|
|
|
|
rctx = (resctx_t *)trans;
|
|
|
|
REQUIRE(RCTX_VALID(rctx));
|
|
|
|
|
|
|
|
LOCK(&rctx->lock);
|
|
|
|
|
|
|
|
if (!rctx->canceled) {
|
2018-04-17 08:29:14 -07:00
|
|
|
rctx->canceled = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (rctx->fetch != NULL) {
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_resolver_cancelfetch(rctx->fetch);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UNLOCK(&rctx->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist) {
|
|
|
|
dns_name_t *name;
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
|
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
|
|
|
REQUIRE(namelist != NULL);
|
|
|
|
|
|
|
|
while ((name = ISC_LIST_HEAD(*namelist)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(*namelist, name, link);
|
|
|
|
while ((rdataset = ISC_LIST_HEAD(name->list)) != NULL) {
|
|
|
|
ISC_LIST_UNLINK(name->list, rdataset, link);
|
|
|
|
putrdataset(client->mctx, &rdataset);
|
|
|
|
}
|
|
|
|
dns_name_free(name, client->mctx);
|
|
|
|
isc_mem_put(client->mctx, name, sizeof(*name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 13:51:47 -07:00
|
|
|
/*%
|
|
|
|
* Destroy name resolution transaction state identified by '*transp'.
|
|
|
|
*
|
|
|
|
* The caller must have received the CLIENTRESDONE event (either because the
|
|
|
|
* resolution completed or because cancelresolve() was called).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
destroyrestrans(dns_clientrestrans_t **transp) {
|
|
|
|
resctx_t *rctx = NULL;
|
|
|
|
isc_mem_t *mctx = NULL;
|
|
|
|
dns_client_t *client = NULL;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(transp != NULL);
|
2021-08-12 13:51:47 -07:00
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
rctx = (resctx_t *)*transp;
|
2019-08-06 17:35:20 +02:00
|
|
|
*transp = NULL;
|
2021-08-12 13:51:47 -07:00
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
REQUIRE(RCTX_VALID(rctx));
|
|
|
|
REQUIRE(rctx->fetch == NULL);
|
|
|
|
REQUIRE(rctx->event == NULL);
|
2021-08-12 13:51:47 -07:00
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
client = rctx->client;
|
2021-08-12 13:51:47 -07:00
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
|
|
|
|
|
|
|
mctx = client->mctx;
|
|
|
|
dns_view_detach(&rctx->view);
|
|
|
|
|
2015-09-30 14:58:31 +10:00
|
|
|
/*
|
|
|
|
* Wait for the lock in client_resfind to be released before
|
|
|
|
* destroying the lock.
|
|
|
|
*/
|
|
|
|
LOCK(&rctx->lock);
|
|
|
|
UNLOCK(&rctx->lock);
|
|
|
|
|
2009-09-01 00:22:28 +00:00
|
|
|
LOCK(&client->lock);
|
|
|
|
|
|
|
|
INSIST(ISC_LINK_LINKED(rctx, link));
|
|
|
|
ISC_LIST_UNLINK(client->resctxs, rctx, link);
|
|
|
|
|
|
|
|
UNLOCK(&client->lock);
|
|
|
|
|
|
|
|
INSIST(ISC_LIST_EMPTY(rctx->namelist));
|
|
|
|
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&rctx->lock);
|
2009-09-01 00:22:28 +00:00
|
|
|
rctx->magic = 0;
|
|
|
|
|
|
|
|
isc_mem_put(mctx, rctx, sizeof(*rctx));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
|
2019-09-18 19:45:20 -07:00
|
|
|
dns_rdatatype_t rdtype, const dns_name_t *keyname,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t *databuf) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_view_t *view = NULL;
|
|
|
|
dns_keytable_t *secroots = NULL;
|
|
|
|
dns_name_t *name = NULL;
|
2020-02-28 20:08:04 +00:00
|
|
|
char rdatabuf[DST_KEY_MAXSIZE];
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned char digest[ISC_MAX_MD_SIZE];
|
|
|
|
dns_rdata_ds_t ds;
|
2019-09-18 19:45:20 -07:00
|
|
|
dns_decompress_t dctx;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_rdata_t rdata;
|
|
|
|
isc_buffer_t b;
|
2009-09-01 00:22:28 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_CLIENT_VALID(client));
|
|
|
|
|
|
|
|
LOCK(&client->lock);
|
|
|
|
result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
|
|
|
|
rdclass, &view);
|
|
|
|
UNLOCK(&client->lock);
|
2019-09-18 19:45:20 -07:00
|
|
|
CHECK(result);
|
2009-10-27 22:46:13 +00:00
|
|
|
|
2019-09-18 19:45:20 -07:00
|
|
|
CHECK(dns_view_getsecroots(view, &secroots));
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2019-09-18 19:45:20 -07:00
|
|
|
DE_CONST(keyname, name);
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2019-12-20 11:37:11 -08:00
|
|
|
if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) {
|
2019-09-18 19:45:20 -07:00
|
|
|
result = ISC_R_NOTIMPLEMENTED;
|
2019-12-20 11:37:11 -08:00
|
|
|
goto cleanup;
|
2019-09-18 19:45:20 -07:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
|
2020-02-28 20:08:04 +00:00
|
|
|
isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
|
2019-12-20 11:37:11 -08:00
|
|
|
dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
|
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
|
2020-02-12 13:59:18 +01:00
|
|
|
CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype, databuf, &dctx, 0,
|
|
|
|
&b));
|
2019-12-20 11:37:11 -08:00
|
|
|
dns_decompress_invalidate(&dctx);
|
|
|
|
|
|
|
|
if (rdtype == dns_rdatatype_ds) {
|
|
|
|
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
|
|
|
|
} else {
|
|
|
|
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
|
|
|
|
digest, &ds));
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(dns_keytable_add(secroots, false, false, name, &ds));
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup:
|
2019-09-18 19:45:20 -07:00
|
|
|
if (view != NULL) {
|
2009-10-27 22:46:13 +00:00
|
|
|
dns_view_detach(&view);
|
2019-09-18 19:45:20 -07:00
|
|
|
}
|
|
|
|
if (secroots != NULL) {
|
2009-10-27 22:46:13 +00:00
|
|
|
dns_keytable_detach(&secroots);
|
2019-09-18 19:45:20 -07:00
|
|
|
}
|
2009-09-01 00:22:28 +00:00
|
|
|
return (result);
|
|
|
|
}
|