1999-06-16 01:32:31 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2021-06-03 08:37:05 +02:00
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*
|
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.
|
1999-06-16 01:32:31 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2025-07-14 17:12:35 +02:00
|
|
|
/*
|
|
|
|
* FIXME: Might need dns_dispatch_shuttingdown()
|
|
|
|
*/
|
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
1999-06-16 01:32:31 +00:00
|
|
|
#include <stdlib.h>
|
2020-03-09 16:17:26 +01:00
|
|
|
#include <sys/types.h>
|
2007-06-26 02:52:15 +00:00
|
|
|
#include <unistd.h>
|
1999-06-16 01:32:31 +00:00
|
|
|
|
2024-03-04 12:58:56 +01:00
|
|
|
#include <isc/async.h>
|
2023-09-14 18:01:39 +02:00
|
|
|
#include <isc/hash.h>
|
|
|
|
#include <isc/hashmap.h>
|
2024-08-14 13:25:50 +02:00
|
|
|
#include <isc/log.h>
|
2023-05-27 19:20:47 -07:00
|
|
|
#include <isc/loop.h>
|
1999-06-18 02:01:42 +00:00
|
|
|
#include <isc/mem.h>
|
2000-05-10 21:34:50 +00:00
|
|
|
#include <isc/mutex.h>
|
2021-10-04 14:11:57 +02:00
|
|
|
#include <isc/net.h>
|
2021-01-14 13:02:57 -08:00
|
|
|
#include <isc/netmgr.h>
|
2008-06-23 19:41:20 +00:00
|
|
|
#include <isc/portset.h>
|
|
|
|
#include <isc/random.h>
|
2009-01-27 22:30:00 +00:00
|
|
|
#include <isc/stats.h>
|
2000-05-13 21:57:02 +00:00
|
|
|
#include <isc/string.h>
|
2023-01-04 19:21:14 +01:00
|
|
|
#include <isc/tid.h>
|
2007-06-26 06:02:37 +00:00
|
|
|
#include <isc/time.h>
|
2022-09-19 11:04:22 +00:00
|
|
|
#include <isc/tls.h>
|
2023-09-14 18:01:39 +02:00
|
|
|
#include <isc/urcu.h>
|
1999-12-16 22:24:22 +00:00
|
|
|
#include <isc/util.h>
|
1999-06-16 01:32:31 +00:00
|
|
|
|
2000-11-03 02:45:55 +00:00
|
|
|
#include <dns/acl.h>
|
1999-06-16 01:32:31 +00:00
|
|
|
#include <dns/dispatch.h>
|
1999-06-30 01:33:11 +00:00
|
|
|
#include <dns/message.h>
|
2008-04-03 05:55:52 +00:00
|
|
|
#include <dns/stats.h>
|
2022-09-19 11:04:22 +00:00
|
|
|
#include <dns/transport.h>
|
2000-05-10 21:34:50 +00:00
|
|
|
#include <dns/types.h>
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
|
2000-09-18 04:50:05 +00:00
|
|
|
|
2000-05-10 21:34:50 +00:00
|
|
|
struct dns_dispatchmgr {
|
|
|
|
/* Unlocked. */
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_refcount_t references;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mem_t *mctx;
|
|
|
|
dns_acl_t *blackhole;
|
|
|
|
isc_stats_t *stats;
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
uint32_t nloops;
|
|
|
|
|
|
|
|
struct cds_lfht **tcps;
|
2000-09-19 06:59:28 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
struct cds_lfht *qids;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t *v4ports; /*%< available ports for IPv4 */
|
2020-02-12 13:59:18 +01:00
|
|
|
unsigned int nv4ports; /*%< # of available ports for IPv4 */
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t *v6ports; /*%< available ports for IPv4 */
|
2020-02-12 13:59:18 +01:00
|
|
|
unsigned int nv6ports; /*%< # of available ports for IPv4 */
|
2000-05-10 21:34:50 +00:00
|
|
|
};
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
typedef enum {
|
|
|
|
DNS_DISPATCHSTATE_NONE = 0UL,
|
|
|
|
DNS_DISPATCHSTATE_CONNECTING,
|
|
|
|
DNS_DISPATCHSTATE_CONNECTED,
|
|
|
|
DNS_DISPATCHSTATE_CANCELED,
|
|
|
|
} dns_dispatchstate_t;
|
|
|
|
|
1999-07-06 19:32:40 +00:00
|
|
|
struct dns_dispentry {
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_refcount_t references;
|
2023-09-14 18:01:39 +02:00
|
|
|
isc_mem_t *mctx;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatch_t *disp;
|
2023-05-27 19:20:47 -07:00
|
|
|
isc_loop_t *loop;
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nmhandle_t *handle; /*%< netmgr handle for UDP connection */
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatchstate_t state;
|
2022-09-19 11:04:22 +00:00
|
|
|
dns_transport_t *transport;
|
|
|
|
isc_tlsctx_cache_t *tlsctx_cache;
|
2021-08-04 13:14:11 -07:00
|
|
|
unsigned int retries;
|
2024-10-30 09:23:33 +00:00
|
|
|
unsigned int connect_timeout;
|
2021-10-01 12:53:31 -07:00
|
|
|
unsigned int timeout;
|
|
|
|
isc_time_t start;
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_sockaddr_t local;
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_sockaddr_t peer;
|
2021-05-25 22:54:17 -07:00
|
|
|
in_port_t port;
|
|
|
|
dns_messageid_t id;
|
2021-08-03 15:27:06 +02:00
|
|
|
dispatch_cb_t connected;
|
|
|
|
dispatch_cb_t sent;
|
|
|
|
dispatch_cb_t response;
|
2020-02-13 14:44:37 -08:00
|
|
|
void *arg;
|
2022-11-30 17:58:35 +01:00
|
|
|
bool reading;
|
|
|
|
isc_result_t result;
|
2021-05-25 22:54:17 -07:00
|
|
|
ISC_LINK(dns_dispentry_t) alink;
|
2021-08-03 18:24:27 -07:00
|
|
|
ISC_LINK(dns_dispentry_t) plink;
|
2021-08-04 13:14:11 -07:00
|
|
|
ISC_LINK(dns_dispentry_t) rlink;
|
2023-09-14 18:01:39 +02:00
|
|
|
|
|
|
|
struct cds_lfht_node ht_node;
|
|
|
|
struct rcu_head rcu_head;
|
2008-06-23 19:41:20 +00:00
|
|
|
};
|
|
|
|
|
1999-06-16 01:32:31 +00:00
|
|
|
struct dns_dispatch {
|
|
|
|
/* Unlocked. */
|
2023-01-04 19:21:14 +01:00
|
|
|
unsigned int magic; /*%< magic */
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid;
|
2023-09-15 15:59:28 +02:00
|
|
|
isc_socktype_t socktype;
|
|
|
|
isc_refcount_t references;
|
2023-09-15 14:38:02 +02:00
|
|
|
isc_mem_t *mctx;
|
2024-10-15 16:09:48 +11:00
|
|
|
dns_dispatchmgr_t *mgr; /*%< dispatch manager */
|
|
|
|
isc_nmhandle_t *handle; /*%< netmgr handle for TCP connection */
|
|
|
|
isc_sockaddr_t local; /*%< local address */
|
|
|
|
isc_sockaddr_t peer; /*%< peer address (TCP) */
|
|
|
|
dns_transport_t *transport; /*%< TCP transport parameters */
|
2012-04-28 14:52:28 -07:00
|
|
|
|
2023-10-20 08:14:27 +02:00
|
|
|
dns_dispatchopt_t options;
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatchstate_t state;
|
|
|
|
|
|
|
|
bool reading;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dns_displist_t pending;
|
|
|
|
dns_displist_t active;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
uint_fast32_t requests; /*%< how many requests we have */
|
2021-11-29 09:59:33 +01:00
|
|
|
|
|
|
|
unsigned int timedout;
|
2023-09-15 14:38:02 +02:00
|
|
|
|
|
|
|
struct cds_lfht_node ht_node;
|
|
|
|
struct rcu_head rcu_head;
|
1999-06-16 01:32:31 +00:00
|
|
|
};
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define DISPATCH_MAGIC ISC_MAGIC('D', 'i', 's', 'p')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
|
2020-02-13 14:44:37 -08:00
|
|
|
#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
#define dns_dispentry_ref(ptr) \
|
|
|
|
dns_dispentry__ref(ptr, __func__, __FILE__, __LINE__)
|
|
|
|
#define dns_dispentry_unref(ptr) \
|
|
|
|
dns_dispentry__unref(ptr, __func__, __FILE__, __LINE__)
|
|
|
|
#define dns_dispentry_attach(ptr, ptrp) \
|
|
|
|
dns_dispentry__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
|
|
|
|
#define dns_dispentry_detach(ptrp) \
|
|
|
|
dns_dispentry__detach(ptrp, __func__, __FILE__, __LINE__)
|
|
|
|
ISC_REFCOUNT_TRACE_DECL(dns_dispentry);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_DECL(dns_dispentry);
|
|
|
|
#endif
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
/*
|
|
|
|
* The number of attempts to find unique <addr, port, query_id> combination
|
|
|
|
*/
|
|
|
|
#define QID_MAX_TRIES 64
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initial and minimum QID table sizes.
|
|
|
|
*/
|
|
|
|
#define QIDS_INIT_SIZE (1 << 4) /* Must be power of 2 */
|
|
|
|
#define QIDS_MIN_SIZE (1 << 4) /* Must be power of 2 */
|
|
|
|
|
1999-06-30 01:33:11 +00:00
|
|
|
/*
|
2000-05-13 21:57:02 +00:00
|
|
|
* Statics.
|
1999-06-30 01:33:11 +00:00
|
|
|
*/
|
2021-05-25 22:54:17 -07:00
|
|
|
static void
|
|
|
|
dispatchmgr_destroy(dns_dispatchmgr_t *mgr);
|
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
2021-01-14 13:02:57 -08:00
|
|
|
udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|
|
|
void *arg);
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
2021-01-14 13:02:57 -08:00
|
|
|
tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|
|
|
void *arg);
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
2022-11-30 17:58:35 +01:00
|
|
|
dispentry_cancel(dns_dispentry_t *resp, isc_result_t result);
|
2020-02-14 08:14:03 +01:00
|
|
|
static isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid, dns_dispatch_t **dispp);
|
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
|
|
|
static void
|
2022-11-30 17:58:35 +01:00
|
|
|
udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp);
|
|
|
|
static void
|
2023-05-16 15:35:00 -07:00
|
|
|
udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp);
|
|
|
|
static void
|
2023-02-21 20:14:30 -08:00
|
|
|
tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp);
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
|
|
|
tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
|
2024-10-30 13:31:34 +00:00
|
|
|
int64_t timeout);
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
2024-10-30 13:31:34 +00:00
|
|
|
udp_dispatch_getnext(dns_dispentry_t *resp, int64_t timeout);
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
static const char *
|
|
|
|
socktype2str(dns_dispentry_t *resp) {
|
|
|
|
dns_transport_type_t transport_type = DNS_TRANSPORT_UDP;
|
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
|
|
|
|
if (disp->socktype == isc_socktype_tcp) {
|
|
|
|
if (resp->transport != NULL) {
|
|
|
|
transport_type =
|
|
|
|
dns_transport_get_type(resp->transport);
|
|
|
|
} else {
|
|
|
|
transport_type = DNS_TRANSPORT_TCP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (transport_type) {
|
|
|
|
case DNS_TRANSPORT_UDP:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "UDP";
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_TRANSPORT_TCP:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "TCP";
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_TRANSPORT_TLS:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "TLS";
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_TRANSPORT_HTTP:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "HTTP";
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "<unexpected>";
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
state2str(dns_dispatchstate_t state) {
|
|
|
|
switch (state) {
|
|
|
|
case DNS_DISPATCHSTATE_NONE:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "none";
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "connecting";
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTED:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "connected";
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CANCELED:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "canceled";
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
2024-11-19 10:38:03 +01:00
|
|
|
return "<unexpected>";
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...)
|
2020-02-12 13:59:18 +01:00
|
|
|
ISC_FORMAT_PRINTF(3, 4);
|
2001-08-08 22:54:55 +00:00
|
|
|
|
2000-04-29 00:45:26 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {
|
|
|
|
char msgbuf[2048];
|
2000-04-29 00:45:26 +00:00
|
|
|
va_list ap;
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
if (!isc_log_wouldlog(level)) {
|
2000-07-17 23:25:35 +00:00
|
|
|
return;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-07-17 23:25:35 +00:00
|
|
|
|
2000-04-29 00:45:26 +00:00
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH, level,
|
|
|
|
"dispatchmgr %p: %s", mgr, msgbuf);
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
inc_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (mgr->stats != NULL) {
|
2009-01-31 00:10:24 +00:00
|
|
|
isc_stats_increment(mgr->stats, counter);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-01-31 00:10:24 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
dec_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (mgr->stats != NULL) {
|
2012-05-14 10:06:05 -07:00
|
|
|
isc_stats_decrement(mgr->stats, counter);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-05-14 10:06:05 -07:00
|
|
|
}
|
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)
|
2020-02-12 13:59:18 +01:00
|
|
|
ISC_FORMAT_PRINTF(3, 4);
|
2001-08-08 22:54:55 +00:00
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) {
|
|
|
|
char msgbuf[2048];
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
va_list ap;
|
2022-11-30 17:58:35 +01:00
|
|
|
int r;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
if (!isc_log_wouldlog(level)) {
|
2000-07-13 01:16:22 +00:00
|
|
|
return;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
va_start(ap, fmt);
|
2022-11-30 17:58:35 +01:00
|
|
|
r = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
|
|
|
|
if (r < 0) {
|
|
|
|
msgbuf[0] = '\0';
|
|
|
|
} else if ((unsigned int)r >= sizeof(msgbuf)) {
|
|
|
|
/* Truncated */
|
|
|
|
msgbuf[sizeof(msgbuf) - 1] = '\0';
|
|
|
|
}
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH, level,
|
|
|
|
"dispatch %p: %s", disp, msgbuf);
|
2000-04-29 00:45:26 +00:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
|
|
|
dispentry_log(dns_dispentry_t *resp, int level, const char *fmt, ...)
|
|
|
|
ISC_FORMAT_PRINTF(3, 4);
|
|
|
|
|
|
|
|
static void
|
|
|
|
dispentry_log(dns_dispentry_t *resp, int level, const char *fmt, ...) {
|
|
|
|
char msgbuf[2048];
|
|
|
|
va_list ap;
|
|
|
|
int r;
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
if (!isc_log_wouldlog(level)) {
|
2022-11-30 17:58:35 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
r = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
|
|
|
|
if (r < 0) {
|
|
|
|
msgbuf[0] = '\0';
|
|
|
|
} else if ((unsigned int)r >= sizeof(msgbuf)) {
|
|
|
|
/* Truncated */
|
|
|
|
msgbuf[sizeof(msgbuf) - 1] = '\0';
|
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
dispatch_log(resp->disp, level, "%s response %p: %s",
|
|
|
|
socktype2str(resp), resp, msgbuf);
|
|
|
|
}
|
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
/*%
|
2021-05-25 22:54:17 -07:00
|
|
|
* Choose a random port number for a dispatch entry.
|
2008-06-23 19:41:20 +00:00
|
|
|
*/
|
|
|
|
static isc_result_t
|
2021-05-25 22:54:17 -07:00
|
|
|
setup_socket(dns_dispatch_t *disp, dns_dispentry_t *resp,
|
|
|
|
const isc_sockaddr_t *dest, in_port_t *portp) {
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchmgr_t *mgr = disp->mgr;
|
|
|
|
unsigned int nports;
|
2020-12-09 19:44:41 -08:00
|
|
|
in_port_t *ports = NULL;
|
2023-02-02 12:16:49 -08:00
|
|
|
in_port_t port = *portp;
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (resp->retries++ > 5) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_FAILURE;
|
2021-08-04 13:14:11 -07:00
|
|
|
}
|
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
if (isc_sockaddr_pf(&disp->local) == AF_INET) {
|
2020-12-09 19:44:41 -08:00
|
|
|
nports = mgr->nv4ports;
|
|
|
|
ports = mgr->v4ports;
|
2008-06-23 19:41:20 +00:00
|
|
|
} else {
|
2020-12-09 19:44:41 -08:00
|
|
|
nports = mgr->nv6ports;
|
|
|
|
ports = mgr->v6ports;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (nports == 0) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_ADDRNOTAVAIL;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
resp->local = disp->local;
|
|
|
|
resp->peer = *dest;
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2023-02-02 12:16:49 -08:00
|
|
|
if (port == 0) {
|
|
|
|
port = ports[isc_random_uniform(nports)];
|
|
|
|
isc_sockaddr_setport(&resp->local, port);
|
|
|
|
*portp = port;
|
|
|
|
}
|
2021-05-25 22:54:17 -07:00
|
|
|
resp->port = port;
|
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
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
static uint32_t
|
|
|
|
qid_hash(const dns_dispentry_t *dispentry) {
|
2023-09-18 10:02:37 +02:00
|
|
|
isc_hash32_t hash;
|
|
|
|
|
|
|
|
isc_hash32_init(&hash);
|
|
|
|
|
|
|
|
isc_sockaddr_hash_ex(&hash, &dispentry->peer, true);
|
|
|
|
isc_hash32_hash(&hash, &dispentry->id, sizeof(dispentry->id), true);
|
|
|
|
isc_hash32_hash(&hash, &dispentry->port, sizeof(dispentry->port), true);
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return isc_hash32_finalize(&hash);
|
2023-09-14 18:01:39 +02:00
|
|
|
}
|
1999-07-09 20:34:26 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
static int
|
|
|
|
qid_match(struct cds_lfht_node *node, const void *key0) {
|
|
|
|
const dns_dispentry_t *dispentry =
|
|
|
|
caa_container_of(node, dns_dispentry_t, ht_node);
|
|
|
|
const dns_dispentry_t *key = key0;
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return dispentry->id == key->id && dispentry->port == key->port &&
|
|
|
|
isc_sockaddr_equal(&dispentry->peer, &key->peer);
|
2023-09-14 18:01:39 +02:00
|
|
|
}
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
static void
|
|
|
|
dispentry_destroy_rcu(struct rcu_head *rcu_head) {
|
|
|
|
dns_dispentry_t *resp = caa_container_of(rcu_head, dns_dispentry_t,
|
|
|
|
rcu_head);
|
|
|
|
isc_mem_putanddetach(&resp->mctx, resp, sizeof(*resp));
|
1999-06-30 01:33:11 +00:00
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
static void
|
2022-11-30 17:58:35 +01:00
|
|
|
dispentry_destroy(dns_dispentry_t *resp) {
|
|
|
|
dns_dispatch_t *disp = resp->disp;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
/*
|
|
|
|
* We need to call this from here in case there's an external event that
|
|
|
|
* shuts down our dispatch (like ISC_R_SHUTTINGDOWN).
|
|
|
|
*/
|
|
|
|
dispentry_cancel(resp, ISC_R_CANCELED);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
INSIST(disp->requests > 0);
|
|
|
|
disp->requests--;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
|
|
|
resp->magic = 0;
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
INSIST(!ISC_LINK_LINKED(resp, plink));
|
2021-08-04 13:14:11 -07:00
|
|
|
INSIST(!ISC_LINK_LINKED(resp, alink));
|
|
|
|
INSIST(!ISC_LINK_LINKED(resp, rlink));
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "destroying");
|
2022-11-30 17:58:35 +01:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (resp->handle != NULL) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
|
|
|
"detaching handle %p from %p", resp->handle,
|
|
|
|
&resp->handle);
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nmhandle_detach(&resp->handle);
|
|
|
|
}
|
|
|
|
|
2022-09-19 11:04:22 +00:00
|
|
|
if (resp->tlsctx_cache != NULL) {
|
|
|
|
isc_tlsctx_cache_detach(&resp->tlsctx_cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp->transport != NULL) {
|
|
|
|
dns_transport_detach(&resp->transport);
|
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_detach(&disp); /* DISPATCH001 */
|
2023-09-14 18:01:39 +02:00
|
|
|
|
|
|
|
call_rcu(&resp->rcu_head, dispentry_destroy_rcu);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(dns_dispentry, dispentry_destroy);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_IMPL(dns_dispentry, dispentry_destroy);
|
|
|
|
#endif
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-10-01 12:53:31 -07:00
|
|
|
/*
|
|
|
|
* How long in milliseconds has it been since this dispentry
|
2023-05-16 15:35:00 -07:00
|
|
|
* started reading?
|
2021-10-01 12:53:31 -07:00
|
|
|
*/
|
|
|
|
static unsigned int
|
2023-05-16 15:35:00 -07:00
|
|
|
dispentry_runtime(dns_dispentry_t *resp, const isc_time_t *now) {
|
2021-10-01 12:53:31 -07:00
|
|
|
if (isc_time_isepoch(&resp->start)) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return 0;
|
2021-10-01 12:53:31 -07:00
|
|
|
}
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return isc_time_microdiff(now, &resp->start) / 1000;
|
2021-10-01 12:53:31 -07:00
|
|
|
}
|
|
|
|
|
1999-07-08 02:50:00 +00:00
|
|
|
/*
|
|
|
|
* General flow:
|
|
|
|
*
|
2001-05-14 23:10:19 +00:00
|
|
|
* If I/O result == CANCELED or error, free the buffer.
|
1999-07-08 02:50:00 +00:00
|
|
|
*
|
2002-09-04 02:26:13 +00:00
|
|
|
* If query, free the buffer, restart.
|
1999-07-08 02:50:00 +00:00
|
|
|
*
|
|
|
|
* If response:
|
|
|
|
* Allocate event, fill in details.
|
|
|
|
* If cannot allocate, free buffer, restart.
|
|
|
|
* find target. If not found, free buffer, restart.
|
|
|
|
* if event queue is not empty, queue. else, send.
|
|
|
|
* restart.
|
|
|
|
*/
|
1999-06-30 01:33:11 +00:00
|
|
|
static void
|
2021-01-14 13:02:57 -08:00
|
|
|
udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|
|
|
void *arg) {
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispentry_t *resp = (dns_dispentry_t *)arg;
|
2020-12-16 01:32:06 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_messageid_t id;
|
|
|
|
isc_result_t dres;
|
|
|
|
isc_buffer_t source;
|
|
|
|
unsigned int flags;
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_sockaddr_t peer;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_netaddr_t netaddr;
|
2024-10-30 13:31:34 +00:00
|
|
|
int match;
|
|
|
|
int64_t timeout = 0;
|
2023-02-22 11:04:12 -08:00
|
|
|
bool respond = true;
|
2023-05-16 15:35:00 -07:00
|
|
|
isc_time_t now;
|
2020-12-16 01:32:06 -08:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
2021-07-26 20:23:18 -07:00
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
2020-12-16 01:32:06 -08:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
disp = resp->disp;
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
INSIST(resp->reading);
|
|
|
|
resp->reading = false;
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (resp->state == DNS_DISPATCHSTATE_CANCELED) {
|
|
|
|
/*
|
|
|
|
* Nobody is interested in the callback if the response
|
|
|
|
* has been canceled already. Detach from the response
|
|
|
|
* and the handle.
|
|
|
|
*/
|
2023-02-22 11:04:12 -08:00
|
|
|
respond = false;
|
2022-04-27 12:29:50 +00:00
|
|
|
eresult = ISC_R_CANCELED;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
|
|
|
"read callback:%s, requests %" PRIuFAST32,
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(eresult), disp->requests);
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (eresult != ISC_R_SUCCESS) {
|
2000-02-02 23:29:47 +00:00
|
|
|
/*
|
2021-08-04 13:14:11 -07:00
|
|
|
* This is most likely a network error on a connected
|
|
|
|
* socket, a timeout, or the query has been canceled.
|
|
|
|
* It makes no sense to check the address or parse the
|
|
|
|
* packet, but we can return the error to the caller.
|
2000-02-02 23:29:47 +00:00
|
|
|
*/
|
2021-08-04 13:14:11 -07:00
|
|
|
goto done;
|
2000-02-02 23:29:47 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
peer = isc_nmhandle_peeraddr(handle);
|
|
|
|
isc_netaddr_fromsockaddr(&netaddr, &peer);
|
|
|
|
|
2000-11-03 02:45:55 +00:00
|
|
|
/*
|
|
|
|
* If this is from a blackholed address, drop it.
|
|
|
|
*/
|
2001-02-08 18:25:09 +00:00
|
|
|
if (disp->mgr->blackhole != NULL &&
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_acl_match(&netaddr, NULL, disp->mgr->blackhole, NULL, &match,
|
|
|
|
NULL) == ISC_R_SUCCESS &&
|
2020-02-13 14:44:37 -08:00
|
|
|
match > 0)
|
|
|
|
{
|
2024-08-13 18:20:26 +02:00
|
|
|
if (isc_log_wouldlog(ISC_LOG_DEBUG(10))) {
|
2000-11-03 02:45:55 +00:00
|
|
|
char netaddrstr[ISC_NETADDR_FORMATSIZE];
|
|
|
|
isc_netaddr_format(&netaddr, netaddrstr,
|
|
|
|
sizeof(netaddrstr));
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(10),
|
2022-11-30 17:58:35 +01:00
|
|
|
"blackholed packet from %s", netaddrstr);
|
2000-11-03 02:45:55 +00:00
|
|
|
}
|
2021-08-04 13:14:11 -07:00
|
|
|
goto next;
|
2000-11-03 02:45:55 +00:00
|
|
|
}
|
|
|
|
|
1999-06-30 01:33:11 +00:00
|
|
|
/*
|
|
|
|
* Peek into the buffer to see what we can see.
|
|
|
|
*/
|
2021-08-04 13:14:11 -07:00
|
|
|
id = resp->id;
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_buffer_init(&source, region->base, region->length);
|
|
|
|
isc_buffer_add(&source, region->length);
|
1999-06-30 01:33:11 +00:00
|
|
|
dres = dns_message_peekheader(&source, &id, &flags);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (dres != ISC_R_SUCCESS) {
|
2022-11-30 17:58:35 +01:00
|
|
|
char netaddrstr[ISC_NETADDR_FORMATSIZE];
|
|
|
|
isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(10),
|
|
|
|
"got garbage packet from %s", netaddrstr);
|
2021-08-04 13:14:11 -07:00
|
|
|
goto next;
|
1999-06-30 01:33:11 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(92),
|
2022-11-30 17:58:35 +01:00
|
|
|
"got valid DNS message header, /QR %c, id %u",
|
2025-06-18 12:39:17 +10:00
|
|
|
((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0', id);
|
1999-07-08 22:12:37 +00:00
|
|
|
|
1999-06-30 01:33:11 +00:00
|
|
|
/*
|
2021-08-04 13:14:11 -07:00
|
|
|
* Look at the message flags. If it's a query, ignore it.
|
1999-06-30 01:33:11 +00:00
|
|
|
*/
|
1999-07-06 19:32:40 +00:00
|
|
|
if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
|
2021-08-04 13:14:11 -07:00
|
|
|
goto next;
|
2004-07-21 00:48:19 +00:00
|
|
|
}
|
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
/*
|
2020-12-16 01:32:06 -08:00
|
|
|
* The QID and the address must match the expected ones.
|
2008-06-23 19:41:20 +00:00
|
|
|
*/
|
2021-01-14 13:02:57 -08:00
|
|
|
if (resp->id != id || !isc_sockaddr_equal(&peer, &resp->peer)) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
|
|
|
"response doesn't match");
|
2021-05-25 22:54:17 -07:00
|
|
|
inc_stats(disp->mgr, dns_resstatscounter_mismatch);
|
2021-08-04 13:14:11 -07:00
|
|
|
goto next;
|
2020-11-25 12:45:47 +01:00
|
|
|
}
|
|
|
|
|
1999-07-08 22:12:37 +00:00
|
|
|
/*
|
2021-08-04 13:14:11 -07:00
|
|
|
* We have the right resp, so call the caller back.
|
1999-07-08 22:12:37 +00:00
|
|
|
*/
|
2021-08-04 13:14:11 -07:00
|
|
|
goto done;
|
1999-07-08 22:12:37 +00:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
next:
|
|
|
|
/*
|
Fix handling of mismatched responses past timeout
When a UDP dispatch receives a mismatched response, it checks whether
there is still enough time to wait for the correct one to arrive before
the timeout fires. If there is not, the result code is set to
ISC_R_TIMEDOUT, but it is not subsequently used anywhere as 'response'
is set to NULL a few lines earlier. This results in the higher-level
read callback (resquery_response() in case of resolver code) not being
called. However, shortly afterwards, a few levels up the call chain,
isc__nm_udp_read_cb() calls isc__nmsocket_timer_stop() on the dispatch
socket, effectively disabling read timeout handling for that socket.
Combined with the fact that reading is not restarted in such a case
(e.g. by calling dispatch_getnext() from udp_recv()), this leads to the
higher-level query structure remaining referenced indefinitely because
the dispatch socket it uses will neither be read from nor closed due to
a timeout. This in turn causes fetch contexts to linger around
indefinitely, which in turn i.a. prevents certain cache nodes (those
containing rdatasets used by fetch contexts, like fctx->nameservers)
from being cleaned.
Fix by making sure the higher-level callback does get invoked with the
ISC_R_TIMEDOUT result code when udp_recv() determines there is no more
time left to receive the correct UDP response before the timeout fires.
This allows the higher-level callback to clean things up, preventing the
reference leak described above.
2021-11-23 15:35:39 +01:00
|
|
|
* This is the wrong response. Check whether there is still enough
|
|
|
|
* time to wait for the correct one to arrive before the timeout fires.
|
2021-08-04 13:14:11 -07:00
|
|
|
*/
|
2023-05-27 19:20:47 -07:00
|
|
|
now = isc_loop_now(resp->loop);
|
2024-09-20 15:13:09 +02:00
|
|
|
if (resp->timeout > 0) {
|
|
|
|
timeout = resp->timeout - dispentry_runtime(resp, &now);
|
|
|
|
if (timeout <= 0) {
|
|
|
|
/*
|
|
|
|
* The time window for receiving the correct response is
|
|
|
|
* already closed, libuv has just not processed the
|
|
|
|
* socket timer yet. Invoke the read callback,
|
|
|
|
* indicating a timeout.
|
|
|
|
*/
|
|
|
|
eresult = ISC_R_TIMEDOUT;
|
|
|
|
goto done;
|
|
|
|
}
|
2021-10-01 12:53:31 -07:00
|
|
|
}
|
Fix handling of mismatched responses past timeout
When a UDP dispatch receives a mismatched response, it checks whether
there is still enough time to wait for the correct one to arrive before
the timeout fires. If there is not, the result code is set to
ISC_R_TIMEDOUT, but it is not subsequently used anywhere as 'response'
is set to NULL a few lines earlier. This results in the higher-level
read callback (resquery_response() in case of resolver code) not being
called. However, shortly afterwards, a few levels up the call chain,
isc__nm_udp_read_cb() calls isc__nmsocket_timer_stop() on the dispatch
socket, effectively disabling read timeout handling for that socket.
Combined with the fact that reading is not restarted in such a case
(e.g. by calling dispatch_getnext() from udp_recv()), this leads to the
higher-level query structure remaining referenced indefinitely because
the dispatch socket it uses will neither be read from nor closed due to
a timeout. This in turn causes fetch contexts to linger around
indefinitely, which in turn i.a. prevents certain cache nodes (those
containing rdatasets used by fetch contexts, like fctx->nameservers)
from being cleaned.
Fix by making sure the higher-level callback does get invoked with the
ISC_R_TIMEDOUT result code when udp_recv() determines there is no more
time left to receive the correct UDP response before the timeout fires.
This allows the higher-level callback to clean things up, preventing the
reference leak described above.
2021-11-23 15:35:39 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not invoke the read callback just yet and instead wait for the
|
|
|
|
* proper response to arrive until the original timeout fires.
|
|
|
|
*/
|
2023-02-22 11:04:12 -08:00
|
|
|
respond = false;
|
2022-11-30 17:58:35 +01:00
|
|
|
udp_dispatch_getnext(resp, timeout);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
done:
|
2023-02-22 11:04:12 -08:00
|
|
|
if (respond) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
|
|
|
"UDP read callback on %p: %s", handle,
|
|
|
|
isc_result_totext(eresult));
|
2023-02-22 11:04:12 -08:00
|
|
|
resp->response(eresult, region, resp->arg);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_detach(&resp); /* DISPENTRY003 */
|
1999-06-30 01:33:11 +00:00
|
|
|
}
|
|
|
|
|
2021-11-30 09:57:27 +01:00
|
|
|
static isc_result_t
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_recv_oldest(dns_dispatch_t *disp, dns_dispentry_t **respp) {
|
|
|
|
dns_dispentry_t *resp = NULL;
|
|
|
|
resp = ISC_LIST_HEAD(disp->active);
|
2021-11-30 09:57:27 +01:00
|
|
|
if (resp != NULL) {
|
|
|
|
disp->timedout++;
|
|
|
|
|
|
|
|
*respp = resp;
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_TIMEDOUT;
|
2021-11-30 09:57:27 +01:00
|
|
|
}
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_NOTFOUND;
|
2021-11-30 09:57:27 +01:00
|
|
|
}
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
/*
|
|
|
|
* NOTE: Must be RCU read locked!
|
|
|
|
*/
|
2021-11-26 09:14:58 +01:00
|
|
|
static isc_result_t
|
2023-09-14 18:01:39 +02:00
|
|
|
tcp_recv_success(dns_dispatch_t *disp, isc_region_t *region,
|
2021-11-26 09:14:58 +01:00
|
|
|
isc_sockaddr_t *peer, dns_dispentry_t **respp) {
|
|
|
|
isc_buffer_t source;
|
|
|
|
dns_messageid_t id;
|
|
|
|
unsigned int flags;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
|
|
|
"TCP read success, length == %d, addr = %p",
|
2021-11-26 09:14:58 +01:00
|
|
|
region->length, region->base);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Peek into the buffer to see what we can see.
|
|
|
|
*/
|
|
|
|
isc_buffer_init(&source, region->base, region->length);
|
|
|
|
isc_buffer_add(&source, region->length);
|
|
|
|
result = dns_message_peekheader(&source, &id, &flags);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(10), "got garbage packet");
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_UNEXPECTED;
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(92),
|
2021-11-26 09:14:58 +01:00
|
|
|
"got valid DNS message header, /QR %c, id %u",
|
2025-06-18 12:39:17 +10:00
|
|
|
((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0', id);
|
2021-11-26 09:14:58 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Look at the message flags. If it's a query, ignore it and keep
|
|
|
|
* reading.
|
|
|
|
*/
|
|
|
|
if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(10),
|
|
|
|
"got DNS query instead of answer");
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_UNEXPECTED;
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have a valid response; find the associated dispentry object
|
|
|
|
* and call the caller back.
|
|
|
|
*/
|
2023-09-14 18:01:39 +02:00
|
|
|
dns_dispentry_t key = {
|
|
|
|
.id = id,
|
|
|
|
.peer = *peer,
|
2023-09-15 15:59:28 +02:00
|
|
|
.port = isc_sockaddr_getport(&disp->local),
|
2023-09-14 18:01:39 +02:00
|
|
|
};
|
|
|
|
struct cds_lfht_iter iter;
|
|
|
|
cds_lfht_lookup(disp->mgr->qids, qid_hash(&key), qid_match, &key,
|
|
|
|
&iter);
|
|
|
|
|
|
|
|
dns_dispentry_t *resp = cds_lfht_entry(cds_lfht_iter_get_node(&iter),
|
|
|
|
dns_dispentry_t, ht_node);
|
2024-10-02 08:37:48 +02:00
|
|
|
|
|
|
|
/* Skip responses that are not ours */
|
|
|
|
if (resp != NULL && resp->disp == disp) {
|
2023-09-14 18:01:39 +02:00
|
|
|
if (!resp->reading) {
|
2023-02-22 11:04:12 -08:00
|
|
|
/*
|
|
|
|
* We already got a message for this QID and weren't
|
|
|
|
* expecting any more.
|
|
|
|
*/
|
2022-11-30 17:58:35 +01:00
|
|
|
result = ISC_R_UNEXPECTED;
|
2023-09-14 18:01:39 +02:00
|
|
|
} else {
|
|
|
|
*respp = resp;
|
2021-11-30 09:57:27 +01:00
|
|
|
}
|
2021-11-29 09:59:33 +01:00
|
|
|
} else {
|
2022-11-30 17:58:35 +01:00
|
|
|
result = ISC_R_NOTFOUND;
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
|
|
|
"search for response in hashtable: %s",
|
2023-09-14 18:01:39 +02:00
|
|
|
isc_result_totext(result));
|
2021-11-26 09:14:58 +01:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_recv_add(dns_displist_t *resps, dns_dispentry_t *resp,
|
|
|
|
isc_result_t result) {
|
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY009 */
|
|
|
|
ISC_LIST_UNLINK(resp->disp->active, resp, alink);
|
|
|
|
ISC_LIST_APPEND(*resps, resp, rlink);
|
|
|
|
INSIST(resp->reading);
|
|
|
|
resp->reading = false;
|
|
|
|
resp->result = result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
tcp_recv_shutdown(dns_dispatch_t *disp, dns_displist_t *resps,
|
|
|
|
isc_result_t result) {
|
2021-11-26 09:14:58 +01:00
|
|
|
/*
|
|
|
|
* If there are any active responses, shut them all down.
|
|
|
|
*/
|
2025-08-19 07:14:45 +02:00
|
|
|
ISC_LIST_FOREACH(disp->active, resp, alink) {
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_recv_add(resps, resp, result);
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
2022-12-20 06:11:26 +01:00
|
|
|
disp->state = DNS_DISPATCHSTATE_CANCELED;
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) {
|
2025-08-19 07:14:45 +02:00
|
|
|
ISC_LIST_FOREACH(*resps, resp, rlink) {
|
2021-11-26 09:14:58 +01:00
|
|
|
ISC_LIST_UNLINK(*resps, resp, rlink);
|
2023-02-21 20:14:30 -08:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "read callback: %s",
|
2023-02-21 20:14:30 -08:00
|
|
|
isc_result_totext(resp->result));
|
|
|
|
resp->response(resp->result, region, resp->arg);
|
|
|
|
dns_dispentry_detach(&resp); /* DISPENTRY009 */
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-12 23:44:31 +00:00
|
|
|
/*
|
|
|
|
* General flow:
|
|
|
|
*
|
2002-09-04 02:26:13 +00:00
|
|
|
* If I/O result == CANCELED, EOF, or error, notify everyone as the
|
|
|
|
* various queues drain.
|
1999-07-12 23:44:31 +00:00
|
|
|
*
|
|
|
|
* If response:
|
|
|
|
* Allocate event, fill in details.
|
2002-09-04 02:26:13 +00:00
|
|
|
* If cannot allocate, restart.
|
|
|
|
* find target. If not found, restart.
|
1999-07-12 23:44:31 +00:00
|
|
|
* if event queue is not empty, queue. else, send.
|
|
|
|
* restart.
|
|
|
|
*/
|
|
|
|
static void
|
2021-11-26 09:14:58 +01:00
|
|
|
tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
|
2021-01-14 13:02:57 -08:00
|
|
|
void *arg) {
|
2021-08-03 18:24:27 -07:00
|
|
|
dns_dispatch_t *disp = (dns_dispatch_t *)arg;
|
2021-11-26 09:14:58 +01:00
|
|
|
dns_dispentry_t *resp = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
char buf[ISC_SOCKADDR_FORMATSIZE];
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_sockaddr_t peer;
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_displist_t resps = ISC_LIST_INITIALIZER;
|
2023-05-27 19:20:47 -07:00
|
|
|
isc_time_t now;
|
2024-09-20 15:13:09 +02:00
|
|
|
int timeout = 0;
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
1999-11-16 21:05:09 +00:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
INSIST(disp->reading);
|
|
|
|
disp->reading = false;
|
2019-11-22 10:49:40 +11:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
|
|
|
"TCP read:%s:requests %" PRIuFAST32,
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(result), disp->requests);
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
peer = isc_nmhandle_peeraddr(handle);
|
2008-04-03 02:01:08 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
rcu_read_lock();
|
2022-11-30 17:58:35 +01:00
|
|
|
/*
|
|
|
|
* Phase 1: Process timeout and success.
|
|
|
|
*/
|
2021-11-26 09:14:58 +01:00
|
|
|
switch (result) {
|
2021-08-03 18:24:27 -07:00
|
|
|
case ISC_R_TIMEDOUT:
|
|
|
|
/*
|
2022-11-30 17:58:35 +01:00
|
|
|
* Time out the oldest response in the active queue.
|
2021-08-03 18:24:27 -07:00
|
|
|
*/
|
2022-11-30 17:58:35 +01:00
|
|
|
result = tcp_recv_oldest(disp, &resp);
|
2021-11-26 09:14:58 +01:00
|
|
|
break;
|
|
|
|
case ISC_R_SUCCESS:
|
|
|
|
/* We got an answer */
|
2023-09-14 18:01:39 +02:00
|
|
|
result = tcp_recv_success(disp, region, &peer, &resp);
|
2022-11-30 17:58:35 +01:00
|
|
|
break;
|
2021-11-30 09:57:27 +01:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp != NULL) {
|
|
|
|
tcp_recv_add(&resps, resp, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Phase 2: Look if we timed out before.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (result == ISC_R_NOTFOUND) {
|
|
|
|
if (disp->timedout > 0) {
|
|
|
|
/* There was active query that timed-out before */
|
|
|
|
disp->timedout--;
|
|
|
|
} else {
|
|
|
|
result = ISC_R_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Phase 3: Trigger timeouts. It's possible that the responses would
|
2023-02-21 20:14:30 -08:00
|
|
|
* have been timed out out already, but non-matching TCP reads have
|
2022-11-30 17:58:35 +01:00
|
|
|
* prevented this.
|
|
|
|
*/
|
2023-05-27 19:20:47 -07:00
|
|
|
resp = ISC_LIST_HEAD(disp->active);
|
|
|
|
if (resp != NULL) {
|
|
|
|
now = isc_loop_now(resp->loop);
|
|
|
|
}
|
|
|
|
while (resp != NULL) {
|
|
|
|
dns_dispentry_t *next = ISC_LIST_NEXT(resp, alink);
|
2022-11-30 17:58:35 +01:00
|
|
|
|
2024-09-20 15:13:09 +02:00
|
|
|
if (resp->timeout > 0) {
|
|
|
|
timeout = resp->timeout - dispentry_runtime(resp, &now);
|
|
|
|
if (timeout <= 0) {
|
|
|
|
tcp_recv_add(&resps, resp, ISC_R_TIMEDOUT);
|
|
|
|
}
|
2000-09-08 22:02:21 +00:00
|
|
|
}
|
2023-05-27 19:20:47 -07:00
|
|
|
|
|
|
|
resp = next;
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Phase 4: log if we errored out.
|
|
|
|
*/
|
|
|
|
switch (result) {
|
|
|
|
case ISC_R_SUCCESS:
|
|
|
|
case ISC_R_TIMEDOUT:
|
|
|
|
case ISC_R_NOTFOUND:
|
|
|
|
break;
|
2000-04-29 00:45:26 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case ISC_R_SHUTTINGDOWN:
|
|
|
|
case ISC_R_CANCELED:
|
|
|
|
case ISC_R_EOF:
|
|
|
|
case ISC_R_CONNECTIONRESET:
|
|
|
|
isc_sockaddr_format(&peer, buf, sizeof(buf));
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
|
|
|
"shutting down TCP: %s: %s", buf,
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(result));
|
|
|
|
tcp_recv_shutdown(disp, &resps, result);
|
|
|
|
break;
|
2021-11-26 09:14:58 +01:00
|
|
|
default:
|
2021-08-03 18:24:27 -07:00
|
|
|
isc_sockaddr_format(&peer, buf, sizeof(buf));
|
2021-11-26 09:14:58 +01:00
|
|
|
dispatch_log(disp, ISC_LOG_ERROR,
|
2021-08-03 18:24:27 -07:00
|
|
|
"shutting down due to TCP "
|
|
|
|
"receive error: %s: %s",
|
2021-11-26 09:14:58 +01:00
|
|
|
buf, isc_result_totext(result));
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_recv_shutdown(disp, &resps, result);
|
2021-11-26 09:14:58 +01:00
|
|
|
break;
|
2021-11-26 09:14:58 +01:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
/*
|
|
|
|
* Phase 5: Resume reading if there are still active responses
|
|
|
|
*/
|
2023-05-16 15:35:00 -07:00
|
|
|
resp = ISC_LIST_HEAD(disp->active);
|
|
|
|
if (resp != NULL) {
|
2024-09-20 15:13:09 +02:00
|
|
|
if (resp->timeout > 0) {
|
|
|
|
timeout = resp->timeout - dispentry_runtime(resp, &now);
|
|
|
|
INSIST(timeout > 0);
|
|
|
|
}
|
2023-05-16 15:35:00 -07:00
|
|
|
tcp_startrecv(disp, resp);
|
2024-09-20 15:13:09 +02:00
|
|
|
if (timeout > 0) {
|
|
|
|
isc_nmhandle_settimeout(handle, timeout);
|
|
|
|
}
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
rcu_read_unlock();
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
/*
|
|
|
|
* Phase 6: Process all scheduled callbacks.
|
|
|
|
*/
|
|
|
|
tcp_recv_processall(&resps, region);
|
2021-08-03 18:24:27 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_detach(&disp); /* DISPATCH002 */
|
2000-05-10 21:34:50 +00:00
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
/*%
|
|
|
|
* Create a temporary port list to set the initial default set of dispatch
|
2021-10-04 14:11:57 +02:00
|
|
|
* ephemeral ports. This is almost meaningless as the application will
|
2021-05-25 22:54:17 -07:00
|
|
|
* normally set the ports explicitly, but is provided to fill some minor corner
|
|
|
|
* cases.
|
2000-05-10 21:34:50 +00:00
|
|
|
*/
|
|
|
|
static void
|
2021-10-04 14:11:57 +02:00
|
|
|
create_default_portset(isc_mem_t *mctx, int family, isc_portset_t **portsetp) {
|
|
|
|
in_port_t low, high;
|
|
|
|
|
|
|
|
isc_net_getudpportrange(family, &low, &high);
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_portset_create(mctx, portsetp);
|
2021-10-04 14:11:57 +02:00
|
|
|
isc_portset_addrange(*portsetp, low, high);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2020-12-09 15:45:13 -08:00
|
|
|
static isc_result_t
|
|
|
|
setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
|
|
|
|
isc_portset_t *v6portset) {
|
|
|
|
in_port_t *v4ports, *v6ports, p = 0;
|
|
|
|
unsigned int nv4ports, nv6ports, i4 = 0, i6 = 0;
|
|
|
|
|
|
|
|
nv4ports = isc_portset_nports(v4portset);
|
|
|
|
nv6ports = isc_portset_nports(v6portset);
|
|
|
|
|
|
|
|
v4ports = NULL;
|
|
|
|
if (nv4ports != 0) {
|
2023-08-23 08:56:31 +02:00
|
|
|
v4ports = isc_mem_cget(mgr->mctx, nv4ports, sizeof(in_port_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-12-09 15:45:13 -08:00
|
|
|
v6ports = NULL;
|
|
|
|
if (nv6ports != 0) {
|
2023-08-23 08:56:31 +02:00
|
|
|
v6ports = isc_mem_cget(mgr->mctx, nv6ports, sizeof(in_port_t));
|
2020-12-09 15:45:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (isc_portset_isset(v4portset, p)) {
|
|
|
|
INSIST(i4 < nv4ports);
|
|
|
|
v4ports[i4++] = p;
|
|
|
|
}
|
|
|
|
if (isc_portset_isset(v6portset, p)) {
|
|
|
|
INSIST(i6 < nv6ports);
|
|
|
|
v6ports[i6++] = p;
|
|
|
|
}
|
|
|
|
} while (p++ < 65535);
|
|
|
|
INSIST(i4 == nv4ports && i6 == nv6ports);
|
|
|
|
|
|
|
|
if (mgr->v4ports != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(mgr->mctx, mgr->v4ports, mgr->nv4ports,
|
|
|
|
sizeof(in_port_t));
|
2020-12-09 15:45:13 -08:00
|
|
|
}
|
|
|
|
mgr->v4ports = v4ports;
|
|
|
|
mgr->nv4ports = nv4ports;
|
|
|
|
|
|
|
|
if (mgr->v6ports != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(mgr->mctx, mgr->v6ports, mgr->nv6ports,
|
|
|
|
sizeof(in_port_t));
|
2020-12-09 15:45:13 -08:00
|
|
|
}
|
|
|
|
mgr->v6ports = v6ports;
|
|
|
|
mgr->nv6ports = nv6ports;
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
1999-06-30 01:33:11 +00:00
|
|
|
/*
|
|
|
|
* Publics.
|
|
|
|
*/
|
|
|
|
|
1999-07-22 01:34:31 +00:00
|
|
|
isc_result_t
|
2025-07-14 17:12:35 +02:00
|
|
|
dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) {
|
2020-12-09 15:45:13 -08:00
|
|
|
dns_dispatchmgr_t *mgr = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_portset_t *v4portset = NULL;
|
|
|
|
isc_portset_t *v6portset = NULL;
|
2000-05-10 21:34:50 +00:00
|
|
|
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(mgrp != NULL && *mgrp == NULL);
|
|
|
|
|
|
|
|
mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
|
2023-09-15 14:38:02 +02:00
|
|
|
*mgr = (dns_dispatchmgr_t){
|
|
|
|
.magic = 0,
|
2025-07-14 10:50:21 +02:00
|
|
|
.nloops = isc_loopmgr_nloops(),
|
2023-09-15 14:38:02 +02:00
|
|
|
};
|
2021-01-14 13:02:57 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
fprintf(stderr, "dns_dispatchmgr__init:%s:%s:%d:%p->references = 1\n",
|
|
|
|
__func__, __FILE__, __LINE__, mgr);
|
|
|
|
#endif
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_refcount_init(&mgr->references, 1);
|
2000-05-10 21:34:50 +00:00
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
isc_mem_attach(mctx, &mgr->mctx);
|
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
mgr->tcps = isc_mem_cget(mgr->mctx, mgr->nloops, sizeof(mgr->tcps[0]));
|
|
|
|
for (size_t i = 0; i < mgr->nloops; i++) {
|
|
|
|
mgr->tcps[i] = cds_lfht_new(
|
|
|
|
2, 2, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
|
|
|
|
NULL);
|
|
|
|
}
|
2021-05-12 21:16:17 +02:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
create_default_portset(mgr->mctx, AF_INET, &v4portset);
|
|
|
|
create_default_portset(mgr->mctx, AF_INET6, &v6portset);
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2020-12-09 15:45:13 -08:00
|
|
|
setavailports(mgr, v4portset, v6portset);
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
isc_portset_destroy(mgr->mctx, &v4portset);
|
|
|
|
isc_portset_destroy(mgr->mctx, &v6portset);
|
|
|
|
|
|
|
|
mgr->qids = cds_lfht_new(QIDS_INIT_SIZE, QIDS_MIN_SIZE, 0,
|
|
|
|
CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
|
|
|
|
NULL);
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2020-12-09 15:45:13 -08:00
|
|
|
mgr->magic = DNS_DISPATCHMGR_MAGIC;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2020-12-09 15:45:13 -08:00
|
|
|
*mgrp = mgr;
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2000-05-10 21:34:50 +00:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(dns_dispatchmgr, dispatchmgr_destroy);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_IMPL(dns_dispatchmgr, dispatchmgr_destroy);
|
|
|
|
#endif
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2000-11-03 02:45:55 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) {
|
2000-11-03 02:45:55 +00:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
2020-02-13 21:48:23 +01:00
|
|
|
if (mgr->blackhole != NULL) {
|
2000-12-26 09:48:41 +00:00
|
|
|
dns_acl_detach(&mgr->blackhole);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-11-03 02:45:55 +00:00
|
|
|
dns_acl_attach(blackhole, &mgr->blackhole);
|
|
|
|
}
|
|
|
|
|
2001-02-09 00:23:16 +00:00
|
|
|
dns_acl_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr) {
|
2000-11-03 02:45:55 +00:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
2024-11-19 10:38:03 +01:00
|
|
|
return mgr->blackhole;
|
2000-11-03 02:45:55 +00:00
|
|
|
}
|
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_portset_t *v6portset) {
|
2008-06-23 19:41:20 +00:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
2024-11-19 10:38:03 +01:00
|
|
|
return setavailports(mgr, v4portset, v6portset);
|
2003-02-26 05:05:16 +00:00
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
static void
|
|
|
|
dispatchmgr_destroy(dns_dispatchmgr_t *mgr) {
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_refcount_destroy(&mgr->references);
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
mgr->magic = 0;
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
RUNTIME_CHECK(!cds_lfht_destroy(mgr->qids, NULL));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
for (size_t i = 0; i < mgr->nloops; i++) {
|
|
|
|
RUNTIME_CHECK(!cds_lfht_destroy(mgr->tcps[i], NULL));
|
|
|
|
}
|
|
|
|
isc_mem_cput(mgr->mctx, mgr->tcps, mgr->nloops, sizeof(mgr->tcps[0]));
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (mgr->blackhole != NULL) {
|
|
|
|
dns_acl_detach(&mgr->blackhole);
|
|
|
|
}
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (mgr->stats != NULL) {
|
|
|
|
isc_stats_detach(&mgr->stats);
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (mgr->v4ports != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(mgr->mctx, mgr->v4ports, mgr->nv4ports,
|
|
|
|
sizeof(in_port_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-05-25 22:54:17 -07:00
|
|
|
if (mgr->v6ports != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(mgr->mctx, mgr->v6ports, mgr->nv6ports,
|
|
|
|
sizeof(in_port_t));
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(dns_dispatchmgr_t));
|
2000-05-10 21:34:50 +00:00
|
|
|
}
|
|
|
|
|
2008-04-03 05:55:52 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
|
2008-04-03 05:55:52 +00:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
|
|
|
REQUIRE(mgr->stats == NULL);
|
|
|
|
|
2009-01-27 22:30:00 +00:00
|
|
|
isc_stats_attach(stats, &mgr->stats);
|
2008-04-03 05:55:52 +00:00
|
|
|
}
|
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
/*
|
|
|
|
* Allocate and set important limits.
|
|
|
|
*/
|
2020-12-18 14:59:50 -08:00
|
|
|
static void
|
2025-06-04 17:54:20 +02:00
|
|
|
dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, isc_tid_t tid,
|
2021-08-03 18:24:27 -07:00
|
|
|
dns_dispatch_t **dispp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2000-05-10 21:34:50 +00:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
1999-06-18 23:54:59 +00:00
|
|
|
REQUIRE(dispp != NULL && *dispp == NULL);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
/*
|
|
|
|
* Set up the dispatcher, mostly. Don't bother setting some of
|
|
|
|
* the options that are controlled by tcp vs. udp, etc.
|
|
|
|
*/
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2021-05-12 21:16:17 +02:00
|
|
|
disp = isc_mem_get(mgr->mctx, sizeof(*disp));
|
2022-11-30 17:58:35 +01:00
|
|
|
*disp = (dns_dispatch_t){
|
|
|
|
.socktype = type,
|
|
|
|
.active = ISC_LIST_INITIALIZER,
|
|
|
|
.pending = ISC_LIST_INITIALIZER,
|
2023-09-15 11:36:28 +02:00
|
|
|
.tid = tid,
|
2022-11-30 17:58:35 +01:00
|
|
|
.magic = DISPATCH_MAGIC,
|
|
|
|
};
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
isc_mem_attach(mgr->mctx, &disp->mctx);
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispatchmgr_attach(mgr, &disp->mgr);
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
fprintf(stderr, "dns_dispatch__init:%s:%s:%d:%p->references = 1\n",
|
|
|
|
__func__, __FILE__, __LINE__, disp);
|
|
|
|
#endif
|
|
|
|
isc_refcount_init(&disp->references, 1); /* DISPATCH000 */
|
2021-05-25 22:54:17 -07:00
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
*dispp = disp;
|
|
|
|
}
|
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
struct dispatch_key {
|
|
|
|
const isc_sockaddr_t *local;
|
|
|
|
const isc_sockaddr_t *peer;
|
2024-10-15 16:09:48 +11:00
|
|
|
const dns_transport_t *transport;
|
2023-09-15 14:38:02 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
dispatch_hash(struct dispatch_key *key) {
|
|
|
|
uint32_t hashval = isc_sockaddr_hash(key->peer, false);
|
|
|
|
if (key->local) {
|
|
|
|
hashval ^= isc_sockaddr_hash(key->local, true);
|
|
|
|
}
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return hashval;
|
2023-09-15 14:38:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dispatch_match(struct cds_lfht_node *node, const void *key0) {
|
|
|
|
dns_dispatch_t *disp = caa_container_of(node, dns_dispatch_t, ht_node);
|
|
|
|
const struct dispatch_key *key = key0;
|
|
|
|
|
Improve reuse of outgoing TCP connections
The dns_dispatch_gettcp() function is used for finding an existing TCP
connection that can be reused for sending a query from a specified local
address to a specified remote address. The logic for matching the
provided <local address, remote address> tuple to one of the existing
TCP connections is implemented in the dispatch_match() function:
- if the examined TCP connection already has a libuv handle assigned,
it means the connection has already been established; therefore,
compare the provided <local address, remote address> tuple against
the corresponding address tuple for the libuv handle associated with
the connection,
- if the examined TCP connection does not yet have a libuv handle
assigned, it means the connection has not yet been established;
therefore, compare the provided <local address, remote address>
tuple against the corresponding address tuple that the TCP
connection was originally created for.
This logic limits TCP connection reuse potential as the libuv handle
assigned to an existing dispatch object may have a more specific local
<address, port> tuple associated with it than the local <address, port>
tuple that the dispatch object was originally created for. That's
because the local address for outgoing connections can be set to a
wildcard <address, port> tuple (indicating that the caller does not care
what source <address, port> tuple will be used for establishing the
connection, thereby delegating the task of picking it to the operating
system) and then get "upgraded" to a specific <address, port> tuple when
the socket is bound (and a libuv handle gets associated with it). When
another dns_dispatch_gettcp() caller then tries to look for an existing
TCP connection to the same peer and passes a wildcard address in the
local part of the tuple, the function will not match that request to a
previously-established TCP connection (unless isc_nmhandle_localaddr()
returns a wildcard address as well).
Simplify dispatch_match() so that the libuv handle associated with an
existing dispatch object is not examined for the purpose of matching it
to the provided <local address, remote address> tuple; instead, always
examine the <local address, remote address> tuple that the dispatch
object was originally created for. This enables reuse of TCP
connections created without providing a specific local socket address
while still preventing other connections (created for a specific local
socket address) from being inadvertently shared.
2024-12-29 10:22:20 +01:00
|
|
|
return disp->transport == key->transport &&
|
|
|
|
isc_sockaddr_equal(&disp->peer, key->peer) &&
|
|
|
|
(key->local == NULL ||
|
|
|
|
isc_sockaddr_equal(&disp->local, key->local));
|
2023-09-15 14:38:02 +02:00
|
|
|
}
|
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
|
2023-10-20 08:14:27 +02:00
|
|
|
const isc_sockaddr_t *destaddr,
|
2024-10-15 16:09:48 +11:00
|
|
|
dns_transport_t *transport, dns_dispatchopt_t options,
|
|
|
|
dns_dispatch_t **dispp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid = isc_tid();
|
2000-09-19 06:59:28 +00:00
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
2020-12-18 14:59:50 -08:00
|
|
|
REQUIRE(destaddr != NULL);
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
dispatch_allocate(mgr, isc_socktype_tcp, tid, &disp);
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2023-10-20 08:14:27 +02:00
|
|
|
disp->options = options;
|
2020-12-18 14:59:50 -08:00
|
|
|
disp->peer = *destaddr;
|
2024-10-15 16:09:48 +11:00
|
|
|
if (transport != NULL) {
|
|
|
|
dns_transport_attach(transport, &disp->transport);
|
|
|
|
}
|
2020-12-18 14:59:50 -08:00
|
|
|
|
|
|
|
if (localaddr != NULL) {
|
|
|
|
disp->local = *localaddr;
|
|
|
|
} else {
|
2021-08-03 18:24:27 -07:00
|
|
|
int pf;
|
|
|
|
pf = isc_sockaddr_pf(destaddr);
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_sockaddr_anyofpf(&disp->local, pf);
|
|
|
|
isc_sockaddr_setport(&disp->local, 0);
|
2020-12-16 01:32:06 -08:00
|
|
|
}
|
|
|
|
|
2000-05-10 21:34:50 +00:00
|
|
|
/*
|
|
|
|
* Append it to the dispatcher list.
|
|
|
|
*/
|
2023-09-15 14:38:02 +02:00
|
|
|
struct dispatch_key key = {
|
|
|
|
.local = &disp->local,
|
|
|
|
.peer = &disp->peer,
|
2024-10-15 16:09:48 +11:00
|
|
|
.transport = transport,
|
2023-09-15 14:38:02 +02:00
|
|
|
};
|
2021-08-03 18:24:27 -07:00
|
|
|
|
2023-10-20 08:14:27 +02:00
|
|
|
if ((disp->options & DNS_DISPATCHOPT_UNSHARED) == 0) {
|
|
|
|
rcu_read_lock();
|
|
|
|
cds_lfht_add(mgr->tcps[tid], dispatch_hash(&key),
|
|
|
|
&disp->ht_node);
|
|
|
|
rcu_read_unlock();
|
|
|
|
}
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
if (isc_log_wouldlog(90)) {
|
2022-11-30 17:58:35 +01:00
|
|
|
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2022-12-28 12:10:09 +00:00
|
|
|
isc_sockaddr_format(&disp->local, addrbuf,
|
2022-11-30 17:58:35 +01:00
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
mgr_log(mgr, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"dns_dispatch_createtcp: created TCP dispatch %p for "
|
|
|
|
"%s",
|
|
|
|
disp, addrbuf);
|
|
|
|
}
|
|
|
|
*dispp = disp;
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
2014-09-04 10:37:45 +10:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
|
2024-10-15 16:09:48 +11:00
|
|
|
const isc_sockaddr_t *localaddr, dns_transport_t *transport,
|
|
|
|
dns_dispatch_t **dispp) {
|
2021-08-04 13:14:11 -07:00
|
|
|
dns_dispatch_t *disp_connected = NULL;
|
|
|
|
dns_dispatch_t *disp_fallback = NULL;
|
|
|
|
isc_result_t result = ISC_R_NOTFOUND;
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid = isc_tid();
|
2015-01-20 17:22:31 -08:00
|
|
|
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
|
|
|
REQUIRE(destaddr != NULL);
|
|
|
|
REQUIRE(dispp != NULL && *dispp == NULL);
|
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
struct dispatch_key key = {
|
|
|
|
.local = localaddr,
|
|
|
|
.peer = destaddr,
|
2024-10-15 16:09:48 +11:00
|
|
|
.transport = transport,
|
2023-09-15 14:38:02 +02:00
|
|
|
};
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
rcu_read_lock();
|
|
|
|
struct cds_lfht_iter iter;
|
|
|
|
dns_dispatch_t *disp = NULL;
|
|
|
|
cds_lfht_for_each_entry_duplicate(mgr->tcps[tid], dispatch_hash(&key),
|
|
|
|
dispatch_match, &key, &iter, disp,
|
|
|
|
ht_node) {
|
|
|
|
INSIST(disp->tid == isc_tid());
|
|
|
|
INSIST(disp->socktype == isc_socktype_tcp);
|
2022-12-20 06:11:26 +01:00
|
|
|
|
|
|
|
switch (disp->state) {
|
|
|
|
case DNS_DISPATCHSTATE_NONE:
|
|
|
|
/* A dispatch in indeterminate state, skip it */
|
|
|
|
break;
|
|
|
|
case DNS_DISPATCHSTATE_CONNECTED:
|
|
|
|
if (ISC_LIST_EMPTY(disp->active)) {
|
|
|
|
/* Ignore dispatch with no responses */
|
2022-11-30 17:58:35 +01:00
|
|
|
break;
|
2022-12-20 06:11:26 +01:00
|
|
|
}
|
|
|
|
/* We found a connected dispatch */
|
|
|
|
dns_dispatch_attach(disp, &disp_connected);
|
|
|
|
break;
|
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
|
|
|
if (ISC_LIST_EMPTY(disp->pending)) {
|
|
|
|
/* Ignore dispatch with no responses */
|
2022-11-30 17:58:35 +01:00
|
|
|
break;
|
2021-08-04 13:14:11 -07:00
|
|
|
}
|
2022-12-20 06:11:26 +01:00
|
|
|
/* We found "a" dispatch, store it for later */
|
|
|
|
if (disp_fallback == NULL) {
|
|
|
|
dns_dispatch_attach(disp, &disp_fallback);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DNS_DISPATCHSTATE_CANCELED:
|
|
|
|
/* A canceled dispatch, skip it. */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2021-08-04 13:14:11 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (disp_connected != NULL) {
|
|
|
|
break;
|
|
|
|
}
|
2015-01-20 17:22:31 -08:00
|
|
|
}
|
2023-09-15 14:38:02 +02:00
|
|
|
rcu_read_unlock();
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (disp_connected != NULL) {
|
|
|
|
/* We found connected dispatch */
|
|
|
|
INSIST(disp_connected->handle != NULL);
|
2015-01-20 17:22:31 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
*dispp = disp_connected;
|
|
|
|
disp_connected = NULL;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (disp_fallback != NULL) {
|
|
|
|
dns_dispatch_detach(&disp_fallback);
|
|
|
|
}
|
|
|
|
} else if (disp_fallback != NULL) {
|
|
|
|
*dispp = disp_fallback;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
|
|
|
result = ISC_R_SUCCESS;
|
2015-01-20 17:22:31 -08:00
|
|
|
}
|
2020-12-18 14:59:50 -08:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2015-01-20 17:22:31 -08:00
|
|
|
}
|
|
|
|
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
|
2021-08-03 18:24:27 -07:00
|
|
|
dns_dispatch_t **dispp) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2007-02-02 02:18:06 +00:00
|
|
|
dns_dispatch_t *disp = NULL;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
|
|
|
REQUIRE(localaddr != NULL);
|
|
|
|
REQUIRE(dispp != NULL && *dispp == NULL);
|
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
result = dispatch_createudp(mgr, localaddr, isc_tid(), &disp);
|
2020-12-16 01:32:06 -08:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
*dispp = disp;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
}
|
2020-12-18 14:59:50 -08:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid, dns_dispatch_t **dispp) {
|
2020-12-18 14:59:50 -08:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2020-12-16 01:32:06 -08:00
|
|
|
isc_sockaddr_t sa_any;
|
2018-11-08 19:34:51 -08:00
|
|
|
|
2020-12-16 01:32:06 -08:00
|
|
|
/*
|
2021-01-14 13:02:57 -08:00
|
|
|
* Check whether this address/port is available locally.
|
2020-12-16 01:32:06 -08:00
|
|
|
*/
|
2021-08-03 18:24:27 -07:00
|
|
|
isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
|
2020-12-16 01:32:06 -08:00
|
|
|
if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
|
2021-01-14 13:02:57 -08:00
|
|
|
result = isc_nm_checkaddr(localaddr, isc_socktype_udp);
|
2018-11-08 19:34:51 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2018-11-08 19:34:51 -08:00
|
|
|
}
|
2020-12-16 01:32:06 -08:00
|
|
|
}
|
2011-07-28 04:04:37 +00:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
dispatch_allocate(mgr, isc_socktype_udp, tid, &disp);
|
2022-11-30 17:58:35 +01:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
if (isc_log_wouldlog(90)) {
|
2020-12-16 01:32:06 -08:00
|
|
|
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
2008-11-12 23:10:57 +00:00
|
|
|
|
2020-12-16 01:32:06 -08:00
|
|
|
isc_sockaddr_format(localaddr, addrbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
2023-09-15 15:59:28 +02:00
|
|
|
mgr_log(mgr, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"dispatch_createudp: created UDP dispatch %p for %s",
|
|
|
|
disp, addrbuf);
|
2003-02-26 05:05:16 +00:00
|
|
|
}
|
2020-12-16 01:32:06 -08:00
|
|
|
|
2001-01-07 22:02:48 +00:00
|
|
|
disp->local = *localaddr;
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
|
|
|
|
/*
|
2022-11-30 17:58:35 +01:00
|
|
|
* Don't append it to the dispatcher list, we don't care about UDP, only
|
|
|
|
* TCP should be searched
|
|
|
|
*
|
|
|
|
* ISC_LIST_APPEND(mgr->list, disp, link);
|
Merge the mlg-20000518 branch onto the mainline. Change summary:
dns_dispatch_create() no longer exists. dns_dispatch_createtcp()
and dns_dispatch_getudp() are the replacements. _createtcp() takes
a bound, connected TCP socket, while _getudp() will search for
a sharable UDP socket, and if found, attach to it and return a
pointer to it. If one is not found, it will create a udp socket,
bind it to a supplied local address, and create a new dispatcher
around it.
dns_dispatch_remove{request,response}() no longer take the dispatch
as an argument.
query-source can now be set per view.
The dispatch manager holds onto three memory pools, one for
allocating dispatchers from, one for events, and one for
requests/replies. The free list on these pools is hard-coded,
but set to 1024. This keeps us from having to dig into the
isc_mem_t the pools draw from as often.
dns_resolver_create() and dns_view_createresolver() require that
valid dispatchers be passed in; dispatchers are no longer created
for the caller.
2000-05-19 21:46:46 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
*dispp = disp;
|
2011-07-28 04:04:37 +00:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
1999-06-16 01:32:31 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
static void
|
|
|
|
dispatch_destroy_rcu(struct rcu_head *rcu_head) {
|
|
|
|
dns_dispatch_t *disp = caa_container_of(rcu_head, dns_dispatch_t,
|
|
|
|
rcu_head);
|
|
|
|
|
|
|
|
isc_mem_putanddetach(&disp->mctx, disp, sizeof(*disp));
|
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
static void
|
2021-08-03 18:24:27 -07:00
|
|
|
dispatch_destroy(dns_dispatch_t *disp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispatchmgr_t *mgr = disp->mgr;
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid = isc_tid();
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
disp->magic = 0;
|
|
|
|
|
2023-10-20 08:14:27 +02:00
|
|
|
if (disp->socktype == isc_socktype_tcp &&
|
|
|
|
(disp->options & DNS_DISPATCHOPT_UNSHARED) == 0)
|
|
|
|
{
|
2023-09-15 14:38:02 +02:00
|
|
|
(void)cds_lfht_del(mgr->tcps[tid], &disp->ht_node);
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
INSIST(disp->requests == 0);
|
|
|
|
INSIST(ISC_LIST_EMPTY(disp->pending));
|
|
|
|
INSIST(ISC_LIST_EMPTY(disp->active));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90), "destroying dispatch %p", disp);
|
2022-11-30 17:58:35 +01:00
|
|
|
|
|
|
|
if (disp->handle) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
|
|
|
"detaching TCP handle %p from %p", disp->handle,
|
|
|
|
&disp->handle);
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nmhandle_detach(&disp->handle);
|
|
|
|
}
|
2024-10-15 16:09:48 +11:00
|
|
|
if (disp->transport != NULL) {
|
|
|
|
dns_transport_detach(&disp->transport);
|
|
|
|
}
|
2023-09-15 14:38:02 +02:00
|
|
|
dns_dispatchmgr_detach(&disp->mgr);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
call_rcu(&disp->rcu_head, dispatch_destroy_rcu);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(dns_dispatch, dispatch_destroy);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_IMPL(dns_dispatch, dispatch_destroy);
|
|
|
|
#endif
|
1999-06-16 01:32:31 +00:00
|
|
|
|
1999-07-22 01:34:31 +00:00
|
|
|
isc_result_t
|
2023-10-20 08:14:27 +02:00
|
|
|
dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop,
|
2024-10-30 09:23:33 +00:00
|
|
|
dns_dispatchopt_t options, unsigned int connect_timeout,
|
|
|
|
unsigned int timeout, const isc_sockaddr_t *dest,
|
|
|
|
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
|
|
|
|
dispatch_cb_t connected, dispatch_cb_t sent,
|
|
|
|
dispatch_cb_t response, void *arg, dns_messageid_t *idp,
|
|
|
|
dns_dispentry_t **respp) {
|
1999-06-18 02:01:42 +00:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
REQUIRE(dest != NULL);
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(respp != NULL && *respp == NULL);
|
1999-06-18 02:01:42 +00:00
|
|
|
REQUIRE(idp != NULL);
|
2021-01-14 13:02:57 -08:00
|
|
|
REQUIRE(disp->socktype == isc_socktype_tcp ||
|
|
|
|
disp->socktype == isc_socktype_udp);
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(connected != NULL);
|
|
|
|
REQUIRE(response != NULL);
|
|
|
|
REQUIRE(sent != NULL);
|
2023-05-27 19:20:47 -07:00
|
|
|
REQUIRE(loop != NULL);
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2024-10-15 16:09:48 +11:00
|
|
|
REQUIRE(disp->transport == transport);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (disp->state == DNS_DISPATCHSTATE_CANCELED) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_CANCELED;
|
1999-07-09 02:47:55 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
in_port_t localport = isc_sockaddr_getport(&disp->local);
|
|
|
|
dns_dispentry_t *resp = isc_mem_get(disp->mctx, sizeof(*resp));
|
2022-11-30 17:58:35 +01:00
|
|
|
*resp = (dns_dispentry_t){
|
2024-10-30 09:23:33 +00:00
|
|
|
.connect_timeout = connect_timeout,
|
2022-11-30 17:58:35 +01:00
|
|
|
.timeout = timeout,
|
2024-10-01 14:16:47 +00:00
|
|
|
.port = localport,
|
2022-11-30 17:58:35 +01:00
|
|
|
.peer = *dest,
|
2023-05-27 19:20:47 -07:00
|
|
|
.loop = loop,
|
2022-11-30 17:58:35 +01:00
|
|
|
.connected = connected,
|
|
|
|
.sent = sent,
|
|
|
|
.response = response,
|
|
|
|
.arg = arg,
|
|
|
|
.alink = ISC_LINK_INITIALIZER,
|
|
|
|
.plink = ISC_LINK_INITIALIZER,
|
|
|
|
.rlink = ISC_LINK_INITIALIZER,
|
|
|
|
.magic = RESPONSE_MAGIC,
|
|
|
|
};
|
|
|
|
|
|
|
|
#if DNS_DISPATCH_TRACE
|
|
|
|
fprintf(stderr, "dns_dispentry__init:%s:%s:%d:%p->references = 1\n",
|
2023-05-16 15:35:00 -07:00
|
|
|
__func__, __FILE__, __LINE__, resp);
|
2022-11-30 17:58:35 +01:00
|
|
|
#endif
|
|
|
|
isc_refcount_init(&resp->references, 1); /* DISPENTRY000 */
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
if (disp->socktype == isc_socktype_udp) {
|
2023-09-15 15:59:28 +02:00
|
|
|
isc_result_t result = setup_socket(disp, resp, dest,
|
|
|
|
&localport);
|
2008-06-23 19:41:20 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-09-15 14:38:02 +02:00
|
|
|
isc_mem_put(disp->mctx, resp, sizeof(*resp));
|
2009-01-31 00:10:24 +00:00
|
|
|
inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
isc_result_t result = ISC_R_NOMORE;
|
|
|
|
size_t i = 0;
|
2023-09-14 18:01:39 +02:00
|
|
|
rcu_read_lock();
|
2014-01-09 15:57:59 +11:00
|
|
|
do {
|
2023-09-14 18:01:39 +02:00
|
|
|
/*
|
|
|
|
* Try somewhat hard to find a unique ID. Start with
|
|
|
|
* a random number unless DNS_DISPATCHOPT_FIXEDID is set,
|
|
|
|
* in which case we start with the ID passed in via *idp.
|
|
|
|
*/
|
|
|
|
resp->id = ((options & DNS_DISPATCHOPT_FIXEDID) != 0)
|
|
|
|
? *idp
|
|
|
|
: (dns_messageid_t)isc_random16();
|
|
|
|
|
|
|
|
struct cds_lfht_node *node =
|
|
|
|
cds_lfht_add_unique(disp->mgr->qids, qid_hash(resp),
|
|
|
|
qid_match, resp, &resp->ht_node);
|
|
|
|
|
|
|
|
if (node != &resp->ht_node) {
|
|
|
|
if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
|
|
|
|
/*
|
|
|
|
* When using fixed ID, we either must
|
|
|
|
* use it or fail
|
|
|
|
*/
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result = ISC_R_SUCCESS;
|
2022-11-30 17:58:35 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-09-14 18:01:39 +02:00
|
|
|
} while (i++ < QID_MAX_TRIES);
|
|
|
|
fail:
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-09-15 14:38:02 +02:00
|
|
|
isc_mem_put(disp->mctx, resp, sizeof(*resp));
|
2024-09-27 12:48:22 +00:00
|
|
|
rcu_read_unlock();
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
1999-06-18 02:01:42 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 14:38:02 +02:00
|
|
|
isc_mem_attach(disp->mctx, &resp->mctx);
|
2023-09-14 18:01:39 +02:00
|
|
|
|
2022-09-19 11:04:22 +00:00
|
|
|
if (transport != NULL) {
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_transport_attach(transport, &resp->transport);
|
2022-09-19 11:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsctx_cache != NULL) {
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_tlsctx_cache_attach(tlsctx_cache, &resp->tlsctx_cache);
|
2022-09-19 11:04:22 +00:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_attach(disp, &resp->disp); /* DISPATCH001 */
|
1999-06-18 02:01:42 +00:00
|
|
|
|
1999-07-09 00:51:08 +00:00
|
|
|
disp->requests++;
|
2020-12-09 19:44:41 -08:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
inc_stats(disp->mgr, (disp->socktype == isc_socktype_udp)
|
|
|
|
? dns_resstatscounter_disprequdp
|
|
|
|
: dns_resstatscounter_dispreqtcp);
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
rcu_read_unlock();
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
*idp = resp->id;
|
2022-11-30 17:58:35 +01:00
|
|
|
*respp = resp;
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
1999-06-16 01:32:31 +00:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_t
|
|
|
|
dns_dispatch_getnext(dns_dispentry_t *resp) {
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
2021-08-03 18:24:27 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2024-10-30 13:31:34 +00:00
|
|
|
int64_t timeout = 0;
|
2021-11-30 09:57:27 +01:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "getnext for QID %d", resp->id);
|
2023-02-22 11:04:12 -08:00
|
|
|
|
2024-09-20 15:13:09 +02:00
|
|
|
if (resp->timeout > 0) {
|
|
|
|
isc_time_t now = isc_loop_now(resp->loop);
|
|
|
|
timeout = resp->timeout - dispentry_runtime(resp, &now);
|
|
|
|
if (timeout <= 0) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_TIMEDOUT;
|
2024-09-20 15:13:09 +02:00
|
|
|
}
|
2023-05-16 15:35:00 -07:00
|
|
|
}
|
|
|
|
|
2024-10-30 13:31:34 +00:00
|
|
|
INSIST(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (disp->socktype) {
|
2023-05-16 15:35:00 -07:00
|
|
|
case isc_socktype_udp:
|
2022-11-30 17:58:35 +01:00
|
|
|
udp_dispatch_getnext(resp, timeout);
|
2021-08-03 18:24:27 -07:00
|
|
|
break;
|
|
|
|
case isc_socktype_tcp:
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_dispatch_getnext(disp, resp, timeout);
|
2021-08-03 18:24:27 -07:00
|
|
|
break;
|
|
|
|
default:
|
2021-10-11 12:50:17 +02:00
|
|
|
UNREACHABLE();
|
2021-08-03 18:24:27 -07:00
|
|
|
}
|
2016-07-11 13:36:16 +10:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
/*
|
|
|
|
* NOTE: Must be RCU read locked!
|
|
|
|
*/
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
|
|
|
udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
|
2016-07-11 13:36:16 +10:00
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(resp->disp->mgr));
|
2016-07-11 13:36:16 +10:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
2023-02-22 11:04:12 -08:00
|
|
|
bool respond = false;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"canceling response: %s, %s/%s (%s/%s), "
|
2023-09-15 11:36:28 +02:00
|
|
|
"requests %" PRIuFAST32,
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(result), state2str(resp->state),
|
|
|
|
resp->reading ? "reading" : "not reading",
|
|
|
|
state2str(disp->state),
|
|
|
|
disp->reading ? "reading" : "not reading",
|
|
|
|
disp->requests);
|
2016-07-11 13:36:16 +10:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (ISC_LINK_LINKED(resp, alink)) {
|
|
|
|
ISC_LIST_UNLINK(disp->active, resp, alink);
|
2021-10-01 12:53:31 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (resp->state) {
|
|
|
|
case DNS_DISPATCHSTATE_NONE:
|
|
|
|
break;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
|
|
|
break;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTED:
|
|
|
|
if (resp->reading) {
|
2023-02-22 11:04:12 -08:00
|
|
|
respond = true;
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
|
|
|
"canceling read on %p", resp->handle);
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_nm_cancelread(resp->handle);
|
|
|
|
}
|
|
|
|
break;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CANCELED:
|
|
|
|
goto unlock;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2021-10-03 15:15:50 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dec_stats(disp->mgr, dns_resstatscounter_disprequdp);
|
2021-10-03 15:15:50 -07:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
(void)cds_lfht_del(disp->mgr->qids, &resp->ht_node);
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
resp->state = DNS_DISPATCHSTATE_CANCELED;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
unlock:
|
2023-02-22 11:04:12 -08:00
|
|
|
if (respond) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "read callback: %s",
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(result));
|
2023-02-22 11:04:12 -08:00
|
|
|
resp->response(result, NULL, resp->arg);
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
2021-10-03 15:15:50 -07:00
|
|
|
}
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
/*
|
|
|
|
* NOTE: Must be RCU read locked!
|
|
|
|
*/
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
|
|
|
tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(resp->disp->mgr));
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
dns_displist_t resps = ISC_LIST_INITIALIZER;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"canceling response: %s, %s/%s (%s/%s), "
|
2023-09-15 11:36:28 +02:00
|
|
|
"requests %" PRIuFAST32,
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(result), state2str(resp->state),
|
|
|
|
resp->reading ? "reading" : "not reading",
|
|
|
|
state2str(disp->state),
|
|
|
|
disp->reading ? "reading" : "not reading",
|
|
|
|
disp->requests);
|
|
|
|
|
|
|
|
switch (resp->state) {
|
|
|
|
case DNS_DISPATCHSTATE_NONE:
|
|
|
|
break;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
|
|
|
break;
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTED:
|
|
|
|
if (resp->reading) {
|
|
|
|
tcp_recv_add(&resps, resp, ISC_R_CANCELED);
|
|
|
|
}
|
2021-01-14 13:02:57 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
INSIST(!ISC_LINK_LINKED(resp, alink));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (ISC_LIST_EMPTY(disp->active)) {
|
|
|
|
INSIST(disp->handle != NULL);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
#if DISPATCH_TCP_KEEPALIVE
|
|
|
|
/*
|
|
|
|
* This is an experimental code that keeps the TCP
|
|
|
|
* connection open for 1 second before it is finally
|
|
|
|
* closed. By keeping the TCP connection open, it can
|
|
|
|
* be reused by dns_request that uses
|
|
|
|
* dns_dispatch_gettcp() to join existing TCP
|
|
|
|
* connections.
|
|
|
|
*
|
|
|
|
* It is disabled for now, because it changes the
|
|
|
|
* behaviour, but I am keeping the code here for future
|
|
|
|
* reference when we improve the dns_dispatch to reuse
|
|
|
|
* the TCP connections also in the resolver.
|
|
|
|
*
|
|
|
|
* The TCP connection reuse should be seamless and not
|
|
|
|
* require any extra handling on the client side though.
|
|
|
|
*/
|
|
|
|
isc_nmhandle_cleartimeout(disp->handle);
|
|
|
|
isc_nmhandle_settimeout(disp->handle, 1000);
|
|
|
|
|
|
|
|
if (!disp->reading) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"final 1 second timeout on %p",
|
|
|
|
disp->handle);
|
2023-02-21 20:14:30 -08:00
|
|
|
tcp_startrecv(disp, NULL);
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (disp->reading) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"canceling read on %p",
|
|
|
|
disp->handle);
|
|
|
|
isc_nm_cancelread(disp->handle);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
2000-09-18 04:50:05 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CANCELED:
|
|
|
|
goto unlock;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2020-12-09 19:44:41 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dec_stats(disp->mgr, dns_resstatscounter_dispreqtcp);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
(void)cds_lfht_del(disp->mgr->qids, &resp->ht_node);
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
resp->state = DNS_DISPATCHSTATE_CANCELED;
|
|
|
|
|
|
|
|
unlock:
|
1999-07-09 00:51:08 +00:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
/*
|
2022-12-20 08:39:36 +01:00
|
|
|
* NOTE: Calling the response callback directly from here should be done
|
|
|
|
* asynchronously, as the dns_dispatch_done() is usually called directly
|
|
|
|
* from the response callback, so there's a slight chance that the call
|
|
|
|
* stack will get higher here, but it's mitigated by the ".reading"
|
|
|
|
* flag, so we don't ever go into a loop.
|
2022-11-30 17:58:35 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
tcp_recv_processall(&resps, NULL);
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-11-30 17:58:35 +01:00
|
|
|
dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
|
|
|
|
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
|
2023-09-14 18:01:39 +02:00
|
|
|
rcu_read_lock();
|
2021-01-14 13:02:57 -08:00
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_udp:
|
2022-11-30 17:58:35 +01:00
|
|
|
udp_dispentry_cancel(resp, result);
|
2021-05-25 22:54:17 -07:00
|
|
|
break;
|
2021-01-14 13:02:57 -08:00
|
|
|
case isc_socktype_tcp:
|
2022-11-30 17:58:35 +01:00
|
|
|
tcp_dispentry_cancel(resp, result);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2023-09-14 18:01:39 +02:00
|
|
|
rcu_read_unlock();
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
2021-10-21 02:28:48 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
void
|
|
|
|
dns_dispatch_done(dns_dispentry_t **respp) {
|
|
|
|
REQUIRE(VALID_RESPONSE(*respp));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_t *resp = *respp;
|
|
|
|
*respp = NULL;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dispentry_cancel(resp, ISC_R_CANCELED);
|
|
|
|
dns_dispentry_detach(&resp); /* DISPENTRY000 */
|
|
|
|
}
|
2021-07-26 20:23:18 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
|
|
|
udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp) {
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "attaching handle %p to %p",
|
|
|
|
handle, &resp->handle);
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_nmhandle_attach(handle, &resp->handle);
|
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY003 */
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "reading");
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_nm_read(resp->handle, udp_recv, resp);
|
|
|
|
resp->reading = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-02-21 20:14:30 -08:00
|
|
|
tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) {
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
REQUIRE(disp->socktype == isc_socktype_tcp);
|
|
|
|
|
|
|
|
dns_dispatch_ref(disp); /* DISPATCH002 */
|
|
|
|
if (resp != NULL) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "reading from %p",
|
|
|
|
disp->handle);
|
2023-05-16 15:35:00 -07:00
|
|
|
INSIST(!isc_time_isepoch(&resp->start));
|
2022-11-30 17:58:35 +01:00
|
|
|
} else {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"TCP reading without response from %p",
|
|
|
|
disp->handle);
|
2020-12-19 01:34:41 -08:00
|
|
|
}
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_nm_read(disp->handle, tcp_recv, disp);
|
|
|
|
disp->reading = true;
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
|
|
|
|
2024-03-04 12:58:56 +01:00
|
|
|
static void
|
|
|
|
resp_connected(void *arg) {
|
|
|
|
dns_dispentry_t *resp = arg;
|
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
|
|
|
|
isc_result_totext(resp->result));
|
|
|
|
|
|
|
|
resp->connected(resp->result, NULL, resp->arg);
|
|
|
|
dns_dispentry_detach(&resp); /* DISPENTRY005 */
|
|
|
|
}
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
static void
|
2021-08-04 13:14:11 -07:00
|
|
|
tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|
|
|
dns_dispatch_t *disp = (dns_dispatch_t *)arg;
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_displist_t resps = ISC_LIST_INITIALIZER;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
if (isc_log_wouldlog(90)) {
|
2022-11-30 17:58:35 +01:00
|
|
|
char localbuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
char peerbuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
if (handle != NULL) {
|
|
|
|
isc_sockaddr_t local = isc_nmhandle_localaddr(handle);
|
|
|
|
isc_sockaddr_t peer = isc_nmhandle_peeraddr(handle);
|
|
|
|
|
|
|
|
isc_sockaddr_format(&local, localbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
|
|
|
isc_sockaddr_format(&peer, peerbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
|
|
|
} else {
|
|
|
|
isc_sockaddr_format(&disp->local, localbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
|
|
|
isc_sockaddr_format(&disp->peer, peerbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
|
|
|
}
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispatch_log(disp, ISC_LOG_DEBUG(90),
|
|
|
|
"connected from %s to %s: %s", localbuf, peerbuf,
|
|
|
|
isc_result_totext(eresult));
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-12-19 18:17:46 +01:00
|
|
|
INSIST(disp->state == DNS_DISPATCHSTATE_CONNECTING);
|
2021-08-04 13:14:11 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are pending responses, call the connect
|
|
|
|
* callbacks for all of them.
|
|
|
|
*/
|
2025-08-19 07:14:45 +02:00
|
|
|
ISC_LIST_FOREACH(disp->pending, resp, plink) {
|
2021-08-04 13:14:11 -07:00
|
|
|
ISC_LIST_UNLINK(disp->pending, resp, plink);
|
2022-11-30 17:58:35 +01:00
|
|
|
ISC_LIST_APPEND(resps, resp, rlink);
|
2022-12-20 08:39:36 +01:00
|
|
|
resp->result = eresult;
|
2022-11-30 17:58:35 +01:00
|
|
|
|
2022-12-20 08:39:36 +01:00
|
|
|
if (resp->state == DNS_DISPATCHSTATE_CANCELED) {
|
|
|
|
resp->result = ISC_R_CANCELED;
|
|
|
|
} else if (eresult == ISC_R_SUCCESS) {
|
2022-11-30 17:58:35 +01:00
|
|
|
resp->state = DNS_DISPATCHSTATE_CONNECTED;
|
|
|
|
ISC_LIST_APPEND(disp->active, resp, alink);
|
|
|
|
resp->reading = true;
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "start reading");
|
2022-11-30 17:58:35 +01:00
|
|
|
} else {
|
|
|
|
resp->state = DNS_DISPATCHSTATE_NONE;
|
|
|
|
}
|
2021-08-04 13:14:11 -07:00
|
|
|
}
|
2022-12-20 08:39:36 +01:00
|
|
|
|
2024-12-19 14:22:54 +00:00
|
|
|
/* Take the oldest active response. */
|
2025-03-20 22:25:56 -07:00
|
|
|
dns_dispentry_t *oldest = ISC_LIST_HEAD(disp->active);
|
|
|
|
if (oldest == NULL) {
|
2022-12-20 08:39:36 +01:00
|
|
|
/* All responses have been canceled */
|
|
|
|
disp->state = DNS_DISPATCHSTATE_CANCELED;
|
|
|
|
} else if (eresult == ISC_R_SUCCESS) {
|
|
|
|
disp->state = DNS_DISPATCHSTATE_CONNECTED;
|
2023-02-21 20:14:30 -08:00
|
|
|
isc_nmhandle_attach(handle, &disp->handle);
|
2024-12-19 14:22:54 +00:00
|
|
|
isc_nmhandle_cleartimeout(disp->handle);
|
2025-03-20 22:25:56 -07:00
|
|
|
if (oldest->timeout != 0) {
|
|
|
|
isc_nmhandle_settimeout(disp->handle, oldest->timeout);
|
2024-10-30 09:23:33 +00:00
|
|
|
}
|
2025-03-20 22:25:56 -07:00
|
|
|
tcp_startrecv(disp, oldest);
|
2022-12-20 08:39:36 +01:00
|
|
|
} else {
|
|
|
|
disp->state = DNS_DISPATCHSTATE_NONE;
|
|
|
|
}
|
|
|
|
|
2025-08-19 07:14:45 +02:00
|
|
|
ISC_LIST_FOREACH(resps, resp, rlink) {
|
2022-11-30 17:58:35 +01:00
|
|
|
ISC_LIST_UNLINK(resps, resp, rlink);
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2024-03-04 12:58:56 +01:00
|
|
|
resp_connected(resp);
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
2020-12-19 01:34:41 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_detach(&disp); /* DISPATCH003 */
|
2021-08-04 13:14:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|
|
|
dns_dispentry_t *resp = (dns_dispentry_t *)arg;
|
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "connected: %s",
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(eresult));
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (resp->state) {
|
|
|
|
case DNS_DISPATCHSTATE_CANCELED:
|
2022-12-20 08:39:36 +01:00
|
|
|
eresult = ISC_R_CANCELED;
|
|
|
|
ISC_LIST_UNLINK(disp->pending, resp, plink);
|
|
|
|
goto unlock;
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
|
|
|
ISC_LIST_UNLINK(disp->pending, resp, plink);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (eresult) {
|
2022-12-20 08:39:36 +01:00
|
|
|
case ISC_R_CANCELED:
|
|
|
|
break;
|
2022-11-30 17:58:35 +01:00
|
|
|
case ISC_R_SUCCESS:
|
|
|
|
resp->state = DNS_DISPATCHSTATE_CONNECTED;
|
|
|
|
udp_startrecv(handle, resp);
|
|
|
|
break;
|
2023-04-05 15:28:32 +02:00
|
|
|
case ISC_R_NOPERM:
|
2022-11-30 17:58:35 +01:00
|
|
|
case ISC_R_ADDRINUSE: {
|
2023-04-05 15:28:32 +02:00
|
|
|
in_port_t localport = isc_sockaddr_getport(&disp->local);
|
2021-08-04 13:14:11 -07:00
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
/* probably a port collision; try a different one */
|
|
|
|
result = setup_socket(disp, resp, &resp->peer, &localport);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2022-11-30 17:58:35 +01:00
|
|
|
udp_dispatch_connect(disp, resp);
|
2021-08-04 13:14:11 -07:00
|
|
|
goto detach;
|
|
|
|
}
|
2022-11-30 17:58:35 +01:00
|
|
|
resp->state = DNS_DISPATCHSTATE_NONE;
|
|
|
|
break;
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
|
|
|
resp->state = DNS_DISPATCHSTATE_NONE;
|
|
|
|
break;
|
2021-08-03 18:24:27 -07:00
|
|
|
}
|
2022-12-20 08:39:36 +01:00
|
|
|
unlock:
|
2022-11-30 17:58:35 +01:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_totext(eresult));
|
|
|
|
resp->connected(eresult, NULL, resp->arg);
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
detach:
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_detach(&resp); /* DISPENTRY004 */
|
2020-12-19 01:34:41 -08:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
static void
|
|
|
|
udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
resp->state = DNS_DISPATCHSTATE_CONNECTING;
|
2023-05-27 19:20:47 -07:00
|
|
|
resp->start = isc_loop_now(resp->loop);
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY004 */
|
|
|
|
ISC_LIST_APPEND(disp->pending, resp, plink);
|
2023-05-16 15:35:00 -07:00
|
|
|
|
2025-07-14 17:12:35 +02:00
|
|
|
isc_nm_udpconnect(&resp->local, &resp->peer, udp_connected, resp,
|
|
|
|
resp->timeout);
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
|
2025-03-18 12:52:18 +02:00
|
|
|
static inline const char *
|
|
|
|
get_tls_sni_hostname(dns_dispentry_t *resp) {
|
|
|
|
char *hostname = NULL;
|
|
|
|
|
|
|
|
if (resp->transport != NULL) {
|
|
|
|
hostname = dns_transport_get_remote_hostname(resp->transport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hostname == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isc_tls_valid_sni_hostname(hostname)) {
|
|
|
|
return hostname;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
static isc_result_t
|
|
|
|
tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
|
|
|
|
dns_transport_type_t transport_type = DNS_TRANSPORT_TCP;
|
2022-09-19 11:04:22 +00:00
|
|
|
isc_tlsctx_t *tlsctx = NULL;
|
|
|
|
isc_tlsctx_client_session_cache_t *sess_cache = NULL;
|
2021-01-04 23:03:50 -08:00
|
|
|
|
2022-09-19 11:04:22 +00:00
|
|
|
if (resp->transport != NULL) {
|
|
|
|
transport_type = dns_transport_get_type(resp->transport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (transport_type == DNS_TRANSPORT_TLS) {
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
result = dns_transport_get_tlsctx(
|
|
|
|
resp->transport, &resp->peer, resp->tlsctx_cache,
|
2023-09-15 14:38:02 +02:00
|
|
|
resp->mctx, &tlsctx, &sess_cache);
|
2022-09-19 11:04:22 +00:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2022-09-19 11:04:22 +00:00
|
|
|
}
|
|
|
|
INSIST(tlsctx != NULL);
|
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
/* Check whether the dispatch is already connecting or connected. */
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (disp->state) {
|
|
|
|
case DNS_DISPATCHSTATE_NONE:
|
|
|
|
/* First connection, continue with connecting */
|
|
|
|
disp->state = DNS_DISPATCHSTATE_CONNECTING;
|
|
|
|
resp->state = DNS_DISPATCHSTATE_CONNECTING;
|
2023-05-27 19:20:47 -07:00
|
|
|
resp->start = isc_loop_now(resp->loop);
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY005 */
|
|
|
|
ISC_LIST_APPEND(disp->pending, resp, plink);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
char localbuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
char peerbuf[ISC_SOCKADDR_FORMATSIZE];
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_sockaddr_format(&disp->local, localbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
|
|
|
isc_sockaddr_format(&disp->peer, peerbuf,
|
|
|
|
ISC_SOCKADDR_FORMATSIZE);
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_ref(disp); /* DISPATCH003 */
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
2022-11-30 17:58:35 +01:00
|
|
|
"connecting from %s to %s, timeout %u", localbuf,
|
2024-10-30 09:23:33 +00:00
|
|
|
peerbuf, resp->connect_timeout);
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2025-03-18 12:52:18 +02:00
|
|
|
const char *hostname = get_tls_sni_hostname(resp);
|
2024-12-17 16:24:29 +02:00
|
|
|
|
2025-07-14 17:12:35 +02:00
|
|
|
isc_nm_streamdnsconnect(&disp->local, &disp->peer,
|
|
|
|
tcp_connected, disp,
|
2024-10-30 09:23:33 +00:00
|
|
|
resp->connect_timeout, tlsctx, hostname,
|
2024-12-17 16:24:29 +02:00
|
|
|
sess_cache, ISC_NM_PROXY_NONE, NULL);
|
2022-11-30 17:58:35 +01:00
|
|
|
break;
|
2021-08-03 18:24:27 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
|
|
|
/* Connection pending; add resp to the list */
|
|
|
|
resp->state = DNS_DISPATCHSTATE_CONNECTING;
|
2023-05-27 19:20:47 -07:00
|
|
|
resp->start = isc_loop_now(resp->loop);
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY005 */
|
|
|
|
ISC_LIST_APPEND(disp->pending, resp, plink);
|
2021-01-14 13:02:57 -08:00
|
|
|
break;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTED:
|
|
|
|
resp->state = DNS_DISPATCHSTATE_CONNECTED;
|
2023-05-27 19:20:47 -07:00
|
|
|
resp->start = isc_loop_now(resp->loop);
|
2022-11-30 17:58:35 +01:00
|
|
|
|
|
|
|
/* Add the resp to the reading list */
|
|
|
|
ISC_LIST_APPEND(disp->active, resp, alink);
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90),
|
|
|
|
"already connected; attaching");
|
2022-11-30 17:58:35 +01:00
|
|
|
resp->reading = true;
|
|
|
|
|
|
|
|
if (!disp->reading) {
|
|
|
|
/* Restart the reading */
|
2024-10-30 09:23:33 +00:00
|
|
|
isc_nmhandle_cleartimeout(disp->handle);
|
|
|
|
if (resp->timeout != 0) {
|
|
|
|
isc_nmhandle_settimeout(disp->handle,
|
|
|
|
resp->timeout);
|
|
|
|
}
|
2023-02-21 20:14:30 -08:00
|
|
|
tcp_startrecv(disp, resp);
|
2022-11-30 17:58:35 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 12:58:56 +01:00
|
|
|
/* Already connected; call the connected cb asynchronously */
|
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY005 */
|
|
|
|
isc_async_run(resp->loop, resp_connected, resp);
|
2021-01-14 13:02:57 -08:00
|
|
|
break;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
default:
|
2022-11-30 17:58:35 +01:00
|
|
|
UNREACHABLE();
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
2021-01-04 23:03:50 -08:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_result_t
|
|
|
|
dns_dispatch_connect(dns_dispentry_t *resp) {
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
|
|
|
|
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
|
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_tcp:
|
2024-11-19 10:38:03 +01:00
|
|
|
return tcp_dispatch_connect(disp, resp);
|
2022-11-30 17:58:35 +01:00
|
|
|
|
|
|
|
case isc_socktype_udp:
|
|
|
|
udp_dispatch_connect(disp, resp);
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2022-11-30 17:58:35 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
static void
|
|
|
|
send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|
|
|
dns_dispentry_t *resp = (dns_dispentry_t *)cbarg;
|
|
|
|
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
|
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "sent: %s",
|
|
|
|
isc_result_totext(result));
|
2022-11-30 17:58:35 +01:00
|
|
|
|
2021-08-03 15:27:06 +02:00
|
|
|
resp->sent(result, NULL, resp->arg);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-11-30 17:58:35 +01:00
|
|
|
dispentry_cancel(resp, result);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_detach(&resp); /* DISPENTRY007 */
|
|
|
|
isc_nmhandle_detach(&handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
|
2024-10-30 13:31:34 +00:00
|
|
|
int64_t timeout) {
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "continue reading");
|
2023-02-22 11:04:12 -08:00
|
|
|
|
|
|
|
if (!resp->reading) {
|
|
|
|
ISC_LIST_APPEND(disp->active, resp, alink);
|
|
|
|
resp->reading = true;
|
|
|
|
}
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
if (disp->reading) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-10-30 13:31:34 +00:00
|
|
|
if (timeout != 0) {
|
|
|
|
INSIST(timeout > 0 && timeout <= UINT32_MAX);
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_nmhandle_settimeout(disp->handle, timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_dispatch_ref(disp); /* DISPATCH002 */
|
|
|
|
isc_nm_read(disp->handle, tcp_recv, disp);
|
|
|
|
disp->reading = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-10-30 13:31:34 +00:00
|
|
|
udp_dispatch_getnext(dns_dispentry_t *resp, int64_t timeout) {
|
2022-11-30 17:58:35 +01:00
|
|
|
if (resp->reading) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-10-30 13:31:34 +00:00
|
|
|
if (timeout != 0) {
|
|
|
|
INSIST(timeout > 0 && timeout <= UINT32_MAX);
|
2022-11-30 17:58:35 +01:00
|
|
|
isc_nmhandle_settimeout(resp->handle, timeout);
|
|
|
|
}
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "continue reading");
|
2022-11-30 17:58:35 +01:00
|
|
|
|
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY003 */
|
|
|
|
isc_nm_read(resp->handle, udp_recv, resp);
|
|
|
|
resp->reading = true;
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
2021-08-03 15:27:06 +02:00
|
|
|
void
|
2024-10-30 13:31:34 +00:00
|
|
|
dns_dispatch_resume(dns_dispentry_t *resp, unsigned int timeout) {
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
2021-08-03 15:27:06 +02:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
2021-08-03 15:27:06 +02:00
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "resume");
|
2023-02-22 11:04:12 -08:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
REQUIRE(disp->tid == isc_tid());
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_udp: {
|
|
|
|
udp_dispatch_getnext(resp, timeout);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case isc_socktype_tcp:
|
|
|
|
INSIST(disp->timedout > 0);
|
|
|
|
disp->timedout--;
|
|
|
|
tcp_dispatch_getnext(disp, resp, timeout);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2021-08-03 15:27:06 +02:00
|
|
|
}
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
void
|
2023-01-05 22:18:55 -08:00
|
|
|
dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r) {
|
2021-01-14 13:02:57 -08:00
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
2021-01-14 13:02:57 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
isc_nmhandle_t *sendhandle = NULL;
|
|
|
|
|
2023-09-15 15:59:28 +02:00
|
|
|
dispentry_log(resp, ISC_LOG_DEBUG(90), "sending");
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_udp:
|
|
|
|
isc_nmhandle_attach(resp->handle, &sendhandle);
|
|
|
|
break;
|
|
|
|
case isc_socktype_tcp:
|
|
|
|
isc_nmhandle_attach(disp->handle, &sendhandle);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2021-08-03 18:24:27 -07:00
|
|
|
}
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispentry_ref(resp); /* DISPENTRY007 */
|
|
|
|
isc_nm_send(sendhandle, r, send_done, resp);
|
2021-01-04 23:03:50 -08:00
|
|
|
}
|
|
|
|
|
2001-03-13 05:48:41 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {
|
2001-03-13 05:48:41 +00:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
REQUIRE(addrp != NULL);
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
if (disp->socktype == isc_socktype_udp) {
|
2001-03-13 05:48:41 +00:00
|
|
|
*addrp = disp->local;
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2001-03-13 05:48:41 +00:00
|
|
|
}
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_NOTIMPLEMENTED;
|
2001-03-13 05:48:41 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 14:38:35 -08:00
|
|
|
isc_result_t
|
|
|
|
dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) {
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
2022-11-30 17:58:35 +01:00
|
|
|
REQUIRE(VALID_DISPATCH(resp->disp));
|
2021-01-04 14:38:35 -08:00
|
|
|
REQUIRE(addrp != NULL);
|
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
2021-01-04 14:38:35 -08:00
|
|
|
|
2022-11-30 17:58:35 +01:00
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_tcp:
|
2024-12-29 12:32:05 +01:00
|
|
|
*addrp = isc_nmhandle_localaddr(disp->handle);
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2022-11-30 17:58:35 +01:00
|
|
|
case isc_socktype_udp:
|
2021-05-25 22:54:17 -07:00
|
|
|
*addrp = isc_nmhandle_localaddr(resp->handle);
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2022-11-30 17:58:35 +01:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2021-01-04 14:38:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-27 16:07:24 -07:00
|
|
|
dns_dispatch_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchset_get(dns_dispatchset_t *dset) {
|
2025-06-04 17:54:20 +02:00
|
|
|
isc_tid_t tid = isc_tid();
|
2012-04-27 16:07:24 -07:00
|
|
|
|
|
|
|
/* check that dispatch set is configured */
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dset == NULL || dset->ndisp == 0) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return NULL;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2025-06-04 17:54:20 +02:00
|
|
|
INSIST((uint32_t)tid < dset->ndisp);
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return dset->dispatches[tid];
|
2012-04-27 16:07:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
|
2023-09-15 11:36:28 +02:00
|
|
|
dns_dispatchset_t **dsetp, uint32_t ndisp) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatchset_t *dset = NULL;
|
|
|
|
dns_dispatchmgr_t *mgr = NULL;
|
2023-09-15 11:36:28 +02:00
|
|
|
size_t i;
|
2012-04-27 16:07:24 -07:00
|
|
|
|
|
|
|
REQUIRE(VALID_DISPATCH(source));
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(source->socktype == isc_socktype_udp);
|
2012-04-27 16:07:24 -07:00
|
|
|
REQUIRE(dsetp != NULL && *dsetp == NULL);
|
|
|
|
|
|
|
|
mgr = source->mgr;
|
|
|
|
|
|
|
|
dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t));
|
2023-09-15 11:36:28 +02:00
|
|
|
*dset = (dns_dispatchset_t){ .ndisp = ndisp };
|
2012-04-27 16:07:24 -07:00
|
|
|
|
|
|
|
isc_mem_attach(mctx, &dset->mctx);
|
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
dset->dispatches = isc_mem_cget(dset->mctx, ndisp,
|
|
|
|
sizeof(dns_dispatch_t *));
|
|
|
|
|
2012-04-27 16:07:24 -07:00
|
|
|
dset->dispatches[0] = NULL;
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_attach(source, &dset->dispatches[0]); /* DISPATCH004 */
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
for (i = 1; i < dset->ndisp; i++) {
|
|
|
|
result = dispatch_createudp(mgr, &source->local, i,
|
2020-12-16 01:32:06 -08:00
|
|
|
&dset->dispatches[i]);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2012-04-27 16:07:24 -07:00
|
|
|
goto fail;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
*dsetp = dset;
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_SUCCESS;
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
fail:
|
2023-09-15 11:36:28 +02:00
|
|
|
for (size_t j = 0; j < i; j++) {
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_detach(&(dset->dispatches[j])); /* DISPATCH004 */
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-09-15 11:36:28 +02:00
|
|
|
isc_mem_cput(dset->mctx, dset->dispatches, ndisp,
|
|
|
|
sizeof(dns_dispatch_t *));
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
|
2024-11-19 10:38:03 +01:00
|
|
|
return result;
|
2012-04-27 16:07:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
|
2012-04-27 16:07:24 -07:00
|
|
|
REQUIRE(dsetp != NULL && *dsetp != NULL);
|
|
|
|
|
2023-09-15 11:36:28 +02:00
|
|
|
dns_dispatchset_t *dset = *dsetp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*dsetp = NULL;
|
2023-09-15 11:36:28 +02:00
|
|
|
|
|
|
|
for (size_t i = 0; i < dset->ndisp; i++) {
|
2022-11-30 17:58:35 +01:00
|
|
|
dns_dispatch_detach(&(dset->dispatches[i])); /* DISPATCH004 */
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(dset->mctx, dset->dispatches, dset->ndisp,
|
|
|
|
sizeof(dns_dispatch_t *));
|
2012-04-27 16:07:24 -07:00
|
|
|
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
|
|
|
|
}
|
2023-02-21 20:14:30 -08:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_dispatch_checkperm(dns_dispatch_t *disp) {
|
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
|
|
|
|
if (disp->handle == NULL || disp->socktype == isc_socktype_udp) {
|
2024-11-19 10:38:03 +01:00
|
|
|
return ISC_R_NOPERM;
|
2023-02-21 20:14:30 -08:00
|
|
|
}
|
|
|
|
|
2024-11-19 10:38:03 +01:00
|
|
|
return isc_nm_xfr_checkperm(disp->handle);
|
2023-02-21 20:14:30 -08:00
|
|
|
}
|