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
|
|
|
*
|
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
|
|
|
|
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
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
#include <isc/atomic.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>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/print.h>
|
2008-06-23 19:41:20 +00:00
|
|
|
#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>
|
2007-06-26 06:02:37 +00:00
|
|
|
#include <isc/time.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>
|
2000-04-29 00:45:26 +00:00
|
|
|
#include <dns/log.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>
|
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
|
|
|
|
|
|
|
typedef struct dns_qid {
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_mutex_t lock;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int qid_nbuckets; /*%< hash table size */
|
|
|
|
unsigned int qid_increment; /*%< id increment on collision */
|
2021-01-14 13:02:57 -08:00
|
|
|
dns_displist_t *qid_table; /*%< the table itself */
|
2000-09-18 04:50:05 +00:00
|
|
|
} dns_qid_t;
|
|
|
|
|
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;
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_nm_t *nm;
|
2000-05-10 21:34:50 +00:00
|
|
|
|
|
|
|
/* Locked by "lock". */
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mutex_t lock;
|
2020-02-12 13:59:18 +01:00
|
|
|
unsigned int state;
|
|
|
|
ISC_LIST(dns_dispatch_t) list;
|
2000-09-19 06:59:28 +00:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_qid_t *qid;
|
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
|
|
|
};
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define MGR_SHUTTINGDOWN 0x00000001U
|
2020-02-12 13:59:18 +01:00
|
|
|
#define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
|
2000-05-10 21:34:50 +00:00
|
|
|
|
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;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatch_t *disp;
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nmhandle_t *handle; /*%< netmgr handle for UDP connection */
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int bucket;
|
2021-08-04 13:14:11 -07:00
|
|
|
unsigned int retries;
|
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;
|
2021-05-25 22:54:17 -07:00
|
|
|
bool canceled;
|
2020-02-12 13:59:18 +01:00
|
|
|
ISC_LINK(dns_dispentry_t) link;
|
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;
|
2008-06-23 19:41:20 +00:00
|
|
|
};
|
|
|
|
|
2020-12-09 15:45:13 -08:00
|
|
|
/*%
|
|
|
|
* Fixed UDP buffer size.
|
|
|
|
*/
|
|
|
|
#ifndef DNS_DISPATCH_UDPBUFSIZE
|
|
|
|
#define DNS_DISPATCH_UDPBUFSIZE 4096
|
|
|
|
#endif /* ifndef DNS_DISPATCH_UDPBUFSIZE */
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
typedef enum {
|
|
|
|
DNS_DISPATCHSTATE_NONE = 0UL,
|
|
|
|
DNS_DISPATCHSTATE_CONNECTING,
|
|
|
|
DNS_DISPATCHSTATE_CONNECTED
|
|
|
|
} dns_dispatchstate_t;
|
|
|
|
|
1999-06-16 01:32:31 +00:00
|
|
|
struct dns_dispatch {
|
|
|
|
/* Unlocked. */
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic; /*%< magic */
|
|
|
|
dns_dispatchmgr_t *mgr; /*%< dispatch manager */
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_nmhandle_t *handle; /*%< netmgr handle for TCP connection */
|
|
|
|
isc_sockaddr_t local; /*%< local address */
|
|
|
|
in_port_t localport; /*%< local UDP port */
|
|
|
|
isc_sockaddr_t peer; /*%< peer address (TCP) */
|
2012-04-28 14:52:28 -07:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% Locked by mgr->lock. */
|
2000-05-10 21:34:50 +00:00
|
|
|
ISC_LINK(dns_dispatch_t) link;
|
|
|
|
|
|
|
|
/* Locked by "lock". */
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_mutex_t lock; /*%< locks all below */
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_socktype_t socktype;
|
2021-08-03 18:24:27 -07:00
|
|
|
atomic_uint_fast32_t state;
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_refcount_t references;
|
2021-07-26 20:23:18 -07:00
|
|
|
unsigned int shutdown_out : 1;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dns_displist_t pending;
|
|
|
|
dns_displist_t active;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int nsockets;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int requests; /*%< how many requests we have */
|
|
|
|
unsigned int tcpbuffers; /*%< allocated buffers */
|
1999-06-16 01:32:31 +00:00
|
|
|
};
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define VALID_QID(e) ISC_MAGIC_VALID((e), QID_MAGIC)
|
2000-09-18 04:50:05 +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 DISPSOCK_MAGIC ISC_MAGIC('D', 's', 'o', 'c')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define VALID_DISPSOCK(e) ISC_MAGIC_VALID((e), DISPSOCK_MAGIC)
|
2008-06-23 19:41:20 +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
|
|
|
|
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
|
|
|
/*%
|
|
|
|
* Quota to control the number of UDP dispatch sockets. If a dispatch has
|
|
|
|
* more than the quota of sockets, new queries will purge oldest ones, so
|
|
|
|
* that a massive number of outstanding queries won't prevent subsequent
|
|
|
|
* queries (especially if the older ones take longer time and result in
|
|
|
|
* timeout).
|
|
|
|
*/
|
|
|
|
#ifndef DNS_DISPATCH_SOCKSQUOTA
|
|
|
|
#define DNS_DISPATCH_SOCKSQUOTA 3072
|
|
|
|
#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Quota to control the number of concurrent requests that can be handled
|
|
|
|
* by each TCP dispatch. (UDP dispatches do not currently support socket
|
|
|
|
* sharing.)
|
|
|
|
*/
|
|
|
|
#ifndef DNS_DISPATCH_MAXREQUESTS
|
|
|
|
#define DNS_DISPATCH_MAXREQUESTS 32768
|
|
|
|
#endif /* ifndef DNS_DISPATCH_MAXREQUESTS */
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
/*%
|
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
|
|
|
* Number of buckets in the QID hash table, and the value to
|
|
|
|
* increment the QID by when attempting to avoid collisions.
|
|
|
|
* The number of buckets should be prime, and the increment
|
|
|
|
* should be the next higher prime number.
|
2008-06-23 19:41:20 +00:00
|
|
|
*/
|
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
|
|
|
#ifndef DNS_QID_BUCKETS
|
|
|
|
#define DNS_QID_BUCKETS 16411
|
|
|
|
#endif /* ifndef DNS_QID_BUCKETS */
|
|
|
|
#ifndef DNS_QID_INCREMENT
|
|
|
|
#define DNS_QID_INCREMENT 16433
|
|
|
|
#endif /* ifndef DNS_QID_INCREMENT */
|
2008-06-23 19:41:20 +00:00
|
|
|
|
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 dns_dispentry_t *
|
|
|
|
entry_search(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t,
|
|
|
|
unsigned int);
|
|
|
|
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 uint32_t
|
|
|
|
dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t);
|
|
|
|
static void
|
|
|
|
dispatch_free(dns_dispatch_t **dispp);
|
|
|
|
static isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
|
2021-08-03 18:24:27 -07:00
|
|
|
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
|
|
|
|
qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp);
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
|
2021-01-14 13:02:57 -08:00
|
|
|
static void
|
2021-08-03 18:24:27 -07:00
|
|
|
startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp, dns_dispentry_t *resp);
|
|
|
|
void
|
|
|
|
dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, int32_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
|
|
|
|
|
|
|
#define LVL(x) ISC_LOG_DEBUG(x)
|
1999-07-08 02:50:00 +00: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;
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!isc_log_wouldlog(dns_lctx, 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);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(dns_lctx, 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
|
|
|
}
|
|
|
|
|
2009-01-31 00:10:24 +00:00
|
|
|
static inline 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
|
|
|
}
|
|
|
|
|
2012-05-14 10:06:05 -07:00
|
|
|
static inline 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;
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!isc_log_wouldlog(dns_lctx, 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);
|
|
|
|
vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
|
|
|
|
DNS_LOGMODULE_DISPATCH, level, "dispatch %p: %s", disp,
|
|
|
|
msgbuf);
|
2000-04-29 00:45:26 +00:00
|
|
|
}
|
|
|
|
|
2000-01-07 01:17:47 +00:00
|
|
|
/*
|
|
|
|
* Return a hash of the destination and message id.
|
|
|
|
*/
|
2018-03-28 14:19:37 +02:00
|
|
|
static uint32_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_hash(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id,
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t port) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t ret;
|
2000-01-07 01:17:47 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
ret = isc_sockaddr_hash(dest, true);
|
2018-03-28 14:19:37 +02:00
|
|
|
ret ^= ((uint32_t)id << 16) | port;
|
2000-09-18 04:50:05 +00:00
|
|
|
ret %= qid->qid_nbuckets;
|
2000-01-07 01:17:47 +00:00
|
|
|
|
2000-09-18 04:50:05 +00:00
|
|
|
INSIST(ret < qid->qid_nbuckets);
|
2000-01-07 01:17:47 +00:00
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
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.
|
2012-04-28 14:52:28 -07:00
|
|
|
* The caller must hold the disp->lock
|
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;
|
2021-05-25 22:54:17 -07:00
|
|
|
in_port_t port;
|
2008-06-23 19:41:20 +00:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (resp->retries++ > 5) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
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) {
|
2008-06-23 19:41:20 +00: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
|
|
|
disp->nsockets++;
|
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
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
port = ports[isc_random_uniform(nports)];
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_sockaddr_setport(&resp->local, port);
|
|
|
|
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
|
|
|
|
2020-12-16 01:32:06 -08:00
|
|
|
*portp = port;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*%
|
2021-05-25 22:54:17 -07:00
|
|
|
* Deactivate the socket for a dispatch entry.
|
2021-01-14 13:02:57 -08:00
|
|
|
* The dispatch must be locked.
|
2008-06-23 19:41:20 +00:00
|
|
|
*/
|
|
|
|
static void
|
2021-05-25 22:54:17 -07:00
|
|
|
deactivate_dispentry(dns_dispatch_t *disp, dns_dispentry_t *resp) {
|
|
|
|
if (ISC_LINK_LINKED(resp, alink)) {
|
|
|
|
ISC_LIST_UNLINK(disp->active, resp, alink);
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
2021-07-26 20:23:18 -07:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (resp->handle != NULL) {
|
2021-08-03 18:24:27 -07:00
|
|
|
INSIST(disp->socktype == isc_socktype_udp);
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nm_cancelread(resp->handle);
|
|
|
|
isc_nmhandle_detach(&resp->handle);
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
2021-07-26 20:23:18 -07:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
disp->nsockets--;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2001-01-25 13:47:59 +00:00
|
|
|
/*
|
2008-06-23 19:41:20 +00:00
|
|
|
* Find an entry for query ID 'id', socket address 'dest', and port number
|
2008-08-15 17:29:52 +00:00
|
|
|
* 'port'.
|
2001-01-25 13:47:59 +00:00
|
|
|
* Return NULL if no such entry exists.
|
|
|
|
*/
|
1999-07-06 19:32:40 +00:00
|
|
|
static dns_dispentry_t *
|
2016-12-30 15:45:08 +11:00
|
|
|
entry_search(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id,
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t port, unsigned int bucket) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispentry_t *res = NULL;
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2013-12-23 09:50:18 -08:00
|
|
|
REQUIRE(VALID_QID(qid));
|
2000-09-18 04:50:05 +00:00
|
|
|
REQUIRE(bucket < qid->qid_nbuckets);
|
1999-07-09 20:34:26 +00:00
|
|
|
|
2008-08-15 17:29:52 +00:00
|
|
|
res = ISC_LIST_HEAD(qid->qid_table[bucket]);
|
1999-06-30 01:33:11 +00:00
|
|
|
|
|
|
|
while (res != NULL) {
|
2021-01-14 13:02:57 -08:00
|
|
|
if (res->id == id && isc_sockaddr_equal(dest, &res->peer) &&
|
2008-06-23 19:41:20 +00:00
|
|
|
res->port == port) {
|
1999-06-30 01:33:11 +00:00
|
|
|
return (res);
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
1999-06-30 01:33:11 +00:00
|
|
|
res = ISC_LIST_NEXT(res, link);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
static void
|
2021-09-09 15:25:08 -07:00
|
|
|
dispentry_attach(dns_dispentry_t *resp, dns_dispentry_t **respp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
REQUIRE(respp != NULL && *respp == NULL);
|
|
|
|
|
2021-09-09 15:25:08 -07:00
|
|
|
isc_refcount_increment(&resp->references);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
|
|
|
*respp = resp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-09-09 15:25:08 -07:00
|
|
|
dispentry_destroy(dns_dispentry_t *resp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispatch_t *disp = resp->disp;
|
|
|
|
|
|
|
|
resp->magic = 0;
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (ISC_LINK_LINKED(resp, plink)) {
|
|
|
|
ISC_LIST_UNLINK(disp->pending, resp, plink);
|
|
|
|
}
|
|
|
|
|
|
|
|
INSIST(!ISC_LINK_LINKED(resp, alink));
|
|
|
|
INSIST(!ISC_LINK_LINKED(resp, rlink));
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (resp->handle != NULL) {
|
|
|
|
isc_nmhandle_detach(&resp->handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_refcount_destroy(&resp->references);
|
|
|
|
|
|
|
|
isc_mem_put(disp->mgr->mctx, resp, sizeof(*resp));
|
|
|
|
|
|
|
|
dns_dispatch_detach(&disp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-09-09 15:25:08 -07:00
|
|
|
dispentry_detach(dns_dispentry_t **respp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispentry_t *resp = NULL;
|
|
|
|
uint_fast32_t ref;
|
|
|
|
|
|
|
|
REQUIRE(respp != NULL && VALID_RESPONSE(*respp));
|
|
|
|
|
|
|
|
resp = *respp;
|
|
|
|
*respp = NULL;
|
|
|
|
|
|
|
|
ref = isc_refcount_decrement(&resp->references);
|
|
|
|
if (ref == 1) {
|
2021-09-09 15:25:08 -07:00
|
|
|
dispentry_destroy(resp);
|
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
|
|
|
|
* started reading? (Only used for UDP, to adjust the timeout
|
|
|
|
* downward when running getnext.)
|
|
|
|
*/
|
|
|
|
static unsigned int
|
|
|
|
dispentry_runtime(dns_dispentry_t *resp) {
|
|
|
|
isc_time_t now;
|
|
|
|
|
|
|
|
if (isc_time_isepoch(&resp->start)) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
TIME_NOW(&now);
|
|
|
|
return (isc_time_microdiff(&now, &resp->start) / 1000);
|
|
|
|
}
|
|
|
|
|
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;
|
2021-10-01 12:53:31 -07:00
|
|
|
int match, timeout;
|
2021-08-03 15:27:06 +02:00
|
|
|
dispatch_cb_t response = NULL;
|
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
|
|
|
|
|
|
|
LOCK(&disp->lock);
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dispatch_log(disp, LVL(90), "UDP response %p:%s:requests %d", resp,
|
|
|
|
isc_result_totext(eresult), disp->requests);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The resp may have been deactivated by shutdown; if
|
|
|
|
* so, we can skip the response callback.
|
|
|
|
*/
|
|
|
|
if (ISC_LINK_LINKED(resp, alink)) {
|
|
|
|
response = resp->response;
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
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-08-04 13:14:11 -07:00
|
|
|
INSIST(ISC_LINK_LINKED(resp, alink));
|
2020-12-16 01:32:06 -08: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)
|
|
|
|
{
|
2000-11-03 02:45:55 +00:00
|
|
|
if (isc_log_wouldlog(dns_lctx, LVL(10))) {
|
|
|
|
char netaddrstr[ISC_NETADDR_FORMATSIZE];
|
|
|
|
isc_netaddr_format(&netaddr, netaddrstr,
|
|
|
|
sizeof(netaddrstr));
|
2020-02-12 13:59:18 +01:00
|
|
|
dispatch_log(disp, LVL(10), "blackholed packet from %s",
|
2000-11-03 02:45:55 +00:00
|
|
|
netaddrstr);
|
|
|
|
}
|
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) {
|
2000-06-16 15:51:58 +00:00
|
|
|
dispatch_log(disp, LVL(10), "got garbage packet");
|
2021-08-04 13:14:11 -07:00
|
|
|
goto next;
|
1999-06-30 01:33:11 +00:00
|
|
|
}
|
|
|
|
|
2000-04-29 00:45:26 +00:00
|
|
|
dispatch_log(disp, LVL(92),
|
2000-06-16 15:51:58 +00:00
|
|
|
"got valid DNS message header, /QR %c, id %u",
|
2018-10-11 11:57:57 +02: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)) {
|
2020-12-16 01:32:06 -08:00
|
|
|
dispatch_log(disp, LVL(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
|
|
|
*/
|
2021-10-01 12:53:31 -07:00
|
|
|
timeout = resp->timeout - dispentry_runtime(resp);
|
|
|
|
if (timeout <= 0) {
|
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
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-10-01 12:53:31 -07:00
|
|
|
eresult = ISC_R_TIMEDOUT;
|
|
|
|
goto done;
|
|
|
|
}
|
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.
|
|
|
|
*/
|
|
|
|
response = NULL;
|
2021-10-01 12:53:31 -07:00
|
|
|
dispatch_getnext(disp, resp, resp->timeout - dispentry_runtime(resp));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
done:
|
2014-08-06 18:49:53 +10:00
|
|
|
UNLOCK(&disp->lock);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-07-26 20:23:18 -07:00
|
|
|
if (response != NULL) {
|
2021-08-03 15:27:06 +02:00
|
|
|
response(eresult, region, resp->arg);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
dispentry_detach(&resp);
|
1999-06-30 01:33:11 +00: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
|
|
|
*
|
2002-09-04 02:26:13 +00:00
|
|
|
* If query, restart.
|
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-01-14 13:02:57 -08:00
|
|
|
tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|
|
|
void *arg) {
|
2021-08-03 18:24:27 -07:00
|
|
|
dns_dispatch_t *disp = (dns_dispatch_t *)arg;
|
2021-08-04 13:14:11 -07:00
|
|
|
dns_dispentry_t *resp = NULL, *next = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_messageid_t id;
|
|
|
|
isc_result_t dres;
|
|
|
|
unsigned int flags;
|
|
|
|
unsigned int bucket;
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_qid_t *qid = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
int level;
|
|
|
|
char buf[ISC_SOCKADDR_FORMATSIZE];
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_buffer_t source;
|
|
|
|
isc_sockaddr_t peer;
|
2021-08-04 13:14:11 -07:00
|
|
|
dns_displist_t resps;
|
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
|
|
|
|
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
|
|
|
qid = disp->mgr->qid;
|
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
|
|
|
|
2019-11-22 10:49:40 +11:00
|
|
|
LOCK(&disp->lock);
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dispatch_log(disp, LVL(90), "TCP read:%s:requests %d, buffers %d",
|
|
|
|
isc_result_totext(eresult), disp->requests,
|
|
|
|
disp->tcpbuffers);
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
peer = isc_nmhandle_peeraddr(handle);
|
2021-08-04 13:14:11 -07:00
|
|
|
ISC_LIST_INIT(resps);
|
2021-01-14 13:02:57 -08:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
switch (eresult) {
|
|
|
|
case ISC_R_SUCCESS:
|
|
|
|
/* got our answer */
|
|
|
|
break;
|
2008-04-03 02:01:08 +00:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
case ISC_R_SHUTTINGDOWN:
|
|
|
|
case ISC_R_CANCELED:
|
2021-08-03 18:24:27 -07:00
|
|
|
case ISC_R_EOF:
|
2021-08-04 13:14:11 -07:00
|
|
|
dispatch_log(disp, LVL(90), "shutting down: %s",
|
|
|
|
isc_result_totext(eresult));
|
|
|
|
/*
|
|
|
|
* If there are any active responses, shut them all down.
|
|
|
|
*/
|
2021-11-26 09:14:58 +01:00
|
|
|
goto shutdown;
|
2000-09-08 22:02:21 +00:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
case ISC_R_TIMEDOUT:
|
|
|
|
/*
|
2021-08-04 13:14:11 -07:00
|
|
|
* Time out the oldest response in the active queue,
|
|
|
|
* and move it to the end. (We don't remove it from the
|
|
|
|
* active queue immediately, though, because the callback
|
|
|
|
* might decide to keep waiting and leave it active.)
|
2021-08-03 18:24:27 -07:00
|
|
|
*/
|
|
|
|
resp = ISC_LIST_HEAD(disp->active);
|
2021-08-04 13:14:11 -07:00
|
|
|
if (resp != NULL) {
|
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
|
|
|
ISC_LIST_UNLINK(disp->active, resp, alink);
|
|
|
|
ISC_LIST_APPEND(disp->active, resp, alink);
|
|
|
|
}
|
|
|
|
goto done;
|
2021-08-03 18:24:27 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
if (eresult == ISC_R_CONNECTIONRESET) {
|
|
|
|
level = ISC_LOG_INFO;
|
|
|
|
} else {
|
|
|
|
level = ISC_LOG_ERROR;
|
2000-09-08 22:02:21 +00:00
|
|
|
}
|
2000-04-29 00:45:26 +00:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
isc_sockaddr_format(&peer, buf, sizeof(buf));
|
|
|
|
dispatch_log(disp, level,
|
|
|
|
"shutting down due to TCP "
|
|
|
|
"receive error: %s: %s",
|
|
|
|
buf, isc_result_totext(eresult));
|
2021-11-26 09:14:58 +01:00
|
|
|
/*
|
|
|
|
* If there are any active responses, shut them all down.
|
|
|
|
*/
|
|
|
|
for (resp = ISC_LIST_HEAD(disp->active); resp != NULL;
|
|
|
|
resp = next) {
|
|
|
|
next = ISC_LIST_NEXT(resp, alink);
|
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
|
|
|
ISC_LIST_UNLINK(disp->active, resp, alink);
|
|
|
|
ISC_LIST_APPEND(resps, resp, rlink);
|
|
|
|
}
|
2021-08-04 13:14:11 -07:00
|
|
|
goto done;
|
1999-07-12 23:44:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dispatch_log(disp, LVL(90), "success, length == %d, addr = %p",
|
|
|
|
region->length, region->base);
|
1999-07-12 23:44:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Peek into the buffer to see what we can see.
|
|
|
|
*/
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_buffer_init(&source, region->base, region->length);
|
|
|
|
isc_buffer_add(&source, region->length);
|
|
|
|
dres = dns_message_peekheader(&source, &id, &flags);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (dres != ISC_R_SUCCESS) {
|
2000-06-16 15:51:58 +00:00
|
|
|
dispatch_log(disp, LVL(10), "got garbage packet");
|
2021-11-26 09:14:58 +01:00
|
|
|
eresult = ISC_R_UNEXPECTED;
|
|
|
|
goto shutdown;
|
1999-07-12 23:44:31 +00:00
|
|
|
}
|
|
|
|
|
2000-04-29 00:45:26 +00:00
|
|
|
dispatch_log(disp, LVL(92),
|
2000-06-16 15:51:58 +00:00
|
|
|
"got valid DNS message header, /QR %c, id %u",
|
2018-10-11 11:57:57 +02:00
|
|
|
(((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0'), id);
|
1999-07-12 23:44:31 +00:00
|
|
|
|
|
|
|
/*
|
2021-11-26 09:14:58 +01:00
|
|
|
* Look at the message flags. If it's a query, stop reading.
|
1999-07-12 23:44:31 +00:00
|
|
|
*/
|
|
|
|
if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
|
2021-11-26 09:14:58 +01:00
|
|
|
dispatch_log(disp, LVL(10), "got DNS query instead of answer");
|
|
|
|
eresult = ISC_R_UNEXPECTED;
|
|
|
|
goto shutdown;
|
1999-07-12 23:44:31 +00:00
|
|
|
}
|
|
|
|
|
2004-07-21 00:48:19 +00:00
|
|
|
/*
|
2021-08-04 13:14:11 -07:00
|
|
|
* We have a valid response; find the associated dispentry object
|
|
|
|
* and call the caller back.
|
2004-07-21 00:48:19 +00:00
|
|
|
*/
|
2021-01-14 13:02:57 -08:00
|
|
|
bucket = dns_hash(qid, &peer, id, disp->localport);
|
2004-07-21 00:48:19 +00:00
|
|
|
LOCK(&qid->lock);
|
2021-01-14 13:02:57 -08:00
|
|
|
resp = entry_search(qid, &peer, id, disp->localport, bucket);
|
2021-08-04 13:14:11 -07:00
|
|
|
if (resp != NULL) {
|
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
dispatch_log(disp, LVL(90), "search for response in bucket %d: %s",
|
2004-07-21 00:48:19 +00:00
|
|
|
bucket, (resp == NULL ? "not found" : "found"));
|
2021-04-22 18:58:01 -07:00
|
|
|
UNLOCK(&qid->lock);
|
2004-07-21 00:48:19 +00:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dispatch_getnext(disp, NULL, -1);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-11-26 09:14:58 +01:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
shutdown:
|
|
|
|
for (resp = ISC_LIST_HEAD(disp->active); resp != NULL; resp = next) {
|
|
|
|
next = ISC_LIST_NEXT(resp, alink);
|
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
|
|
|
ISC_LIST_UNLINK(disp->active, resp, alink);
|
|
|
|
ISC_LIST_APPEND(resps, resp, rlink);
|
|
|
|
}
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
done:
|
2014-08-06 18:49:53 +10:00
|
|
|
UNLOCK(&disp->lock);
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2021-07-26 20:23:18 -07:00
|
|
|
if (resp != NULL) {
|
2021-08-04 13:14:11 -07:00
|
|
|
/* We got a matching response, or timed out */
|
2021-08-03 15:27:06 +02:00
|
|
|
resp->response(eresult, region, resp->arg);
|
2021-08-04 13:14:11 -07:00
|
|
|
dispentry_detach(&resp);
|
|
|
|
} else {
|
|
|
|
/* We're being shut down; cancel all outstanding resps */
|
|
|
|
for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) {
|
|
|
|
next = ISC_LIST_NEXT(resp, rlink);
|
|
|
|
ISC_LIST_UNLINK(resps, resp, rlink);
|
|
|
|
resp->response(ISC_R_SHUTTINGDOWN, region, resp->arg);
|
|
|
|
dispentry_detach(&resp);
|
|
|
|
}
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
2021-08-03 18:24:27 -07:00
|
|
|
|
|
|
|
dns_dispatch_detach(&disp);
|
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) {
|
|
|
|
v4ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv4ports);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-12-09 15:45:13 -08:00
|
|
|
v6ports = NULL;
|
|
|
|
if (nv6ports != 0) {
|
|
|
|
v6ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv6ports);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
isc_mem_put(mgr->mctx, mgr->v4ports,
|
|
|
|
mgr->nv4ports * sizeof(in_port_t));
|
|
|
|
}
|
|
|
|
mgr->v4ports = v4ports;
|
|
|
|
mgr->nv4ports = nv4ports;
|
|
|
|
|
|
|
|
if (mgr->v6ports != NULL) {
|
|
|
|
isc_mem_put(mgr->mctx, mgr->v6ports,
|
|
|
|
mgr->nv6ports * sizeof(in_port_t));
|
|
|
|
}
|
|
|
|
mgr->v6ports = v6ports;
|
|
|
|
mgr->nv6ports = nv6ports;
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-06-30 01:33:11 +00:00
|
|
|
/*
|
|
|
|
* Publics.
|
|
|
|
*/
|
|
|
|
|
1999-07-22 01:34:31 +00:00
|
|
|
isc_result_t
|
2021-01-14 13:02:57 -08:00
|
|
|
dns_dispatchmgr_create(isc_mem_t *mctx, isc_nm_t *nm,
|
|
|
|
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));
|
2021-01-14 13:02:57 -08:00
|
|
|
*mgr = (dns_dispatchmgr_t){ .magic = 0 };
|
|
|
|
|
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);
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_nm_attach(nm, &mgr->nm);
|
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
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&mgr->lock);
|
2021-05-12 21:16:17 +02:00
|
|
|
|
2000-05-10 21:34:50 +00:00
|
|
|
ISC_LIST_INIT(mgr->list);
|
2021-05-12 21:16:17 +02:00
|
|
|
|
2021-10-04 14:11:57 +02:00
|
|
|
create_default_portset(mctx, AF_INET, &v4portset);
|
|
|
|
create_default_portset(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
|
|
|
|
2020-12-09 15:45:13 -08:00
|
|
|
isc_portset_destroy(mctx, &v4portset);
|
|
|
|
isc_portset_destroy(mctx, &v6portset);
|
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
|
|
|
|
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
|
|
|
qid_allocate(mgr, &mgr->qid);
|
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;
|
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-10 21:34:50 +00:00
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
void
|
2021-09-09 15:25:08 -07:00
|
|
|
dns_dispatchmgr_attach(dns_dispatchmgr_t *mgr, dns_dispatchmgr_t **mgrp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
|
|
|
REQUIRE(mgrp != NULL && *mgrp == NULL);
|
|
|
|
|
2021-09-09 15:25:08 -07:00
|
|
|
isc_refcount_increment(&mgr->references);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
|
|
|
*mgrp = mgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-09-09 15:25:08 -07:00
|
|
|
dns_dispatchmgr_detach(dns_dispatchmgr_t **mgrp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispatchmgr_t *mgr = NULL;
|
|
|
|
uint_fast32_t ref;
|
|
|
|
|
|
|
|
REQUIRE(mgrp != NULL && VALID_DISPATCHMGR(*mgrp));
|
|
|
|
|
|
|
|
mgr = *mgrp;
|
|
|
|
*mgrp = NULL;
|
|
|
|
|
|
|
|
ref = isc_refcount_decrement(&mgr->references);
|
|
|
|
if (ref == 1) {
|
|
|
|
dispatchmgr_destroy(mgr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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));
|
2001-02-09 00:23:16 +00: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));
|
2020-12-09 15:45:13 -08: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;
|
|
|
|
isc_mutex_destroy(&mgr->lock);
|
|
|
|
mgr->state = 0;
|
2000-05-10 21:34:50 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
qid_destroy(mgr->mctx, &mgr->qid);
|
|
|
|
|
|
|
|
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) {
|
|
|
|
isc_mem_put(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) {
|
|
|
|
isc_mem_put(mgr->mctx, mgr->v6ports,
|
|
|
|
mgr->nv6ports * sizeof(in_port_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_nm_detach(&mgr->nm);
|
|
|
|
|
|
|
|
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(ISC_LIST_EMPTY(mgr->list));
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_qid_t *qid = NULL;
|
2000-09-18 04:50:05 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
REQUIRE(qidp != NULL && *qidp == NULL);
|
2000-09-19 06:59:28 +00:00
|
|
|
|
|
|
|
qid = isc_mem_get(mgr->mctx, sizeof(*qid));
|
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
|
|
|
*qid = (dns_qid_t){ .qid_nbuckets = DNS_QID_BUCKETS,
|
|
|
|
.qid_increment = DNS_QID_INCREMENT };
|
2000-09-18 04:50:05 +00:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
qid->qid_table = isc_mem_get(mgr->mctx,
|
Dispatch API simplification
- Many dispatch attributes can be set implicitly instead of being passed
in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from
whether we're calling dns_dispatch_createtcp() or _createudp(). we
can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or
the socket that were passed in.
- We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket'
parameter has been removed from dns_dispatch_createudp(), along with
the code implementing it. also removed isc_socket_dup() since it no
longer has any callers.
- The 'buffersize' parameter was ignored and has now been removed;
buffersize is now fixed at 4096.
- Maxbuffers and maxrequests don't need to be passed in on every call to
dns_dispatch_createtcp() and _createudp().
In all current uses, the value for mgr->maxbuffers will either be
raised once from its default of 20000 to 32768, or else left
alone. (passing in a value lower than 20000 does not lower it.) there
isn't enough difference between these values for there to be any need
to configure this.
The value for disp->maxrequests controls both the quota of concurrent
requests for a dispatch and also the size of the dispatch socket
memory pool. it's not clear that this quota is necessary at all. the
memory pool size currently starts at 32768, but is sometimes lowered
to 4096, which is definitely unnecessary.
This commit sets both values permanently to 32768.
- Previously TCP dispatches allocated their own separate QID table,
which didn't incorporate a port table. this commit removes
per-dispatch QID tables and shares the same table between all
dispatches. since dispatches are created for each TCP socket, this may
speed up the dispatch allocation process. there may be a slight
increase in lock contention since all dispatches are sharing a single
QID table, but since TCP sockets are used less often than UDP
sockets (which were already sharing a QID table), it should not be a
substantial change.
- The dispatch port table was being used to determine whether a port was
already in use; if so, then a UDP socket would be bound with
REUSEADDR. this commit removes the port table, and always binds UDP
sockets that way.
2020-12-17 00:43:00 -08:00
|
|
|
DNS_QID_BUCKETS * sizeof(dns_displist_t));
|
|
|
|
for (i = 0; i < qid->qid_nbuckets; i++) {
|
2000-09-18 04:50:05 +00:00
|
|
|
ISC_LIST_INIT(qid->qid_table[i]);
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
2000-09-18 04:50:05 +00:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
isc_mutex_init(&qid->lock);
|
2000-09-18 04:50:05 +00:00
|
|
|
qid->magic = QID_MAGIC;
|
|
|
|
*qidp = qid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_qid_t *qid = NULL;
|
2000-09-18 04:50:05 +00:00
|
|
|
|
|
|
|
REQUIRE(qidp != NULL);
|
|
|
|
qid = *qidp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*qidp = NULL;
|
2000-09-18 04:50:05 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_QID(qid));
|
|
|
|
|
|
|
|
qid->magic = 0;
|
2000-09-19 06:59:28 +00:00
|
|
|
isc_mem_put(mctx, qid->qid_table,
|
2000-09-18 04:50:05 +00:00
|
|
|
qid->qid_nbuckets * sizeof(dns_displist_t));
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&qid->lock);
|
2000-09-19 06:59:28 +00:00
|
|
|
isc_mem_put(mctx, qid, sizeof(*qid));
|
2000-09-18 04:50:05 +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
|
2021-08-03 18:24:27 -07:00
|
|
|
dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type,
|
|
|
|
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));
|
2021-05-25 22:54:17 -07:00
|
|
|
*disp = (dns_dispatch_t){ .socktype = type };
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispatchmgr_attach(mgr, &disp->mgr);
|
|
|
|
isc_refcount_init(&disp->references, 1);
|
2000-05-10 21:34:50 +00:00
|
|
|
ISC_LINK_INIT(disp, link);
|
2021-05-25 22:54:17 -07:00
|
|
|
ISC_LIST_INIT(disp->active);
|
2021-08-03 18:24:27 -07:00
|
|
|
ISC_LIST_INIT(disp->pending);
|
2020-12-18 14:59:50 -08:00
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&disp->lock);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
1999-06-18 23:54:59 +00:00
|
|
|
disp->magic = DISPATCH_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
|
|
|
*dispp = disp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-01-17 14:18:27 +00:00
|
|
|
* MUST be unlocked, and not used by anything.
|
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_free(dns_dispatch_t **dispp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
|
|
|
dns_dispatchmgr_t *mgr = 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_DISPATCH(*dispp));
|
|
|
|
disp = *dispp;
|
|
|
|
*dispp = NULL;
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
disp->magic = 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
|
|
|
mgr = disp->mgr;
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
|
|
|
|
|
|
|
INSIST(disp->requests == 0);
|
2021-05-25 22:54:17 -07:00
|
|
|
INSIST(ISC_LIST_EMPTY(disp->active));
|
2021-01-14 13:02:57 -08:00
|
|
|
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&disp->lock);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-05-12 21:16:17 +02:00
|
|
|
isc_mem_put(mgr->mctx, disp, sizeof(*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
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
|
2021-08-03 18:24:27 -07:00
|
|
|
const isc_sockaddr_t *destaddr, isc_dscp_t dscp,
|
|
|
|
dns_dispatch_t **dispp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
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
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
UNUSED(dscp);
|
|
|
|
|
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
|
|
|
LOCK(&mgr->lock);
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
dispatch_allocate(mgr, isc_socktype_tcp, &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
|
|
|
disp->peer = *destaddr;
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
2021-08-03 18:24:27 -07:00
|
|
|
|
|
|
|
/* FIXME: There should be a lookup hashtable here */
|
2000-05-10 21:34:50 +00:00
|
|
|
ISC_LIST_APPEND(mgr->list, disp, link);
|
|
|
|
UNLOCK(&mgr->lock);
|
1999-07-12 23:44:31 +00:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
mgr_log(mgr, LVL(90), "dns_dispatch_createtcp: created TCP dispatch %p",
|
|
|
|
disp);
|
1999-06-18 23:54:59 +00:00
|
|
|
*dispp = disp;
|
1999-06-30 01:33:11 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
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,
|
2018-04-17 08:29:14 -07:00
|
|
|
const isc_sockaddr_t *localaddr, bool *connected,
|
2020-02-13 14:44:37 -08:00
|
|
|
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;
|
2015-01-20 17:22:31 -08:00
|
|
|
|
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
|
|
|
REQUIRE(destaddr != NULL);
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(connected != NULL);
|
2015-01-20 17:22:31 -08:00
|
|
|
REQUIRE(dispp != NULL && *dispp == NULL);
|
|
|
|
|
|
|
|
LOCK(&mgr->lock);
|
2021-08-04 13:14:11 -07:00
|
|
|
|
|
|
|
for (dns_dispatch_t *disp = ISC_LIST_HEAD(mgr->list); disp != NULL;
|
2021-08-03 18:24:27 -07:00
|
|
|
disp = ISC_LIST_NEXT(disp, link))
|
|
|
|
{
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_sockaddr_t sockname;
|
|
|
|
isc_sockaddr_t peeraddr;
|
|
|
|
|
2015-01-20 17:22:31 -08:00
|
|
|
LOCK(&disp->lock);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
|
|
|
if (disp->handle != NULL) {
|
|
|
|
sockname = isc_nmhandle_localaddr(disp->handle);
|
|
|
|
peeraddr = isc_nmhandle_peeraddr(disp->handle);
|
|
|
|
} else {
|
|
|
|
sockname = disp->local;
|
|
|
|
peeraddr = disp->peer;
|
|
|
|
}
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
/*
|
|
|
|
* The conditions match:
|
|
|
|
* 1. socktype is TCP
|
|
|
|
* 2. destination address is same
|
|
|
|
* 3. local address is either NULL or same
|
|
|
|
*/
|
2021-08-04 13:14:11 -07:00
|
|
|
if (disp->socktype == isc_socktype_tcp &&
|
|
|
|
isc_sockaddr_equal(destaddr, &peeraddr) &&
|
|
|
|
(localaddr == NULL ||
|
|
|
|
isc_sockaddr_eqaddr(localaddr, &sockname)))
|
|
|
|
{
|
|
|
|
if (atomic_load(&disp->state) ==
|
|
|
|
DNS_DISPATCHSTATE_CONNECTED) {
|
|
|
|
/* We found connected dispatch */
|
|
|
|
disp_connected = disp;
|
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We found "a" dispatch, store it for later */
|
|
|
|
if (disp_fallback == NULL) {
|
|
|
|
disp_fallback = disp;
|
|
|
|
}
|
|
|
|
|
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-01-20 17:22:31 -08:00
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
}
|
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
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
*connected = true;
|
|
|
|
dns_dispatch_attach(disp_connected, dispp);
|
|
|
|
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
} else if (disp_fallback != NULL) {
|
|
|
|
/* We found matching dispatch */
|
2021-08-03 18:24:27 -07:00
|
|
|
*connected = false;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
|
|
|
dns_dispatch_attach(disp_fallback, dispp);
|
|
|
|
|
|
|
|
result = ISC_R_SUCCESS;
|
2015-01-20 17:22:31 -08:00
|
|
|
}
|
2020-12-18 14:59:50 -08:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
UNLOCK(&mgr->lock);
|
2021-08-04 13:14:11 -07: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);
|
|
|
|
|
|
|
|
LOCK(&mgr->lock);
|
2021-08-03 18:24:27 -07:00
|
|
|
result = dispatch_createudp(mgr, localaddr, &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
|
|
|
}
|
|
|
|
UNLOCK(&mgr->lock);
|
2020-12-18 14:59:50 -08: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,
|
2021-08-03 18:24:27 -07:00
|
|
|
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
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
dispatch_allocate(mgr, isc_socktype_udp, &disp);
|
2015-02-10 13:54:03 -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) {
|
2021-01-14 13:02:57 -08:00
|
|
|
goto cleanup;
|
2018-11-08 19:34:51 -08:00
|
|
|
}
|
2020-12-16 01:32:06 -08:00
|
|
|
}
|
2011-07-28 04:04:37 +00:00
|
|
|
|
2020-12-16 01:32:06 -08:00
|
|
|
if (isc_log_wouldlog(dns_lctx, 90)) {
|
|
|
|
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);
|
|
|
|
mgr_log(mgr, LVL(90),
|
|
|
|
"dispatch_createudp: created UDP dispatch for %s",
|
|
|
|
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
|
|
|
|
|
|
|
/*
|
|
|
|
* Append it to the dispatcher list.
|
|
|
|
*/
|
|
|
|
ISC_LIST_APPEND(mgr->list, disp, link);
|
|
|
|
|
|
|
|
mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
|
|
|
|
|
|
|
|
*dispp = disp;
|
2011-07-28 04:04:37 +00:00
|
|
|
|
2008-06-23 19:41:20 +00: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
|
|
|
|
|
|
|
/*
|
|
|
|
* Error returns.
|
|
|
|
*/
|
2021-01-14 13:02:57 -08:00
|
|
|
cleanup:
|
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
|
|
|
dispatch_free(&disp);
|
2008-06-23 19:41:20 +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
|
|
|
return (result);
|
1999-06-16 01:32:31 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
LOCK(&mgr->lock);
|
|
|
|
ISC_LIST_UNLINK(mgr->list, disp, link);
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
|
|
|
|
dispatch_log(disp, LVL(90), "shutting down; detaching from handle %p",
|
|
|
|
disp->handle);
|
|
|
|
|
|
|
|
if (disp->handle != NULL) {
|
|
|
|
isc_nmhandle_detach(&disp->handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
dispatch_free(&disp);
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
/*
|
|
|
|
* Because dispatch uses mgr->mctx, we must detach after freeing
|
|
|
|
* dispatch, not before.
|
2021-05-25 22:54:17 -07:00
|
|
|
*/
|
|
|
|
dns_dispatchmgr_detach(&mgr);
|
|
|
|
}
|
|
|
|
|
1999-06-18 23:54:59 +00:00
|
|
|
void
|
2021-09-09 15:25:08 -07:00
|
|
|
dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {
|
1999-07-13 00:25:21 +00:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
REQUIRE(dispp != NULL && *dispp == NULL);
|
|
|
|
|
2021-09-09 15:25:08 -07:00
|
|
|
isc_refcount_increment(&disp->references);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
1999-07-13 00:25:21 +00:00
|
|
|
*dispp = disp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-09-09 15:25:08 -07:00
|
|
|
dns_dispatch_detach(dns_dispatch_t **dispp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2021-05-25 22:54:17 -07:00
|
|
|
uint_fast32_t ref;
|
1999-06-18 23:54:59 +00:00
|
|
|
|
|
|
|
REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));
|
|
|
|
|
|
|
|
disp = *dispp;
|
|
|
|
*dispp = NULL;
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
ref = isc_refcount_decrement(&disp->references);
|
|
|
|
dispatch_log(disp, LVL(90), "detach: refcount %" PRIuFAST32, ref - 1);
|
|
|
|
if (ref == 1) {
|
|
|
|
LOCK(&disp->lock);
|
2021-08-03 18:24:27 -07:00
|
|
|
INSIST(ISC_LIST_EMPTY(disp->pending));
|
|
|
|
INSIST(ISC_LIST_EMPTY(disp->active));
|
2021-05-25 22:54:17 -07:00
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
dispatch_destroy(disp);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-06-16 01:32:31 +00:00
|
|
|
}
|
|
|
|
|
1999-07-22 01:34:31 +00:00
|
|
|
isc_result_t
|
2021-10-03 15:15:50 -07:00
|
|
|
dns_dispatch_add(dns_dispatch_t *disp, unsigned int options,
|
|
|
|
unsigned int timeout, const isc_sockaddr_t *dest,
|
|
|
|
dispatch_cb_t connected, dispatch_cb_t sent,
|
|
|
|
dispatch_cb_t response, void *arg, dns_messageid_t *idp,
|
|
|
|
dns_dispentry_t **resp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispentry_t *res = NULL;
|
2021-01-14 13:02:57 -08:00
|
|
|
dns_qid_t *qid = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t localport = 0;
|
|
|
|
dns_messageid_t id;
|
2021-01-14 13:02:57 -08:00
|
|
|
unsigned int bucket;
|
2020-12-09 19:44:41 -08:00
|
|
|
bool ok = false;
|
2021-01-14 13:02:57 -08:00
|
|
|
int i = 0;
|
2021-08-03 15:27:06 +02:00
|
|
|
dispatch_cb_t oldest_response = NULL;
|
1999-06-18 02:01:42 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
REQUIRE(dest != NULL);
|
|
|
|
REQUIRE(resp != NULL && *resp == NULL);
|
|
|
|
REQUIRE(idp != NULL);
|
2021-01-14 13:02:57 -08:00
|
|
|
REQUIRE(disp->socktype == isc_socktype_tcp ||
|
|
|
|
disp->socktype == isc_socktype_udp);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
|
|
|
LOCK(&disp->lock);
|
|
|
|
|
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
|
|
|
if (disp->requests >= DNS_DISPATCH_MAXREQUESTS) {
|
1999-07-09 02:47:55 +00:00
|
|
|
UNLOCK(&disp->lock);
|
1999-07-10 00:15:41 +00:00
|
|
|
return (ISC_R_QUOTA);
|
1999-07-09 02:47:55 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
qid = disp->mgr->qid;
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
if (disp->socktype == isc_socktype_udp &&
|
2020-02-13 14:44:37 -08:00
|
|
|
disp->nsockets > DNS_DISPATCH_SOCKSQUOTA)
|
|
|
|
{
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispentry_t *oldest = NULL;
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Kill oldest outstanding query if the number of sockets
|
|
|
|
* exceeds the quota to keep the room for new queries.
|
|
|
|
*/
|
2021-05-25 22:54:17 -07:00
|
|
|
oldest = ISC_LIST_HEAD(disp->active);
|
|
|
|
if (oldest != NULL) {
|
2021-07-26 20:23:18 -07:00
|
|
|
oldest_response = oldest->response;
|
2020-12-09 19:44:41 -08:00
|
|
|
inc_stats(disp->mgr, dns_resstatscounter_dispabort);
|
2008-06-23 19:41:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
res = isc_mem_get(disp->mgr->mctx, sizeof(*res));
|
|
|
|
|
|
|
|
*res = (dns_dispentry_t){ .port = localport,
|
|
|
|
.timeout = timeout,
|
|
|
|
.peer = *dest,
|
|
|
|
.connected = connected,
|
|
|
|
.sent = sent,
|
2021-07-26 20:23:18 -07:00
|
|
|
.response = response,
|
2021-05-25 22:54:17 -07:00
|
|
|
.arg = arg };
|
|
|
|
|
|
|
|
isc_refcount_init(&res->references, 1);
|
|
|
|
|
|
|
|
ISC_LINK_INIT(res, link);
|
|
|
|
ISC_LINK_INIT(res, alink);
|
2021-08-03 18:24:27 -07:00
|
|
|
ISC_LINK_INIT(res, plink);
|
2021-08-04 13:14:11 -07:00
|
|
|
ISC_LINK_INIT(res, rlink);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
if (disp->socktype == isc_socktype_udp) {
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_result_t result = setup_socket(disp, res, dest, &localport);
|
2008-06-23 19:41:20 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_mem_put(disp->mgr->mctx, res, sizeof(*res));
|
2008-06-23 19:41:20 +00:00
|
|
|
UNLOCK(&disp->lock);
|
2009-01-31 00:10:24 +00:00
|
|
|
inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
|
2008-06-23 19:41:20 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-18 02:01:42 +00:00
|
|
|
/*
|
2020-12-09 19:44:41 -08: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.
|
1999-06-18 02:01:42 +00:00
|
|
|
*/
|
2018-04-22 14:56:28 +02:00
|
|
|
if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
|
2014-10-01 07:24:16 +10:00
|
|
|
id = *idp;
|
2018-04-22 14:56:28 +02:00
|
|
|
} else {
|
2018-05-28 15:22:23 +02:00
|
|
|
id = (dns_messageid_t)isc_random16();
|
2018-04-22 14:56:28 +02:00
|
|
|
}
|
2020-12-09 19:44:41 -08:00
|
|
|
|
|
|
|
LOCK(&qid->lock);
|
2014-01-09 15:57:59 +11:00
|
|
|
do {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispentry_t *entry = NULL;
|
2013-12-23 09:50:18 -08:00
|
|
|
bucket = dns_hash(qid, dest, id, localport);
|
2020-12-09 19:44:41 -08:00
|
|
|
entry = entry_search(qid, dest, id, localport, bucket);
|
|
|
|
if (entry == NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ok = true;
|
1999-06-18 02:01:42 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-09-18 04:50:05 +00:00
|
|
|
id += qid->qid_increment;
|
1999-12-15 17:14:52 +00:00
|
|
|
id &= 0x0000ffff;
|
2014-01-09 15:57:59 +11:00
|
|
|
} while (i++ < 64);
|
2012-04-28 14:52:28 -07:00
|
|
|
UNLOCK(&qid->lock);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
|
|
|
if (!ok) {
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_mem_put(disp->mgr->mctx, res, sizeof(*res));
|
1999-06-18 02:01:42 +00:00
|
|
|
UNLOCK(&disp->lock);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMORE);
|
1999-06-18 02:01:42 +00:00
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispatch_attach(disp, &res->disp);
|
2021-01-14 13:02:57 -08:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
res->id = id;
|
|
|
|
res->bucket = bucket;
|
2020-12-09 19:44:41 -08:00
|
|
|
res->magic = RESPONSE_MAGIC;
|
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
|
|
|
|
2012-04-28 14:52:28 -07:00
|
|
|
LOCK(&qid->lock);
|
2000-09-18 04:50:05 +00:00
|
|
|
ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
|
|
|
|
UNLOCK(&qid->lock);
|
1999-06-18 02:01:42 +00: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
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
ISC_LIST_APPEND(disp->active, res, alink);
|
1999-07-09 00:51:08 +00:00
|
|
|
|
1999-06-18 02:01:42 +00:00
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
|
2021-07-26 20:23:18 -07:00
|
|
|
if (oldest_response != NULL) {
|
2021-08-03 15:27:06 +02:00
|
|
|
oldest_response(ISC_R_CANCELED, NULL, res->arg);
|
2021-05-25 22:54:17 -07:00
|
|
|
}
|
2020-12-16 01:32:06 -08:00
|
|
|
|
1999-06-18 02:01:42 +00:00
|
|
|
*idp = id;
|
|
|
|
*resp = res;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-06-16 01:32:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
void
|
|
|
|
dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, int32_t timeout) {
|
2021-10-18 12:49:40 -07:00
|
|
|
REQUIRE(timeout <= (int32_t)UINT16_MAX);
|
2021-08-03 18:24:27 -07:00
|
|
|
|
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_udp:
|
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
|
|
|
if (timeout > 0) {
|
|
|
|
isc_nmhandle_settimeout(resp->handle, timeout);
|
|
|
|
}
|
|
|
|
isc_nm_read(resp->handle, udp_recv, resp);
|
|
|
|
break;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
case isc_socktype_tcp:
|
|
|
|
dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL });
|
|
|
|
if (timeout > 0) {
|
|
|
|
isc_nmhandle_settimeout(disp->handle, timeout);
|
|
|
|
}
|
|
|
|
isc_nm_read(disp->handle, tcp_recv, disp);
|
|
|
|
break;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
default:
|
|
|
|
INSIST(0);
|
|
|
|
ISC_UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-11 13:36:16 +10:00
|
|
|
isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dns_dispatch_getnext(dns_dispentry_t *resp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2021-10-01 12:53:31 -07:00
|
|
|
int32_t timeout;
|
2016-07-11 13:36:16 +10:00
|
|
|
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
|
|
|
disp = resp->disp;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2016-07-11 13:36:16 +10:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
|
|
|
|
2021-10-01 12:53:31 -07:00
|
|
|
if (disp->socktype == isc_socktype_udp) {
|
|
|
|
timeout = resp->timeout - dispentry_runtime(resp);
|
|
|
|
if (timeout <= 0) {
|
|
|
|
return (ISC_R_TIMEDOUT);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
timeout = -1;
|
|
|
|
}
|
|
|
|
|
2016-07-11 13:36:16 +10:00
|
|
|
LOCK(&disp->lock);
|
2021-10-01 12:53:31 -07:00
|
|
|
dispatch_getnext(disp, resp, timeout);
|
2016-07-11 13:36:16 +10:00
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-06-18 02:01:42 +00:00
|
|
|
void
|
2021-10-03 15:15:50 -07:00
|
|
|
dns_dispatch_cancel(dns_dispentry_t **respp) {
|
|
|
|
dns_dispentry_t *resp = NULL;
|
2021-10-18 11:49:56 +02:00
|
|
|
dns_dispatch_t *disp = NULL;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
|
|
|
REQUIRE(respp != NULL);
|
|
|
|
|
|
|
|
resp = *respp;
|
2021-10-06 18:32:19 +11:00
|
|
|
*respp = NULL;
|
2021-10-03 15:15:50 -07:00
|
|
|
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
2021-10-18 11:49:56 +02:00
|
|
|
disp = resp->disp;
|
2021-10-03 15:15:50 -07:00
|
|
|
resp->canceled = true;
|
|
|
|
|
|
|
|
/* Connected UDP. */
|
|
|
|
if (resp->handle != NULL) {
|
|
|
|
isc_nm_cancelread(resp->handle);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2021-10-18 11:49:56 +02:00
|
|
|
LOCK(&disp->lock);
|
2021-10-03 15:15:50 -07:00
|
|
|
/* TCP pending connection. */
|
|
|
|
if (ISC_LINK_LINKED(resp, plink)) {
|
|
|
|
dns_dispentry_t *copy = resp;
|
|
|
|
|
2021-10-18 11:49:56 +02:00
|
|
|
ISC_LIST_UNLINK(disp->pending, resp, plink);
|
2021-10-03 15:15:50 -07:00
|
|
|
if (resp->connected != NULL) {
|
|
|
|
resp->connected(ISC_R_CANCELED, NULL, resp->arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to detach twice if we were pending
|
|
|
|
* connection - once to take the place of the
|
|
|
|
* detach in tcp_connected() or udp_connected()
|
|
|
|
* that we won't reach, and again later in
|
|
|
|
* dns_dispatch_done().
|
|
|
|
*/
|
|
|
|
dispentry_detach(©);
|
2021-10-18 11:49:56 +02:00
|
|
|
UNLOCK(&disp->lock);
|
2021-10-03 15:15:50 -07:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Connected TCP, or unconnected UDP.
|
|
|
|
*
|
|
|
|
* If TCP, we don't want to cancel the dispatch
|
|
|
|
* unless this is the last resp waiting.
|
|
|
|
*/
|
|
|
|
if (ISC_LINK_LINKED(resp, alink)) {
|
2021-10-18 11:49:56 +02:00
|
|
|
ISC_LIST_UNLINK(disp->active, resp, alink);
|
|
|
|
if (ISC_LIST_EMPTY(disp->active) && disp->handle != NULL) {
|
|
|
|
isc_nm_cancelread(disp->handle);
|
2021-10-03 15:15:50 -07:00
|
|
|
} else if (resp->response != NULL) {
|
|
|
|
resp->response(ISC_R_CANCELED, NULL, resp->arg);
|
|
|
|
}
|
|
|
|
}
|
2021-10-18 11:49:56 +02:00
|
|
|
UNLOCK(&disp->lock);
|
2021-10-03 15:15:50 -07:00
|
|
|
|
|
|
|
done:
|
2021-10-06 18:32:19 +11:00
|
|
|
dns_dispatch_done(&resp);
|
2021-10-03 15:15:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_dispatch_done(dns_dispentry_t **respp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatchmgr_t *mgr = NULL;
|
|
|
|
dns_dispatch_t *disp = NULL;
|
2021-05-25 22:54:17 -07:00
|
|
|
dns_dispentry_t *resp = NULL;
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_qid_t *qid = NULL;
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
REQUIRE(respp != NULL);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
resp = *respp;
|
|
|
|
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
|
|
|
disp = resp->disp;
|
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
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
2021-01-14 13:02:57 -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
|
|
|
mgr = disp->mgr;
|
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
|
|
|
REQUIRE(VALID_DISPATCHMGR(mgr));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
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
|
|
|
qid = mgr->qid;
|
2000-09-18 04:50:05 +00:00
|
|
|
|
1999-06-18 02:01:42 +00:00
|
|
|
LOCK(&disp->lock);
|
1999-07-09 00:51:08 +00:00
|
|
|
INSIST(disp->requests > 0);
|
|
|
|
disp->requests--;
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
dec_stats(disp->mgr, (disp->socktype == isc_socktype_udp)
|
2020-02-12 13:59:18 +01:00
|
|
|
? dns_resstatscounter_disprequdp
|
|
|
|
: dns_resstatscounter_dispreqtcp);
|
2020-12-09 19:44:41 -08:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
deactivate_dispentry(disp, resp);
|
1999-06-18 02:01:42 +00:00
|
|
|
|
2000-09-18 04:50:05 +00:00
|
|
|
LOCK(&qid->lock);
|
2021-05-25 22:54:17 -07:00
|
|
|
ISC_LIST_UNLINK(qid->qid_table[resp->bucket], resp, link);
|
2000-09-18 04:50:05 +00:00
|
|
|
UNLOCK(&qid->lock);
|
2021-05-25 22:54:17 -07:00
|
|
|
UNLOCK(&disp->lock);
|
1999-07-09 00:51:08 +00:00
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
dispentry_detach(respp);
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* disp must be locked.
|
|
|
|
*/
|
|
|
|
static void
|
2021-08-03 18:24:27 -07:00
|
|
|
startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp, dns_dispentry_t *resp) {
|
2021-01-14 13:02:57 -08:00
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_udp:
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(resp != NULL && resp->handle == NULL);
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-10-01 12:53:31 -07:00
|
|
|
TIME_NOW(&resp->start);
|
2021-08-03 18:24:27 -07:00
|
|
|
isc_nmhandle_attach(handle, &resp->handle);
|
2021-07-26 20:23:18 -07:00
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nm_read(resp->handle, udp_recv, resp);
|
|
|
|
break;
|
2021-07-26 20:23:18 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
case isc_socktype_tcp:
|
2021-08-04 13:14:11 -07:00
|
|
|
REQUIRE(disp != NULL);
|
|
|
|
LOCK(&disp->lock);
|
|
|
|
REQUIRE(disp->handle == NULL);
|
2021-10-20 11:39:13 -07:00
|
|
|
REQUIRE(atomic_compare_exchange_strong(
|
|
|
|
&disp->state,
|
|
|
|
&(uint_fast32_t){ DNS_DISPATCHSTATE_CONNECTING },
|
|
|
|
DNS_DISPATCHSTATE_CONNECTED));
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
isc_nmhandle_attach(handle, &disp->handle);
|
|
|
|
dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL });
|
|
|
|
isc_nm_read(disp->handle, tcp_recv, disp);
|
2021-08-04 13:14:11 -07:00
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
break;
|
2021-07-26 20:23:18 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
default:
|
2020-12-19 01:34:41 -08:00
|
|
|
INSIST(0);
|
|
|
|
ISC_UNREACHABLE();
|
|
|
|
}
|
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;
|
|
|
|
dns_dispentry_t *resp = NULL, *next = NULL;
|
|
|
|
dns_displist_t resps;
|
|
|
|
|
|
|
|
dispatch_log(disp, LVL(90), "TCP connected (%p): %s", disp,
|
|
|
|
isc_result_totext(eresult));
|
|
|
|
|
|
|
|
ISC_LIST_INIT(resps);
|
|
|
|
|
|
|
|
if (MGR_IS_SHUTTINGDOWN(disp->mgr)) {
|
|
|
|
eresult = ISC_R_SHUTTINGDOWN;
|
|
|
|
}
|
2021-01-14 13:02:57 -08:00
|
|
|
|
|
|
|
if (eresult == ISC_R_SUCCESS) {
|
2021-08-04 13:14:11 -07:00
|
|
|
startrecv(handle, disp, NULL);
|
|
|
|
}
|
2021-08-03 18:24:27 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
/*
|
|
|
|
* If there are pending responses, call the connect
|
|
|
|
* callbacks for all of them.
|
|
|
|
*/
|
|
|
|
LOCK(&disp->lock);
|
|
|
|
for (resp = ISC_LIST_HEAD(disp->pending); resp != NULL; resp = next) {
|
|
|
|
next = ISC_LIST_NEXT(resp, plink);
|
|
|
|
ISC_LIST_UNLINK(disp->pending, resp, plink);
|
|
|
|
ISC_LIST_APPEND(resps, resp, plink);
|
|
|
|
}
|
|
|
|
UNLOCK(&disp->lock);
|
2021-08-03 18:24:27 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) {
|
|
|
|
next = ISC_LIST_NEXT(resp, plink);
|
|
|
|
ISC_LIST_UNLINK(resps, resp, plink);
|
|
|
|
|
|
|
|
if (resp->connected != NULL) {
|
|
|
|
resp->connected(eresult, NULL, resp->arg);
|
|
|
|
}
|
|
|
|
dispentry_detach(&resp);
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
2020-12-19 01:34:41 -08:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
dns_dispatch_detach(&disp);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
dispatch_log(disp, LVL(90), "UDP connected (%p): %s", resp,
|
|
|
|
isc_result_totext(eresult));
|
|
|
|
|
2021-07-26 20:23:18 -07:00
|
|
|
if (MGR_IS_SHUTTINGDOWN(disp->mgr)) {
|
|
|
|
eresult = ISC_R_SHUTTINGDOWN;
|
|
|
|
}
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (eresult == ISC_R_SUCCESS && resp->canceled) {
|
|
|
|
eresult = ISC_R_CANCELED;
|
|
|
|
} else if (eresult == ISC_R_SUCCESS) {
|
|
|
|
startrecv(handle, disp, resp);
|
|
|
|
} else if (eresult == ISC_R_ADDRINUSE) {
|
|
|
|
in_port_t localport = 0;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
/* probably a port collision; try a different one */
|
|
|
|
disp->nsockets--;
|
|
|
|
result = setup_socket(disp, resp, &resp->peer, &localport);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
dns_dispatch_connect(resp);
|
|
|
|
goto detach;
|
|
|
|
}
|
2021-01-14 13:02:57 -08:00
|
|
|
}
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
if (resp->connected != NULL) {
|
|
|
|
resp->connected(eresult, NULL, resp->arg);
|
2021-08-03 18:24:27 -07:00
|
|
|
}
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
detach:
|
2021-05-25 22:54:17 -07:00
|
|
|
dispentry_detach(&resp);
|
2020-12-19 01:34:41 -08:00
|
|
|
}
|
|
|
|
|
2021-01-04 23:03:50 -08:00
|
|
|
isc_result_t
|
2021-01-14 13:02:57 -08:00
|
|
|
dns_dispatch_connect(dns_dispentry_t *resp) {
|
|
|
|
dns_dispatch_t *disp = NULL;
|
2021-08-03 18:24:27 -07:00
|
|
|
uint_fast32_t state = DNS_DISPATCHSTATE_NONE;
|
2021-01-04 23:03:50 -08:00
|
|
|
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
disp = resp->disp;
|
|
|
|
|
2021-08-04 13:14:11 -07:00
|
|
|
/* This will be detached once we've connected. */
|
2021-08-03 18:24:27 -07:00
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
2021-05-25 22:54:17 -07:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
switch (disp->socktype) {
|
|
|
|
case isc_socktype_tcp:
|
2021-08-03 18:24:27 -07:00
|
|
|
/*
|
2021-08-04 13:14:11 -07:00
|
|
|
* Check whether the dispatch is already connecting
|
|
|
|
* or connected.
|
2021-08-03 18:24:27 -07:00
|
|
|
*/
|
|
|
|
atomic_compare_exchange_strong(&disp->state,
|
|
|
|
(uint_fast32_t *)&state,
|
|
|
|
DNS_DISPATCHSTATE_CONNECTING);
|
|
|
|
switch (state) {
|
|
|
|
case DNS_DISPATCHSTATE_NONE:
|
|
|
|
/* First connection, continue with connecting */
|
2021-08-04 13:14:11 -07:00
|
|
|
LOCK(&disp->lock);
|
|
|
|
INSIST(ISC_LIST_EMPTY(disp->pending));
|
|
|
|
ISC_LIST_APPEND(disp->pending, resp, plink);
|
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL });
|
2021-08-03 18:24:27 -07:00
|
|
|
isc_nm_tcpdnsconnect(disp->mgr->nm, &disp->local,
|
2021-08-04 13:14:11 -07:00
|
|
|
&disp->peer, tcp_connected, disp,
|
2021-08-03 18:24:27 -07:00
|
|
|
resp->timeout, 0);
|
|
|
|
break;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTING:
|
2021-08-04 13:14:11 -07:00
|
|
|
/* Connection pending; add resp to the list */
|
|
|
|
LOCK(&disp->lock);
|
2021-08-03 18:24:27 -07:00
|
|
|
ISC_LIST_APPEND(disp->pending, resp, plink);
|
2021-08-04 13:14:11 -07:00
|
|
|
UNLOCK(&disp->lock);
|
|
|
|
break;
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
case DNS_DISPATCHSTATE_CONNECTED:
|
2021-08-04 13:14:11 -07:00
|
|
|
/* We are already connected; call the connected cb */
|
2021-08-03 18:24:27 -07:00
|
|
|
if (resp->connected != NULL) {
|
|
|
|
resp->connected(ISC_R_SUCCESS, NULL, resp->arg);
|
|
|
|
}
|
2021-08-04 13:14:11 -07:00
|
|
|
dispentry_detach(&resp);
|
|
|
|
break;
|
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
default:
|
|
|
|
INSIST(0);
|
|
|
|
ISC_UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
case isc_socktype_udp:
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nm_udpconnect(disp->mgr->nm, &resp->local, &resp->peer,
|
2021-08-04 13:14:11 -07:00
|
|
|
udp_connected, resp, resp->timeout, 0);
|
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:
|
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
|
|
|
}
|
2021-01-04 23:03:50 -08:00
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
|
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) {
|
|
|
|
isc_nm_cancelread(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
dispentry_detach(&resp);
|
|
|
|
}
|
|
|
|
|
2021-08-03 15:27:06 +02:00
|
|
|
void
|
2021-08-03 18:24:27 -07:00
|
|
|
dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
|
|
|
|
dns_dispatch_t *disp = NULL;
|
2021-08-04 13:14:11 -07:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
2021-08-03 15:27:06 +02:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
disp = resp->disp;
|
2021-08-03 15:27:06 +02:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
REQUIRE(VALID_DISPATCH(disp));
|
2021-08-03 15:27:06 +02:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
dispatch_getnext(disp, resp, timeout);
|
2021-08-03 15:27:06 +02:00
|
|
|
}
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
void
|
|
|
|
dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp) {
|
|
|
|
isc_nmhandle_t *handle = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_RESPONSE(resp));
|
|
|
|
|
|
|
|
UNUSED(dscp);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* XXX: no DSCP support */
|
2021-01-04 23:03:50 -08:00
|
|
|
if (dscp == -1) {
|
|
|
|
sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
|
|
|
|
sendevent->dscp = 0;
|
|
|
|
} else {
|
|
|
|
sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
|
|
|
|
sendevent->dscp = dscp;
|
|
|
|
if (tcp) {
|
|
|
|
isc_socket_dscp(sock, dscp);
|
|
|
|
}
|
|
|
|
}
|
2021-01-14 13:02:57 -08:00
|
|
|
#endif
|
2021-01-04 23:03:50 -08:00
|
|
|
|
2021-08-03 18:24:27 -07:00
|
|
|
if (resp->disp->socktype == isc_socktype_tcp) {
|
|
|
|
handle = resp->disp->handle;
|
|
|
|
} else {
|
|
|
|
handle = resp->handle;
|
|
|
|
}
|
|
|
|
|
2021-07-26 20:23:18 -07:00
|
|
|
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
|
2021-05-25 22:54:17 -07:00
|
|
|
isc_nm_send(handle, 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;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
REQUIRE(addrp != NULL);
|
|
|
|
|
2021-01-14 13:02:57 -08:00
|
|
|
if (resp->disp->socktype == isc_socktype_tcp) {
|
|
|
|
*addrp = resp->disp->local;
|
|
|
|
return (ISC_R_SUCCESS);
|
2021-01-04 14:38:35 -08:00
|
|
|
}
|
|
|
|
|
2021-05-25 22:54:17 -07:00
|
|
|
if (resp->handle != NULL) {
|
|
|
|
*addrp = isc_nmhandle_localaddr(resp->handle);
|
2021-01-14 13:02:57 -08:00
|
|
|
return (ISC_R_SUCCESS);
|
2021-01-04 14:38:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
|
|
|
}
|
|
|
|
|
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) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatch_t *disp = NULL;
|
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) {
|
2012-04-27 16:07:24 -07:00
|
|
|
return (NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
|
|
|
|
LOCK(&dset->lock);
|
|
|
|
disp = dset->dispatches[dset->cur];
|
|
|
|
dset->cur++;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dset->cur == dset->ndisp) {
|
2012-04-27 16:07:24 -07:00
|
|
|
dset->cur = 0;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
UNLOCK(&dset->lock);
|
|
|
|
|
|
|
|
return (disp);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2021-07-26 20:23:18 -07:00
|
|
|
dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
|
|
|
|
dns_dispatchset_t **dsetp, int n) {
|
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;
|
2020-02-13 14:44:37 -08:00
|
|
|
int i, j;
|
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));
|
2020-12-09 19:44:41 -08:00
|
|
|
*dset = (dns_dispatchset_t){ .ndisp = n };
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&dset->lock);
|
2012-04-27 16:07:24 -07:00
|
|
|
|
|
|
|
dset->dispatches = isc_mem_get(mctx, sizeof(dns_dispatch_t *) * n);
|
|
|
|
|
|
|
|
isc_mem_attach(mctx, &dset->mctx);
|
|
|
|
|
|
|
|
dset->dispatches[0] = NULL;
|
|
|
|
dns_dispatch_attach(source, &dset->dispatches[0]);
|
|
|
|
|
|
|
|
LOCK(&mgr->lock);
|
|
|
|
for (i = 1; i < n; i++) {
|
|
|
|
dset->dispatches[i] = NULL;
|
2021-07-26 20:23:18 -07:00
|
|
|
result = dispatch_createudp(mgr, &source->local,
|
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
|
|
|
}
|
|
|
|
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
*dsetp = dset;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
fail:
|
2012-04-27 16:07:24 -07:00
|
|
|
UNLOCK(&mgr->lock);
|
2012-04-28 23:45:42 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
for (j = 0; j < i; j++) {
|
2012-04-27 16:07:24 -07:00
|
|
|
dns_dispatch_detach(&(dset->dispatches[j]));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
isc_mem_put(mctx, dset->dispatches, sizeof(dns_dispatch_t *) * n);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dset->mctx == mctx) {
|
2012-04-27 16:07:24 -07:00
|
|
|
isc_mem_detach(&dset->mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&dset->lock);
|
2012-04-27 16:07:24 -07:00
|
|
|
isc_mem_put(mctx, dset, sizeof(dns_dispatchset_t));
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
|
2020-12-09 19:44:41 -08:00
|
|
|
dns_dispatchset_t *dset = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
int i;
|
2012-04-27 16:07:24 -07:00
|
|
|
|
|
|
|
REQUIRE(dsetp != NULL && *dsetp != NULL);
|
|
|
|
|
|
|
|
dset = *dsetp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*dsetp = NULL;
|
2020-02-13 21:48:23 +01:00
|
|
|
for (i = 0; i < dset->ndisp; i++) {
|
2012-04-27 16:07:24 -07:00
|
|
|
dns_dispatch_detach(&(dset->dispatches[i]));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-04-27 16:07:24 -07:00
|
|
|
isc_mem_put(dset->mctx, dset->dispatches,
|
|
|
|
sizeof(dns_dispatch_t *) * dset->ndisp);
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&dset->lock);
|
2012-04-27 16:07:24 -07:00
|
|
|
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
|
|
|
|
}
|