Home | History | Annotate | Line # | Download | only in dns
dispatch.c revision 1.1
      1 /*	$NetBSD: dispatch.c,v 1.1 2024/02/18 20:57:31 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <inttypes.h>
     19 #include <stdbool.h>
     20 #include <stdlib.h>
     21 #include <sys/types.h>
     22 #include <unistd.h>
     23 
     24 #include <isc/mem.h>
     25 #include <isc/mutex.h>
     26 #include <isc/portset.h>
     27 #include <isc/print.h>
     28 #include <isc/random.h>
     29 #include <isc/socket.h>
     30 #include <isc/stats.h>
     31 #include <isc/string.h>
     32 #include <isc/task.h>
     33 #include <isc/time.h>
     34 #include <isc/util.h>
     35 
     36 #include <dns/acl.h>
     37 #include <dns/dispatch.h>
     38 #include <dns/events.h>
     39 #include <dns/log.h>
     40 #include <dns/message.h>
     41 #include <dns/portlist.h>
     42 #include <dns/stats.h>
     43 #include <dns/tcpmsg.h>
     44 #include <dns/types.h>
     45 
     46 typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
     47 
     48 typedef struct dispsocket dispsocket_t;
     49 typedef ISC_LIST(dispsocket_t) dispsocketlist_t;
     50 
     51 typedef struct dispportentry dispportentry_t;
     52 typedef ISC_LIST(dispportentry_t) dispportlist_t;
     53 
     54 typedef struct dns_qid {
     55 	unsigned int magic;
     56 	unsigned int qid_nbuckets;  /*%< hash table size */
     57 	unsigned int qid_increment; /*%< id increment on collision */
     58 	isc_mutex_t lock;
     59 	dns_displist_t *qid_table;    /*%< the table itself */
     60 	dispsocketlist_t *sock_table; /*%< socket table */
     61 } dns_qid_t;
     62 
     63 struct dns_dispatchmgr {
     64 	/* Unlocked. */
     65 	unsigned int magic;
     66 	isc_mem_t *mctx;
     67 	dns_acl_t *blackhole;
     68 	dns_portlist_t *portlist;
     69 	isc_stats_t *stats;
     70 
     71 	/* Locked by "lock". */
     72 	isc_mutex_t lock;
     73 	unsigned int state;
     74 	ISC_LIST(dns_dispatch_t) list;
     75 
     76 	/* locked by buffer_lock */
     77 	dns_qid_t *qid;
     78 	isc_mutex_t buffer_lock;
     79 	unsigned int buffers;	 /*%< allocated buffers */
     80 	unsigned int buffersize; /*%< size of each buffer */
     81 	unsigned int maxbuffers; /*%< max buffers */
     82 
     83 	isc_refcount_t irefs;
     84 
     85 	/*%
     86 	 * Locked by qid->lock if qid exists; otherwise, can be used without
     87 	 * being locked.
     88 	 * Memory footprint considerations: this is a simple implementation of
     89 	 * available ports, i.e., an ordered array of the actual port numbers.
     90 	 * This will require about 256KB of memory in the worst case (128KB for
     91 	 * each of IPv4 and IPv6).  We could reduce it by representing it as a
     92 	 * more sophisticated way such as a list (or array) of ranges that are
     93 	 * searched to identify a specific port.  Our decision here is the saved
     94 	 * memory isn't worth the implementation complexity, considering the
     95 	 * fact that the whole BIND9 process (which is mainly named) already
     96 	 * requires a pretty large memory footprint.  We may, however, have to
     97 	 * revisit the decision when we want to use it as a separate module for
     98 	 * an environment where memory requirement is severer.
     99 	 */
    100 	in_port_t *v4ports;    /*%< available ports for IPv4 */
    101 	unsigned int nv4ports; /*%< # of available ports for IPv4 */
    102 	in_port_t *v6ports;    /*%< available ports for IPv4 */
    103 	unsigned int nv6ports; /*%< # of available ports for IPv4 */
    104 };
    105 
    106 #define MGR_SHUTTINGDOWN       0x00000001U
    107 #define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
    108 
    109 #define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
    110 
    111 struct dns_dispentry {
    112 	unsigned int magic;
    113 	dns_dispatch_t *disp;
    114 	dns_messageid_t id;
    115 	in_port_t port;
    116 	unsigned int bucket;
    117 	isc_sockaddr_t host;
    118 	isc_task_t *task;
    119 	isc_taskaction_t action;
    120 	void *arg;
    121 	bool item_out;
    122 	dispsocket_t *dispsocket;
    123 	ISC_LIST(dns_dispatchevent_t) items;
    124 	ISC_LINK(dns_dispentry_t) link;
    125 };
    126 
    127 /*%
    128  * Maximum number of dispatch sockets that can be pooled for reuse.  The
    129  * appropriate value may vary, but experiments have shown a busy caching server
    130  * may need more than 1000 sockets concurrently opened.  The maximum allowable
    131  * number of dispatch sockets (per manager) will be set to the double of this
    132  * value.
    133  */
    134 #ifndef DNS_DISPATCH_POOLSOCKS
    135 #define DNS_DISPATCH_POOLSOCKS 2048
    136 #endif /* ifndef DNS_DISPATCH_POOLSOCKS */
    137 
    138 /*%
    139  * Quota to control the number of dispatch sockets.  If a dispatch has more
    140  * than the quota of sockets, new queries will purge oldest ones, so that
    141  * a massive number of outstanding queries won't prevent subsequent queries
    142  * (especially if the older ones take longer time and result in timeout).
    143  */
    144 #ifndef DNS_DISPATCH_SOCKSQUOTA
    145 #define DNS_DISPATCH_SOCKSQUOTA 3072
    146 #endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
    147 
    148 struct dispsocket {
    149 	unsigned int magic;
    150 	isc_socket_t *socket;
    151 	dns_dispatch_t *disp;
    152 	isc_sockaddr_t host;
    153 	in_port_t localport; /* XXX: should be removed later */
    154 	dispportentry_t *portentry;
    155 	dns_dispentry_t *resp;
    156 	isc_task_t *task;
    157 	ISC_LINK(dispsocket_t) link;
    158 	unsigned int bucket;
    159 	ISC_LINK(dispsocket_t) blink;
    160 };
    161 
    162 /*%
    163  * A port table entry.  We remember every port we first open in a table with a
    164  * reference counter so that we can 'reuse' the same port (with different
    165  * destination addresses) using the SO_REUSEADDR socket option.
    166  */
    167 struct dispportentry {
    168 	in_port_t port;
    169 	isc_refcount_t refs;
    170 	ISC_LINK(struct dispportentry) link;
    171 };
    172 
    173 #ifndef DNS_DISPATCH_PORTTABLESIZE
    174 #define DNS_DISPATCH_PORTTABLESIZE 1024
    175 #endif /* ifndef DNS_DISPATCH_PORTTABLESIZE */
    176 
    177 #define INVALID_BUCKET (0xffffdead)
    178 
    179 /*%
    180  * Number of tasks for each dispatch that use separate sockets for different
    181  * transactions.  This must be a power of 2 as it will divide 32 bit numbers
    182  * to get an uniformly random tasks selection.  See get_dispsocket().
    183  */
    184 #define MAX_INTERNAL_TASKS 64
    185 
    186 struct dns_dispatch {
    187 	/* Unlocked. */
    188 	unsigned int magic;	/*%< magic */
    189 	dns_dispatchmgr_t *mgr; /*%< dispatch manager */
    190 	int ntasks;
    191 	/*%
    192 	 * internal task buckets.  We use multiple tasks to distribute various
    193 	 * socket events well when using separate dispatch sockets.  We use the
    194 	 * 1st task (task[0]) for internal control events.
    195 	 */
    196 	isc_task_t *task[MAX_INTERNAL_TASKS];
    197 	isc_socket_t *socket;	  /*%< isc socket attached to */
    198 	isc_sockaddr_t local;	  /*%< local address */
    199 	in_port_t localport;	  /*%< local UDP port */
    200 	isc_sockaddr_t peer;	  /*%< peer address (TCP) */
    201 	isc_dscp_t dscp;	  /*%< "listen-on" DSCP value */
    202 	unsigned int maxrequests; /*%< max requests */
    203 	isc_event_t *ctlevent;
    204 
    205 	isc_mem_t *sepool; /*%< pool for socket events */
    206 
    207 	/*% Locked by mgr->lock. */
    208 	ISC_LINK(dns_dispatch_t) link;
    209 
    210 	/* Locked by "lock". */
    211 	isc_mutex_t lock; /*%< locks all below */
    212 	isc_sockettype_t socktype;
    213 	unsigned int attributes;
    214 	unsigned int refcount;		  /*%< number of users */
    215 	dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */
    216 	unsigned int shutting_down : 1, shutdown_out : 1, connected : 1,
    217 		tcpmsg_valid : 1, recv_pending : 1; /*%< is a
    218 						     * recv()
    219 						     * pending?
    220 						     * */
    221 	isc_result_t shutdown_why;
    222 	ISC_LIST(dispsocket_t) activesockets;
    223 	ISC_LIST(dispsocket_t) inactivesockets;
    224 	unsigned int nsockets;
    225 	unsigned int requests;	 /*%< how many requests we have */
    226 	unsigned int tcpbuffers; /*%< allocated buffers */
    227 	dns_tcpmsg_t tcpmsg;	 /*%< for tcp streams */
    228 	dns_qid_t *qid;
    229 	dispportlist_t *port_table; /*%< hold ports 'owned' by us */
    230 };
    231 
    232 #define QID_MAGIC    ISC_MAGIC('Q', 'i', 'd', ' ')
    233 #define VALID_QID(e) ISC_MAGIC_VALID((e), QID_MAGIC)
    234 
    235 #define RESPONSE_MAGIC	  ISC_MAGIC('D', 'r', 's', 'p')
    236 #define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
    237 
    238 #define DISPSOCK_MAGIC	  ISC_MAGIC('D', 's', 'o', 'c')
    239 #define VALID_DISPSOCK(e) ISC_MAGIC_VALID((e), DISPSOCK_MAGIC)
    240 
    241 #define DISPATCH_MAGIC	  ISC_MAGIC('D', 'i', 's', 'p')
    242 #define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
    243 
    244 #define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
    245 #define VALID_DISPATCHMGR(e)  ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
    246 
    247 #define DNS_QID(disp)                                          \
    248 	((disp)->socktype == isc_sockettype_tcp) ? (disp)->qid \
    249 						 : (disp)->mgr->qid
    250 
    251 /*%
    252  * Locking a query port buffer is a bit tricky.  We access the buffer without
    253  * locking until qid is created.  Technically, there is a possibility of race
    254  * between the creation of qid and access to the port buffer; in practice,
    255  * however, this should be safe because qid isn't created until the first
    256  * dispatch is created and there should be no contending situation until then.
    257  */
    258 #define PORTBUFLOCK(mgr)        \
    259 	if ((mgr)->qid != NULL) \
    260 	LOCK(&((mgr)->qid->lock))
    261 #define PORTBUFUNLOCK(mgr)      \
    262 	if ((mgr)->qid != NULL) \
    263 	UNLOCK((&(mgr)->qid->lock))
    264 
    265 /*
    266  * Statics.
    267  */
    268 static dns_dispentry_t *
    269 entry_search(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t,
    270 	     unsigned int);
    271 static bool
    272 destroy_disp_ok(dns_dispatch_t *);
    273 static void
    274 destroy_disp(isc_task_t *task, isc_event_t *event);
    275 static void
    276 destroy_dispsocket(dns_dispatch_t *, dispsocket_t **);
    277 static void
    278 deactivate_dispsocket(dns_dispatch_t *, dispsocket_t *);
    279 static void
    280 udp_exrecv(isc_task_t *, isc_event_t *);
    281 static void
    282 udp_shrecv(isc_task_t *, isc_event_t *);
    283 static void
    284 udp_recv(isc_event_t *, dns_dispatch_t *, dispsocket_t *);
    285 static void
    286 tcp_recv(isc_task_t *, isc_event_t *);
    287 static isc_result_t
    288 startrecv(dns_dispatch_t *, dispsocket_t *);
    289 static uint32_t
    290 dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t);
    291 static void
    292 free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
    293 static void *
    294 allocate_udp_buffer(dns_dispatch_t *disp);
    295 static void
    296 free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
    297 static dns_dispatchevent_t *
    298 allocate_devent(dns_dispatch_t *disp);
    299 static void
    300 do_cancel(dns_dispatch_t *disp);
    301 static dns_dispentry_t *
    302 linear_first(dns_qid_t *disp);
    303 static dns_dispentry_t *
    304 linear_next(dns_qid_t *disp, dns_dispentry_t *resp);
    305 static void
    306 dispatch_free(dns_dispatch_t **dispp);
    307 static isc_result_t
    308 get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
    309 	      isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr,
    310 	      isc_socket_t **sockp, isc_socket_t *dup_socket, bool duponly);
    311 static isc_result_t
    312 dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
    313 		   isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
    314 		   unsigned int maxrequests, unsigned int attributes,
    315 		   dns_dispatch_t **dispp, isc_socket_t *dup_socket);
    316 static bool
    317 destroy_mgr_ok(dns_dispatchmgr_t *mgr);
    318 static void
    319 destroy_mgr(dns_dispatchmgr_t **mgrp);
    320 static isc_result_t
    321 qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
    322 	     unsigned int increment, dns_qid_t **qidp, bool needaddrtable);
    323 static void
    324 qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
    325 static isc_result_t
    326 open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
    327 	    unsigned int options, isc_socket_t **sockp,
    328 	    isc_socket_t *dup_socket, bool duponly);
    329 static bool
    330 portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
    331 	      isc_sockaddr_t *sockaddrp);
    332 
    333 #define LVL(x) ISC_LOG_DEBUG(x)
    334 
    335 static void
    336 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...)
    337 	ISC_FORMAT_PRINTF(3, 4);
    338 
    339 static void
    340 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {
    341 	char msgbuf[2048];
    342 	va_list ap;
    343 
    344 	if (!isc_log_wouldlog(dns_lctx, level)) {
    345 		return;
    346 	}
    347 
    348 	va_start(ap, fmt);
    349 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
    350 	va_end(ap);
    351 
    352 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
    353 		      DNS_LOGMODULE_DISPATCH, level, "dispatchmgr %p: %s", mgr,
    354 		      msgbuf);
    355 }
    356 
    357 static void
    358 inc_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
    359 	if (mgr->stats != NULL) {
    360 		isc_stats_increment(mgr->stats, counter);
    361 	}
    362 }
    363 
    364 static void
    365 dec_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
    366 	if (mgr->stats != NULL) {
    367 		isc_stats_decrement(mgr->stats, counter);
    368 	}
    369 }
    370 
    371 static void
    372 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)
    373 	ISC_FORMAT_PRINTF(3, 4);
    374 
    375 static void
    376 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) {
    377 	char msgbuf[2048];
    378 	va_list ap;
    379 
    380 	if (!isc_log_wouldlog(dns_lctx, level)) {
    381 		return;
    382 	}
    383 
    384 	va_start(ap, fmt);
    385 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
    386 	va_end(ap);
    387 
    388 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
    389 		      DNS_LOGMODULE_DISPATCH, level, "dispatch %p: %s", disp,
    390 		      msgbuf);
    391 }
    392 
    393 static void
    394 request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, int level,
    395 	    const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
    396 
    397 static void
    398 request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, int level,
    399 	    const char *fmt, ...) {
    400 	char msgbuf[2048];
    401 	char peerbuf[256];
    402 	va_list ap;
    403 
    404 	if (!isc_log_wouldlog(dns_lctx, level)) {
    405 		return;
    406 	}
    407 
    408 	va_start(ap, fmt);
    409 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
    410 	va_end(ap);
    411 
    412 	if (VALID_RESPONSE(resp)) {
    413 		isc_sockaddr_format(&resp->host, peerbuf, sizeof(peerbuf));
    414 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
    415 			      DNS_LOGMODULE_DISPATCH, level,
    416 			      "dispatch %p response %p %s: %s", disp, resp,
    417 			      peerbuf, msgbuf);
    418 	} else {
    419 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
    420 			      DNS_LOGMODULE_DISPATCH, level,
    421 			      "dispatch %p req/resp %p: %s", disp, resp,
    422 			      msgbuf);
    423 	}
    424 }
    425 
    426 /*
    427  * Return a hash of the destination and message id.
    428  */
    429 static uint32_t
    430 dns_hash(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id,
    431 	 in_port_t port) {
    432 	uint32_t ret;
    433 
    434 	ret = isc_sockaddr_hash(dest, true);
    435 	ret ^= ((uint32_t)id << 16) | port;
    436 	ret %= qid->qid_nbuckets;
    437 
    438 	INSIST(ret < qid->qid_nbuckets);
    439 
    440 	return (ret);
    441 }
    442 
    443 /*
    444  * Find the first entry in 'qid'.  Returns NULL if there are no entries.
    445  */
    446 static dns_dispentry_t *
    447 linear_first(dns_qid_t *qid) {
    448 	dns_dispentry_t *ret;
    449 	unsigned int bucket;
    450 
    451 	bucket = 0;
    452 
    453 	while (bucket < qid->qid_nbuckets) {
    454 		ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
    455 		if (ret != NULL) {
    456 			return (ret);
    457 		}
    458 		bucket++;
    459 	}
    460 
    461 	return (NULL);
    462 }
    463 
    464 /*
    465  * Find the next entry after 'resp' in 'qid'.  Return NULL if there are
    466  * no more entries.
    467  */
    468 static dns_dispentry_t *
    469 linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {
    470 	dns_dispentry_t *ret;
    471 	unsigned int bucket;
    472 
    473 	ret = ISC_LIST_NEXT(resp, link);
    474 	if (ret != NULL) {
    475 		return (ret);
    476 	}
    477 
    478 	bucket = resp->bucket;
    479 	bucket++;
    480 	while (bucket < qid->qid_nbuckets) {
    481 		ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
    482 		if (ret != NULL) {
    483 			return (ret);
    484 		}
    485 		bucket++;
    486 	}
    487 
    488 	return (NULL);
    489 }
    490 
    491 /*
    492  * The dispatch must be locked.
    493  */
    494 static bool
    495 destroy_disp_ok(dns_dispatch_t *disp) {
    496 	if (disp->refcount != 0) {
    497 		return (false);
    498 	}
    499 
    500 	if (disp->recv_pending != 0) {
    501 		return (false);
    502 	}
    503 
    504 	if (!ISC_LIST_EMPTY(disp->activesockets)) {
    505 		return (false);
    506 	}
    507 
    508 	if (disp->shutting_down == 0) {
    509 		return (false);
    510 	}
    511 
    512 	return (true);
    513 }
    514 
    515 /*
    516  * Called when refcount reaches 0 (and safe to destroy).
    517  *
    518  * The dispatcher must be locked.
    519  * The manager must not be locked.
    520  */
    521 static void
    522 destroy_disp(isc_task_t *task, isc_event_t *event) {
    523 	dns_dispatch_t *disp;
    524 	dns_dispatchmgr_t *mgr;
    525 	bool killmgr;
    526 	dispsocket_t *dispsocket;
    527 	int i;
    528 
    529 	INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
    530 
    531 	UNUSED(task);
    532 
    533 	disp = event->ev_arg;
    534 	mgr = disp->mgr;
    535 
    536 	LOCK(&mgr->lock);
    537 	ISC_LIST_UNLINK(mgr->list, disp, link);
    538 
    539 	dispatch_log(disp, LVL(90),
    540 		     "shutting down; detaching from sock %p, task %p",
    541 		     disp->socket, disp->task[0]); /* XXXX */
    542 
    543 	if (disp->sepool != NULL) {
    544 		isc_mem_destroy(&disp->sepool);
    545 	}
    546 
    547 	if (disp->socket != NULL) {
    548 		isc_socket_detach(&disp->socket);
    549 	}
    550 	while ((dispsocket = ISC_LIST_HEAD(disp->inactivesockets)) != NULL) {
    551 		ISC_LIST_UNLINK(disp->inactivesockets, dispsocket, link);
    552 		destroy_dispsocket(disp, &dispsocket);
    553 	}
    554 	for (i = 0; i < disp->ntasks; i++) {
    555 		isc_task_detach(&disp->task[i]);
    556 	}
    557 	isc_event_free(&event);
    558 
    559 	dispatch_free(&disp);
    560 
    561 	killmgr = destroy_mgr_ok(mgr);
    562 	UNLOCK(&mgr->lock);
    563 	if (killmgr) {
    564 		destroy_mgr(&mgr);
    565 	}
    566 }
    567 
    568 /*%
    569  * Manipulate port table per dispatch: find an entry for a given port number,
    570  * create a new entry, and decrement a given entry with possible clean-up.
    571  */
    572 static dispportentry_t *
    573 port_search(dns_dispatch_t *disp, in_port_t port) {
    574 	dispportentry_t *portentry;
    575 
    576 	REQUIRE(disp->port_table != NULL);
    577 
    578 	portentry = ISC_LIST_HEAD(
    579 		disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE]);
    580 	while (portentry != NULL) {
    581 		if (portentry->port == port) {
    582 			return (portentry);
    583 		}
    584 		portentry = ISC_LIST_NEXT(portentry, link);
    585 	}
    586 
    587 	return (NULL);
    588 }
    589 
    590 static dispportentry_t *
    591 new_portentry(dns_dispatch_t *disp, in_port_t port) {
    592 	dispportentry_t *portentry;
    593 	dns_qid_t *qid;
    594 
    595 	REQUIRE(disp->port_table != NULL);
    596 
    597 	portentry = isc_mem_get(disp->mgr->mctx, sizeof(*portentry));
    598 
    599 	portentry->port = port;
    600 	isc_refcount_init(&portentry->refs, 1);
    601 	ISC_LINK_INIT(portentry, link);
    602 	qid = DNS_QID(disp);
    603 	LOCK(&qid->lock);
    604 	ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
    605 			portentry, link);
    606 	UNLOCK(&qid->lock);
    607 
    608 	return (portentry);
    609 }
    610 
    611 /*%
    612  * The caller must hold the qid->lock.
    613  */
    614 static void
    615 deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
    616 	dispportentry_t *portentry = *portentryp;
    617 	*portentryp = NULL;
    618 
    619 	REQUIRE(disp->port_table != NULL);
    620 	REQUIRE(portentry != NULL);
    621 
    622 	if (isc_refcount_decrement(&portentry->refs) == 1) {
    623 		ISC_LIST_UNLINK(disp->port_table[portentry->port %
    624 						 DNS_DISPATCH_PORTTABLESIZE],
    625 				portentry, link);
    626 		isc_mem_put(disp->mgr->mctx, portentry, sizeof(*portentry));
    627 	}
    628 }
    629 
    630 /*%
    631  * Find a dispsocket for socket address 'dest', and port number 'port'.
    632  * Return NULL if no such entry exists.  Requires qid->lock to be held.
    633  */
    634 static dispsocket_t *
    635 socket_search(dns_qid_t *qid, const isc_sockaddr_t *dest, in_port_t port,
    636 	      unsigned int bucket) {
    637 	dispsocket_t *dispsock;
    638 
    639 	REQUIRE(VALID_QID(qid));
    640 	REQUIRE(bucket < qid->qid_nbuckets);
    641 
    642 	dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]);
    643 
    644 	while (dispsock != NULL) {
    645 		if (dispsock->portentry != NULL &&
    646 		    dispsock->portentry->port == port &&
    647 		    isc_sockaddr_equal(dest, &dispsock->host))
    648 		{
    649 			return (dispsock);
    650 		}
    651 		dispsock = ISC_LIST_NEXT(dispsock, blink);
    652 	}
    653 
    654 	return (NULL);
    655 }
    656 
    657 /*%
    658  * Make a new socket for a single dispatch with a random port number.
    659  * The caller must hold the disp->lock
    660  */
    661 static isc_result_t
    662 get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
    663 	       isc_socketmgr_t *sockmgr, dispsocket_t **dispsockp,
    664 	       in_port_t *portp) {
    665 	int i;
    666 	dns_dispatchmgr_t *mgr = disp->mgr;
    667 	isc_socket_t *sock = NULL;
    668 	isc_result_t result = ISC_R_FAILURE;
    669 	in_port_t port;
    670 	isc_sockaddr_t localaddr;
    671 	unsigned int bucket = 0;
    672 	dispsocket_t *dispsock;
    673 	unsigned int nports;
    674 	in_port_t *ports;
    675 	isc_socket_options_t bindoptions;
    676 	dispportentry_t *portentry = NULL;
    677 	dns_qid_t *qid;
    678 
    679 	if (isc_sockaddr_pf(&disp->local) == AF_INET) {
    680 		nports = disp->mgr->nv4ports;
    681 		ports = disp->mgr->v4ports;
    682 	} else {
    683 		nports = disp->mgr->nv6ports;
    684 		ports = disp->mgr->v6ports;
    685 	}
    686 	if (nports == 0) {
    687 		return (ISC_R_ADDRNOTAVAIL);
    688 	}
    689 
    690 	dispsock = ISC_LIST_HEAD(disp->inactivesockets);
    691 	if (dispsock != NULL) {
    692 		ISC_LIST_UNLINK(disp->inactivesockets, dispsock, link);
    693 		sock = dispsock->socket;
    694 		dispsock->socket = NULL;
    695 	} else {
    696 		dispsock = isc_mem_get(mgr->mctx, sizeof(*dispsock));
    697 
    698 		disp->nsockets++;
    699 		dispsock->socket = NULL;
    700 		dispsock->disp = disp;
    701 		dispsock->resp = NULL;
    702 		dispsock->portentry = NULL;
    703 		dispsock->task = NULL;
    704 		isc_task_attach(disp->task[isc_random_uniform(disp->ntasks)],
    705 				&dispsock->task);
    706 		ISC_LINK_INIT(dispsock, link);
    707 		ISC_LINK_INIT(dispsock, blink);
    708 		dispsock->magic = DISPSOCK_MAGIC;
    709 	}
    710 
    711 	/*
    712 	 * Pick up a random UDP port and open a new socket with it.  Avoid
    713 	 * choosing ports that share the same destination because it will be
    714 	 * very likely to fail in bind(2) or connect(2).
    715 	 */
    716 	localaddr = disp->local;
    717 	qid = DNS_QID(disp);
    718 
    719 	for (i = 0; i < 64; i++) {
    720 		port = ports[isc_random_uniform(nports)];
    721 		isc_sockaddr_setport(&localaddr, port);
    722 
    723 		LOCK(&qid->lock);
    724 		bucket = dns_hash(qid, dest, 0, port);
    725 		if (socket_search(qid, dest, port, bucket) != NULL) {
    726 			UNLOCK(&qid->lock);
    727 			continue;
    728 		}
    729 		UNLOCK(&qid->lock);
    730 		bindoptions = 0;
    731 		portentry = port_search(disp, port);
    732 
    733 		if (portentry != NULL) {
    734 			bindoptions |= ISC_SOCKET_REUSEADDRESS;
    735 		}
    736 		result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
    737 				     NULL, false);
    738 		if (result == ISC_R_SUCCESS) {
    739 			if (portentry == NULL) {
    740 				portentry = new_portentry(disp, port);
    741 				if (portentry == NULL) {
    742 					result = ISC_R_NOMEMORY;
    743 					break;
    744 				}
    745 			} else {
    746 				isc_refcount_increment(&portentry->refs);
    747 			}
    748 			break;
    749 		} else if (result == ISC_R_NOPERM) {
    750 			char buf[ISC_SOCKADDR_FORMATSIZE];
    751 			isc_sockaddr_format(&localaddr, buf, sizeof(buf));
    752 			dispatch_log(disp, ISC_LOG_WARNING,
    753 				     "open_socket(%s) -> %s: continuing", buf,
    754 				     isc_result_totext(result));
    755 		} else if (result != ISC_R_ADDRINUSE) {
    756 			break;
    757 		}
    758 	}
    759 
    760 	if (result == ISC_R_SUCCESS) {
    761 		dispsock->socket = sock;
    762 		dispsock->host = *dest;
    763 		dispsock->bucket = bucket;
    764 		LOCK(&qid->lock);
    765 		dispsock->portentry = portentry;
    766 		ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
    767 		UNLOCK(&qid->lock);
    768 		*dispsockp = dispsock;
    769 		*portp = port;
    770 	} else {
    771 		/*
    772 		 * We could keep it in the inactive list, but since this should
    773 		 * be an exceptional case and might be resource shortage, we'd
    774 		 * rather destroy it.
    775 		 */
    776 		if (sock != NULL) {
    777 			isc_socket_detach(&sock);
    778 		}
    779 		destroy_dispsocket(disp, &dispsock);
    780 	}
    781 
    782 	return (result);
    783 }
    784 
    785 /*%
    786  * Destroy a dedicated dispatch socket.
    787  */
    788 static void
    789 destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
    790 	dispsocket_t *dispsock;
    791 	dns_qid_t *qid = DNS_QID(disp);
    792 
    793 	/*
    794 	 * The dispatch must be locked.
    795 	 */
    796 
    797 	REQUIRE(dispsockp != NULL && *dispsockp != NULL);
    798 	dispsock = *dispsockp;
    799 	*dispsockp = NULL;
    800 	REQUIRE(!ISC_LINK_LINKED(dispsock, link));
    801 
    802 	disp->nsockets--;
    803 	dispsock->magic = 0;
    804 	if (dispsock->portentry != NULL) {
    805 		/* socket_search() tests and dereferences portentry. */
    806 		LOCK(&qid->lock);
    807 		deref_portentry(disp, &dispsock->portentry);
    808 		UNLOCK(&qid->lock);
    809 	}
    810 	if (dispsock->socket != NULL) {
    811 		isc_socket_detach(&dispsock->socket);
    812 	}
    813 	if (ISC_LINK_LINKED(dispsock, blink)) {
    814 		LOCK(&qid->lock);
    815 		ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
    816 				blink);
    817 		UNLOCK(&qid->lock);
    818 	}
    819 	if (dispsock->task != NULL) {
    820 		isc_task_detach(&dispsock->task);
    821 	}
    822 	isc_mem_put(disp->mgr->mctx, dispsock, sizeof(*dispsock));
    823 }
    824 
    825 /*%
    826  * Deactivate a dedicated dispatch socket.  Move it to the inactive list for
    827  * future reuse unless the total number of sockets are exceeding the maximum.
    828  */
    829 static void
    830 deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
    831 	isc_result_t result;
    832 	dns_qid_t *qid = DNS_QID(disp);
    833 
    834 	/*
    835 	 * The dispatch must be locked.
    836 	 */
    837 	ISC_LIST_UNLINK(disp->activesockets, dispsock, link);
    838 	if (dispsock->resp != NULL) {
    839 		INSIST(dispsock->resp->dispsocket == dispsock);
    840 		dispsock->resp->dispsocket = NULL;
    841 	}
    842 
    843 	INSIST(dispsock->portentry != NULL);
    844 	/* socket_search() tests and dereferences portentry. */
    845 	LOCK(&qid->lock);
    846 	deref_portentry(disp, &dispsock->portentry);
    847 	UNLOCK(&qid->lock);
    848 
    849 	if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) {
    850 		destroy_dispsocket(disp, &dispsock);
    851 	} else {
    852 		result = isc_socket_close(dispsock->socket);
    853 
    854 		LOCK(&qid->lock);
    855 		ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
    856 				blink);
    857 		UNLOCK(&qid->lock);
    858 
    859 		if (result == ISC_R_SUCCESS) {
    860 			ISC_LIST_APPEND(disp->inactivesockets, dispsock, link);
    861 		} else {
    862 			/*
    863 			 * If the underlying system does not allow this
    864 			 * optimization, destroy this temporary structure (and
    865 			 * create a new one for a new transaction).
    866 			 */
    867 			INSIST(result == ISC_R_NOTIMPLEMENTED);
    868 			destroy_dispsocket(disp, &dispsock);
    869 		}
    870 	}
    871 }
    872 
    873 /*
    874  * Find an entry for query ID 'id', socket address 'dest', and port number
    875  * 'port'.
    876  * Return NULL if no such entry exists.
    877  */
    878 static dns_dispentry_t *
    879 entry_search(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id,
    880 	     in_port_t port, unsigned int bucket) {
    881 	dns_dispentry_t *res;
    882 
    883 	REQUIRE(VALID_QID(qid));
    884 	REQUIRE(bucket < qid->qid_nbuckets);
    885 
    886 	res = ISC_LIST_HEAD(qid->qid_table[bucket]);
    887 
    888 	while (res != NULL) {
    889 		if (res->id == id && isc_sockaddr_equal(dest, &res->host) &&
    890 		    res->port == port)
    891 		{
    892 			return (res);
    893 		}
    894 		res = ISC_LIST_NEXT(res, link);
    895 	}
    896 
    897 	return (NULL);
    898 }
    899 
    900 static void
    901 free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
    902 	unsigned int buffersize;
    903 	INSIST(buf != NULL && len != 0);
    904 
    905 	switch (disp->socktype) {
    906 	case isc_sockettype_tcp:
    907 		INSIST(disp->tcpbuffers > 0);
    908 		disp->tcpbuffers--;
    909 		isc_mem_put(disp->mgr->mctx, buf, len);
    910 		break;
    911 	case isc_sockettype_udp:
    912 		LOCK(&disp->mgr->buffer_lock);
    913 		INSIST(disp->mgr->buffers > 0);
    914 		INSIST(len == disp->mgr->buffersize);
    915 		disp->mgr->buffers--;
    916 		buffersize = disp->mgr->buffersize;
    917 		UNLOCK(&disp->mgr->buffer_lock);
    918 		isc_mem_put(disp->mgr->mctx, buf, buffersize);
    919 		break;
    920 	default:
    921 		UNREACHABLE();
    922 	}
    923 }
    924 
    925 static void *
    926 allocate_udp_buffer(dns_dispatch_t *disp) {
    927 	unsigned int buffersize;
    928 
    929 	LOCK(&disp->mgr->buffer_lock);
    930 	if (disp->mgr->buffers >= disp->mgr->maxbuffers) {
    931 		UNLOCK(&disp->mgr->buffer_lock);
    932 		return (NULL);
    933 	}
    934 	buffersize = disp->mgr->buffersize;
    935 	disp->mgr->buffers++;
    936 	UNLOCK(&disp->mgr->buffer_lock);
    937 
    938 	return (isc_mem_get(disp->mgr->mctx, buffersize));
    939 }
    940 
    941 static void
    942 free_sevent(isc_event_t *ev) {
    943 	isc_mem_t *pool = ev->ev_destroy_arg;
    944 	isc_socketevent_t *sev = (isc_socketevent_t *)ev;
    945 	isc_mem_put(pool, sev, sizeof(*sev));
    946 }
    947 
    948 static isc_socketevent_t *
    949 allocate_sevent(dns_dispatch_t *disp, isc_socket_t *sock, isc_eventtype_t type,
    950 		isc_taskaction_t action, const void *arg) {
    951 	isc_socketevent_t *ev;
    952 	void *deconst_arg;
    953 
    954 	ev = isc_mem_get(disp->sepool, sizeof(*ev));
    955 	DE_CONST(arg, deconst_arg);
    956 	ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, type, action, deconst_arg,
    957 		       sock, free_sevent, disp->sepool);
    958 	ev->result = ISC_R_UNSET;
    959 	ISC_LINK_INIT(ev, ev_link);
    960 	ev->region.base = NULL;
    961 	ev->n = 0;
    962 	ev->offset = 0;
    963 	ev->attributes = 0;
    964 
    965 	return (ev);
    966 }
    967 
    968 static void
    969 free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
    970 	if (disp->failsafe_ev == ev) {
    971 		INSIST(disp->shutdown_out == 1);
    972 		disp->shutdown_out = 0;
    973 
    974 		return;
    975 	}
    976 
    977 	isc_refcount_decrement(&disp->mgr->irefs);
    978 	isc_mem_put(disp->mgr->mctx, ev, sizeof(*ev));
    979 }
    980 
    981 static dns_dispatchevent_t *
    982 allocate_devent(dns_dispatch_t *disp) {
    983 	dns_dispatchevent_t *ev;
    984 
    985 	ev = isc_mem_get(disp->mgr->mctx, sizeof(*ev));
    986 	isc_refcount_increment0(&disp->mgr->irefs);
    987 	ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0, NULL, NULL, NULL, NULL,
    988 		       NULL);
    989 
    990 	return (ev);
    991 }
    992 
    993 static void
    994 udp_exrecv(isc_task_t *task, isc_event_t *ev) {
    995 	dispsocket_t *dispsock = ev->ev_arg;
    996 
    997 	UNUSED(task);
    998 
    999 	REQUIRE(VALID_DISPSOCK(dispsock));
   1000 	udp_recv(ev, dispsock->disp, dispsock);
   1001 }
   1002 
   1003 static void
   1004 udp_shrecv(isc_task_t *task, isc_event_t *ev) {
   1005 	dns_dispatch_t *disp = ev->ev_arg;
   1006 
   1007 	UNUSED(task);
   1008 
   1009 	REQUIRE(VALID_DISPATCH(disp));
   1010 	udp_recv(ev, disp, NULL);
   1011 }
   1012 
   1013 /*
   1014  * General flow:
   1015  *
   1016  * If I/O result == CANCELED or error, free the buffer.
   1017  *
   1018  * If query, free the buffer, restart.
   1019  *
   1020  * If response:
   1021  *	Allocate event, fill in details.
   1022  *		If cannot allocate, free buffer, restart.
   1023  *	find target.  If not found, free buffer, restart.
   1024  *	if event queue is not empty, queue.  else, send.
   1025  *	restart.
   1026  */
   1027 static void
   1028 udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
   1029 	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
   1030 	dns_messageid_t id;
   1031 	isc_result_t dres;
   1032 	isc_buffer_t source;
   1033 	unsigned int flags;
   1034 	dns_dispentry_t *resp = NULL;
   1035 	dns_dispatchevent_t *rev;
   1036 	unsigned int bucket;
   1037 	bool killit;
   1038 	bool queue_response;
   1039 	dns_dispatchmgr_t *mgr;
   1040 	dns_qid_t *qid;
   1041 	isc_netaddr_t netaddr;
   1042 	int match;
   1043 	int result;
   1044 	bool qidlocked = false;
   1045 
   1046 	LOCK(&disp->lock);
   1047 
   1048 	mgr = disp->mgr;
   1049 	qid = mgr->qid;
   1050 
   1051 	LOCK(&disp->mgr->buffer_lock);
   1052 	dispatch_log(disp, LVL(90),
   1053 		     "got packet: requests %d, buffers %d, recvs %d",
   1054 		     disp->requests, disp->mgr->buffers, disp->recv_pending);
   1055 	UNLOCK(&disp->mgr->buffer_lock);
   1056 
   1057 	if (dispsock == NULL && ev->ev_type == ISC_SOCKEVENT_RECVDONE) {
   1058 		/*
   1059 		 * Unless the receive event was imported from a listening
   1060 		 * interface, in which case the event type is
   1061 		 * DNS_EVENT_IMPORTRECVDONE, receive operation must be pending.
   1062 		 */
   1063 		INSIST(disp->recv_pending != 0);
   1064 		disp->recv_pending = 0;
   1065 	}
   1066 
   1067 	if (dispsock != NULL &&
   1068 	    (ev->result == ISC_R_CANCELED || dispsock->resp == NULL))
   1069 	{
   1070 		/*
   1071 		 * dispsock->resp can be NULL if this transaction was canceled
   1072 		 * just after receiving a response.  Since this socket is
   1073 		 * exclusively used and there should be at most one receive
   1074 		 * event the canceled event should have been no effect.  So
   1075 		 * we can (and should) deactivate the socket right now.
   1076 		 */
   1077 		deactivate_dispsocket(disp, dispsock);
   1078 		dispsock = NULL;
   1079 	}
   1080 
   1081 	if (disp->shutting_down) {
   1082 		/*
   1083 		 * This dispatcher is shutting down.
   1084 		 */
   1085 		free_buffer(disp, ev->region.base, ev->region.length);
   1086 
   1087 		isc_event_free(&ev_in);
   1088 		ev = NULL;
   1089 
   1090 		killit = destroy_disp_ok(disp);
   1091 		UNLOCK(&disp->lock);
   1092 		if (killit) {
   1093 			isc_task_send(disp->task[0], &disp->ctlevent);
   1094 		}
   1095 
   1096 		return;
   1097 	}
   1098 
   1099 	if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
   1100 		if (dispsock != NULL) {
   1101 			resp = dispsock->resp;
   1102 			id = resp->id;
   1103 			if (ev->result != ISC_R_SUCCESS) {
   1104 				/*
   1105 				 * This is most likely a network error on a
   1106 				 * connected socket.  It makes no sense to
   1107 				 * check the address or parse the packet, but it
   1108 				 * will help to return the error to the caller.
   1109 				 */
   1110 				goto sendresponse;
   1111 			}
   1112 		} else {
   1113 			free_buffer(disp, ev->region.base, ev->region.length);
   1114 
   1115 			isc_event_free(&ev_in);
   1116 			UNLOCK(&disp->lock);
   1117 			return;
   1118 		}
   1119 	} else if (ev->result != ISC_R_SUCCESS) {
   1120 		free_buffer(disp, ev->region.base, ev->region.length);
   1121 
   1122 		if (ev->result != ISC_R_CANCELED) {
   1123 			dispatch_log(disp, ISC_LOG_ERROR,
   1124 				     "odd socket result in udp_recv(): %s",
   1125 				     isc_result_totext(ev->result));
   1126 		}
   1127 
   1128 		isc_event_free(&ev_in);
   1129 		UNLOCK(&disp->lock);
   1130 		return;
   1131 	}
   1132 
   1133 	/*
   1134 	 * If this is from a blackholed address, drop it.
   1135 	 */
   1136 	isc_netaddr_fromsockaddr(&netaddr, &ev->address);
   1137 	if (disp->mgr->blackhole != NULL &&
   1138 	    dns_acl_match(&netaddr, NULL, disp->mgr->blackhole, NULL, &match,
   1139 			  NULL) == ISC_R_SUCCESS &&
   1140 	    match > 0)
   1141 	{
   1142 		if (isc_log_wouldlog(dns_lctx, LVL(10))) {
   1143 			char netaddrstr[ISC_NETADDR_FORMATSIZE];
   1144 			isc_netaddr_format(&netaddr, netaddrstr,
   1145 					   sizeof(netaddrstr));
   1146 			dispatch_log(disp, LVL(10), "blackholed packet from %s",
   1147 				     netaddrstr);
   1148 		}
   1149 		free_buffer(disp, ev->region.base, ev->region.length);
   1150 		goto restart;
   1151 	}
   1152 
   1153 	/*
   1154 	 * Peek into the buffer to see what we can see.
   1155 	 */
   1156 	isc_buffer_init(&source, ev->region.base, ev->region.length);
   1157 	isc_buffer_add(&source, ev->n);
   1158 	dres = dns_message_peekheader(&source, &id, &flags);
   1159 	if (dres != ISC_R_SUCCESS) {
   1160 		free_buffer(disp, ev->region.base, ev->region.length);
   1161 		dispatch_log(disp, LVL(10), "got garbage packet");
   1162 		goto restart;
   1163 	}
   1164 
   1165 	dispatch_log(disp, LVL(92),
   1166 		     "got valid DNS message header, /QR %c, id %u",
   1167 		     (((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0'), id);
   1168 
   1169 	/*
   1170 	 * Look at flags.  If query, drop it. If response,
   1171 	 * look to see where it goes.
   1172 	 */
   1173 	if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
   1174 		/* query */
   1175 		free_buffer(disp, ev->region.base, ev->region.length);
   1176 		goto restart;
   1177 	}
   1178 
   1179 	/*
   1180 	 * Search for the corresponding response.  If we are using an exclusive
   1181 	 * socket, we've already identified it and we can skip the search; but
   1182 	 * the ID and the address must match the expected ones.
   1183 	 */
   1184 	if (resp == NULL) {
   1185 		bucket = dns_hash(qid, &ev->address, id, disp->localport);
   1186 		LOCK(&qid->lock);
   1187 		qidlocked = true;
   1188 		resp = entry_search(qid, &ev->address, id, disp->localport,
   1189 				    bucket);
   1190 		dispatch_log(disp, LVL(90),
   1191 			     "search for response in bucket %d: %s", bucket,
   1192 			     (resp == NULL ? "not found" : "found"));
   1193 
   1194 	} else if (resp->id != id ||
   1195 		   !isc_sockaddr_equal(&ev->address, &resp->host))
   1196 	{
   1197 		dispatch_log(disp, LVL(90),
   1198 			     "response to an exclusive socket doesn't match");
   1199 		inc_stats(mgr, dns_resstatscounter_mismatch);
   1200 		free_buffer(disp, ev->region.base, ev->region.length);
   1201 		goto unlock;
   1202 	}
   1203 
   1204 	if (resp == NULL) {
   1205 		inc_stats(mgr, dns_resstatscounter_mismatch);
   1206 		free_buffer(disp, ev->region.base, ev->region.length);
   1207 		goto unlock;
   1208 	}
   1209 
   1210 	/*
   1211 	 * Now that we have the original dispatch the query was sent
   1212 	 * from check that the address and port the response was
   1213 	 * sent to make sense.
   1214 	 */
   1215 	if (disp != resp->disp) {
   1216 		isc_sockaddr_t a1;
   1217 		isc_sockaddr_t a2;
   1218 
   1219 		/*
   1220 		 * Check that the socket types and ports match.
   1221 		 */
   1222 		if (disp->socktype != resp->disp->socktype ||
   1223 		    isc_sockaddr_getport(&disp->local) !=
   1224 			    isc_sockaddr_getport(&resp->disp->local))
   1225 		{
   1226 			free_buffer(disp, ev->region.base, ev->region.length);
   1227 			goto unlock;
   1228 		}
   1229 
   1230 		/*
   1231 		 * If each dispatch is bound to a different address
   1232 		 * then fail.
   1233 		 *
   1234 		 * Note under Linux a packet can be sent out via IPv4 socket
   1235 		 * and the response be received via a IPv6 socket.
   1236 		 *
   1237 		 * Requests sent out via IPv6 should always come back in
   1238 		 * via IPv6.
   1239 		 */
   1240 		if (isc_sockaddr_pf(&resp->disp->local) == PF_INET6 &&
   1241 		    isc_sockaddr_pf(&disp->local) != PF_INET6)
   1242 		{
   1243 			free_buffer(disp, ev->region.base, ev->region.length);
   1244 			goto unlock;
   1245 		}
   1246 		isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local));
   1247 		isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local));
   1248 		if (!isc_sockaddr_eqaddr(&disp->local, &resp->disp->local) &&
   1249 		    !isc_sockaddr_eqaddr(&a1, &resp->disp->local) &&
   1250 		    !isc_sockaddr_eqaddr(&a2, &disp->local))
   1251 		{
   1252 			free_buffer(disp, ev->region.base, ev->region.length);
   1253 			goto unlock;
   1254 		}
   1255 	}
   1256 
   1257 sendresponse:
   1258 	queue_response = resp->item_out;
   1259 	rev = allocate_devent(resp->disp);
   1260 	if (rev == NULL) {
   1261 		free_buffer(disp, ev->region.base, ev->region.length);
   1262 		goto unlock;
   1263 	}
   1264 
   1265 	/*
   1266 	 * At this point, rev contains the event we want to fill in, and
   1267 	 * resp contains the information on the place to send it to.
   1268 	 * Send the event off.
   1269 	 */
   1270 	isc_buffer_init(&rev->buffer, ev->region.base, ev->region.length);
   1271 	isc_buffer_add(&rev->buffer, ev->n);
   1272 	rev->result = ev->result;
   1273 	rev->id = id;
   1274 	rev->addr = ev->address;
   1275 	rev->pktinfo = ev->pktinfo;
   1276 	rev->attributes = ev->attributes;
   1277 	if (queue_response) {
   1278 		ISC_LIST_APPEND(resp->items, rev, ev_link);
   1279 	} else {
   1280 		ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
   1281 			       resp->action, resp->arg, resp, NULL, NULL);
   1282 		request_log(disp, resp, LVL(90),
   1283 			    "[a] Sent event %p buffer %p len %d to task %p",
   1284 			    rev, rev->buffer.base, rev->buffer.length,
   1285 			    resp->task);
   1286 		resp->item_out = true;
   1287 		isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
   1288 	}
   1289 unlock:
   1290 	if (qidlocked) {
   1291 		UNLOCK(&qid->lock);
   1292 	}
   1293 
   1294 	/*
   1295 	 * Restart recv() to get the next packet.
   1296 	 */
   1297 restart:
   1298 	result = startrecv(disp, dispsock);
   1299 	if (result != ISC_R_SUCCESS && dispsock != NULL) {
   1300 		/*
   1301 		 * XXX: wired. There seems to be no recovery process other than
   1302 		 * deactivate this socket anyway (since we cannot start
   1303 		 * receiving, we won't be able to receive a cancel event
   1304 		 * from the user).
   1305 		 */
   1306 		deactivate_dispsocket(disp, dispsock);
   1307 	}
   1308 	isc_event_free(&ev_in);
   1309 	UNLOCK(&disp->lock);
   1310 }
   1311 
   1312 /*
   1313  * General flow:
   1314  *
   1315  * If I/O result == CANCELED, EOF, or error, notify everyone as the
   1316  * various queues drain.
   1317  *
   1318  * If query, restart.
   1319  *
   1320  * If response:
   1321  *	Allocate event, fill in details.
   1322  *		If cannot allocate, restart.
   1323  *	find target.  If not found, restart.
   1324  *	if event queue is not empty, queue.  else, send.
   1325  *	restart.
   1326  */
   1327 static void
   1328 tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
   1329 	dns_dispatch_t *disp = ev_in->ev_arg;
   1330 	dns_tcpmsg_t *tcpmsg = &disp->tcpmsg;
   1331 	dns_messageid_t id;
   1332 	isc_result_t dres;
   1333 	unsigned int flags;
   1334 	dns_dispentry_t *resp;
   1335 	dns_dispatchevent_t *rev;
   1336 	unsigned int bucket;
   1337 	bool killit;
   1338 	bool queue_response;
   1339 	dns_qid_t *qid;
   1340 	int level;
   1341 	char buf[ISC_SOCKADDR_FORMATSIZE];
   1342 
   1343 	UNUSED(task);
   1344 
   1345 	REQUIRE(VALID_DISPATCH(disp));
   1346 
   1347 	qid = disp->qid;
   1348 
   1349 	LOCK(&disp->lock);
   1350 
   1351 	dispatch_log(disp, LVL(90),
   1352 		     "got TCP packet: requests %d, buffers %d, recvs %d",
   1353 		     disp->requests, disp->tcpbuffers, disp->recv_pending);
   1354 
   1355 	INSIST(disp->recv_pending != 0);
   1356 	disp->recv_pending = 0;
   1357 
   1358 	if (disp->refcount == 0) {
   1359 		/*
   1360 		 * This dispatcher is shutting down.  Force cancellation.
   1361 		 */
   1362 		tcpmsg->result = ISC_R_CANCELED;
   1363 	}
   1364 
   1365 	if (tcpmsg->result != ISC_R_SUCCESS) {
   1366 		switch (tcpmsg->result) {
   1367 		case ISC_R_CANCELED:
   1368 			break;
   1369 
   1370 		case ISC_R_EOF:
   1371 			dispatch_log(disp, LVL(90), "shutting down on EOF");
   1372 			do_cancel(disp);
   1373 			break;
   1374 
   1375 		case ISC_R_CONNECTIONRESET:
   1376 			level = ISC_LOG_INFO;
   1377 			goto logit;
   1378 
   1379 		default:
   1380 			level = ISC_LOG_ERROR;
   1381 		logit:
   1382 			isc_sockaddr_format(&tcpmsg->address, buf, sizeof(buf));
   1383 			dispatch_log(disp, level,
   1384 				     "shutting down due to TCP "
   1385 				     "receive error: %s: %s",
   1386 				     buf, isc_result_totext(tcpmsg->result));
   1387 			do_cancel(disp);
   1388 			break;
   1389 		}
   1390 
   1391 		/*
   1392 		 * The event is statically allocated in the tcpmsg
   1393 		 * structure, and destroy_disp() frees the tcpmsg, so we must
   1394 		 * free the event *before* calling destroy_disp().
   1395 		 */
   1396 		isc_event_free(&ev_in);
   1397 
   1398 		disp->shutting_down = 1;
   1399 		disp->shutdown_why = tcpmsg->result;
   1400 
   1401 		/*
   1402 		 * If the recv() was canceled pass the word on.
   1403 		 */
   1404 		killit = destroy_disp_ok(disp);
   1405 		UNLOCK(&disp->lock);
   1406 		if (killit) {
   1407 			isc_task_send(disp->task[0], &disp->ctlevent);
   1408 		}
   1409 		return;
   1410 	}
   1411 
   1412 	dispatch_log(disp, LVL(90), "result %d, length == %d, addr = %p",
   1413 		     tcpmsg->result, tcpmsg->buffer.length,
   1414 		     tcpmsg->buffer.base);
   1415 
   1416 	/*
   1417 	 * Peek into the buffer to see what we can see.
   1418 	 */
   1419 	dres = dns_message_peekheader(&tcpmsg->buffer, &id, &flags);
   1420 	if (dres != ISC_R_SUCCESS) {
   1421 		dispatch_log(disp, LVL(10), "got garbage packet");
   1422 		goto restart;
   1423 	}
   1424 
   1425 	dispatch_log(disp, LVL(92),
   1426 		     "got valid DNS message header, /QR %c, id %u",
   1427 		     (((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0'), id);
   1428 
   1429 	/*
   1430 	 * Allocate an event to send to the query or response client, and
   1431 	 * allocate a new buffer for our use.
   1432 	 */
   1433 
   1434 	/*
   1435 	 * Look at flags.  If query, drop it. If response,
   1436 	 * look to see where it goes.
   1437 	 */
   1438 	if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
   1439 		/*
   1440 		 * Query.
   1441 		 */
   1442 		goto restart;
   1443 	}
   1444 
   1445 	/*
   1446 	 * Response.
   1447 	 */
   1448 	bucket = dns_hash(qid, &tcpmsg->address, id, disp->localport);
   1449 	LOCK(&qid->lock);
   1450 	resp = entry_search(qid, &tcpmsg->address, id, disp->localport, bucket);
   1451 	dispatch_log(disp, LVL(90), "search for response in bucket %d: %s",
   1452 		     bucket, (resp == NULL ? "not found" : "found"));
   1453 
   1454 	if (resp == NULL) {
   1455 		goto unlock;
   1456 	}
   1457 	queue_response = resp->item_out;
   1458 	rev = allocate_devent(disp);
   1459 	if (rev == NULL) {
   1460 		goto unlock;
   1461 	}
   1462 
   1463 	/*
   1464 	 * At this point, rev contains the event we want to fill in, and
   1465 	 * resp contains the information on the place to send it to.
   1466 	 * Send the event off.
   1467 	 */
   1468 	dns_tcpmsg_keepbuffer(tcpmsg, &rev->buffer);
   1469 	disp->tcpbuffers++;
   1470 	rev->result = ISC_R_SUCCESS;
   1471 	rev->id = id;
   1472 	rev->addr = tcpmsg->address;
   1473 	if (queue_response) {
   1474 		ISC_LIST_APPEND(resp->items, rev, ev_link);
   1475 	} else {
   1476 		ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
   1477 			       resp->action, resp->arg, resp, NULL, NULL);
   1478 		request_log(disp, resp, LVL(90),
   1479 			    "[b] Sent event %p buffer %p len %d to task %p",
   1480 			    rev, rev->buffer.base, rev->buffer.length,
   1481 			    resp->task);
   1482 		resp->item_out = true;
   1483 		isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
   1484 	}
   1485 unlock:
   1486 	UNLOCK(&qid->lock);
   1487 
   1488 	/*
   1489 	 * Restart recv() to get the next packet.
   1490 	 */
   1491 restart:
   1492 	(void)startrecv(disp, NULL);
   1493 
   1494 	isc_event_free(&ev_in);
   1495 	UNLOCK(&disp->lock);
   1496 }
   1497 
   1498 /*
   1499  * disp must be locked.
   1500  */
   1501 static isc_result_t
   1502 startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) {
   1503 	isc_result_t res;
   1504 	isc_region_t region;
   1505 	isc_socket_t *sock;
   1506 
   1507 	if (disp->shutting_down == 1) {
   1508 		return (ISC_R_SUCCESS);
   1509 	}
   1510 
   1511 	if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) {
   1512 		return (ISC_R_SUCCESS);
   1513 	}
   1514 
   1515 	if (disp->recv_pending != 0 && dispsock == NULL) {
   1516 		return (ISC_R_SUCCESS);
   1517 	}
   1518 
   1519 	if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 &&
   1520 	    dispsock == NULL)
   1521 	{
   1522 		return (ISC_R_SUCCESS);
   1523 	}
   1524 
   1525 	if (dispsock != NULL) {
   1526 		sock = dispsock->socket;
   1527 	} else {
   1528 		sock = disp->socket;
   1529 	}
   1530 	INSIST(sock != NULL);
   1531 
   1532 	switch (disp->socktype) {
   1533 	/*
   1534 	 * UDP reads are always maximal.
   1535 	 */
   1536 	case isc_sockettype_udp:
   1537 		region.length = disp->mgr->buffersize;
   1538 		region.base = allocate_udp_buffer(disp);
   1539 		if (region.base == NULL) {
   1540 			return (ISC_R_NOMEMORY);
   1541 		}
   1542 		if (dispsock != NULL) {
   1543 			isc_task_t *dt = dispsock->task;
   1544 			isc_socketevent_t *sev = allocate_sevent(
   1545 				disp, sock, ISC_SOCKEVENT_RECVDONE, udp_exrecv,
   1546 				dispsock);
   1547 			if (sev == NULL) {
   1548 				free_buffer(disp, region.base, region.length);
   1549 				return (ISC_R_NOMEMORY);
   1550 			}
   1551 
   1552 			res = isc_socket_recv2(sock, &region, 1, dt, sev, 0);
   1553 			if (res != ISC_R_SUCCESS) {
   1554 				free_buffer(disp, region.base, region.length);
   1555 				return (res);
   1556 			}
   1557 		} else {
   1558 			isc_task_t *dt = disp->task[0];
   1559 			isc_socketevent_t *sev = allocate_sevent(
   1560 				disp, sock, ISC_SOCKEVENT_RECVDONE, udp_shrecv,
   1561 				disp);
   1562 			if (sev == NULL) {
   1563 				free_buffer(disp, region.base, region.length);
   1564 				return (ISC_R_NOMEMORY);
   1565 			}
   1566 
   1567 			res = isc_socket_recv2(sock, &region, 1, dt, sev, 0);
   1568 			if (res != ISC_R_SUCCESS) {
   1569 				free_buffer(disp, region.base, region.length);
   1570 				disp->shutdown_why = res;
   1571 				disp->shutting_down = 1;
   1572 				do_cancel(disp);
   1573 				return (ISC_R_SUCCESS); /* recover by cancel */
   1574 			}
   1575 			INSIST(disp->recv_pending == 0);
   1576 			disp->recv_pending = 1;
   1577 		}
   1578 		break;
   1579 
   1580 	case isc_sockettype_tcp:
   1581 		res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task[0],
   1582 					     tcp_recv, disp);
   1583 		if (res != ISC_R_SUCCESS) {
   1584 			disp->shutdown_why = res;
   1585 			disp->shutting_down = 1;
   1586 			do_cancel(disp);
   1587 			return (ISC_R_SUCCESS); /* recover by cancel */
   1588 		}
   1589 		INSIST(disp->recv_pending == 0);
   1590 		disp->recv_pending = 1;
   1591 		break;
   1592 	default:
   1593 		UNREACHABLE();
   1594 	}
   1595 
   1596 	return (ISC_R_SUCCESS);
   1597 }
   1598 
   1599 /*
   1600  * Mgr must be locked when calling this function.
   1601  */
   1602 static bool
   1603 destroy_mgr_ok(dns_dispatchmgr_t *mgr) {
   1604 	mgr_log(mgr, LVL(90),
   1605 		"destroy_mgr_ok: shuttingdown=%d, listnonempty=%d, ",
   1606 		MGR_IS_SHUTTINGDOWN(mgr), !ISC_LIST_EMPTY(mgr->list));
   1607 	if (!MGR_IS_SHUTTINGDOWN(mgr)) {
   1608 		return (false);
   1609 	}
   1610 	if (!ISC_LIST_EMPTY(mgr->list)) {
   1611 		return (false);
   1612 	}
   1613 	if (isc_refcount_current(&mgr->irefs) != 0) {
   1614 		return (false);
   1615 	}
   1616 
   1617 	return (true);
   1618 }
   1619 
   1620 /*
   1621  * Mgr must be unlocked when calling this function.
   1622  */
   1623 static void
   1624 destroy_mgr(dns_dispatchmgr_t **mgrp) {
   1625 	dns_dispatchmgr_t *mgr;
   1626 
   1627 	mgr = *mgrp;
   1628 	*mgrp = NULL;
   1629 
   1630 	mgr->magic = 0;
   1631 	isc_mutex_destroy(&mgr->lock);
   1632 	mgr->state = 0;
   1633 
   1634 	if (mgr->qid != NULL) {
   1635 		qid_destroy(mgr->mctx, &mgr->qid);
   1636 	}
   1637 
   1638 	isc_mutex_destroy(&mgr->buffer_lock);
   1639 
   1640 	if (mgr->blackhole != NULL) {
   1641 		dns_acl_detach(&mgr->blackhole);
   1642 	}
   1643 
   1644 	if (mgr->stats != NULL) {
   1645 		isc_stats_detach(&mgr->stats);
   1646 	}
   1647 
   1648 	if (mgr->v4ports != NULL) {
   1649 		isc_mem_put(mgr->mctx, mgr->v4ports,
   1650 			    mgr->nv4ports * sizeof(in_port_t));
   1651 	}
   1652 	if (mgr->v6ports != NULL) {
   1653 		isc_mem_put(mgr->mctx, mgr->v6ports,
   1654 			    mgr->nv6ports * sizeof(in_port_t));
   1655 	}
   1656 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(dns_dispatchmgr_t));
   1657 }
   1658 
   1659 static isc_result_t
   1660 open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
   1661 	    unsigned int options, isc_socket_t **sockp,
   1662 	    isc_socket_t *dup_socket, bool duponly) {
   1663 	isc_socket_t *sock;
   1664 	isc_result_t result;
   1665 
   1666 	sock = *sockp;
   1667 	if (sock != NULL) {
   1668 		result = isc_socket_open(sock);
   1669 		if (result != ISC_R_SUCCESS) {
   1670 			return (result);
   1671 		}
   1672 	} else if (dup_socket != NULL &&
   1673 		   (!isc_socket_hasreuseport() || duponly))
   1674 	{
   1675 		result = isc_socket_dup(dup_socket, &sock);
   1676 		if (result != ISC_R_SUCCESS) {
   1677 			return (result);
   1678 		}
   1679 
   1680 		isc_socket_setname(sock, "dispatcher", NULL);
   1681 		*sockp = sock;
   1682 		return (ISC_R_SUCCESS);
   1683 	} else {
   1684 		result = isc_socket_create(mgr, isc_sockaddr_pf(local),
   1685 					   isc_sockettype_udp, &sock);
   1686 		if (result != ISC_R_SUCCESS) {
   1687 			return (result);
   1688 		}
   1689 	}
   1690 
   1691 	isc_socket_setname(sock, "dispatcher", NULL);
   1692 
   1693 #ifndef ISC_ALLOW_MAPPED
   1694 	isc_socket_ipv6only(sock, true);
   1695 #endif /* ifndef ISC_ALLOW_MAPPED */
   1696 	result = isc_socket_bind(sock, local, options);
   1697 	if (result != ISC_R_SUCCESS) {
   1698 		if (*sockp == NULL) {
   1699 			isc_socket_detach(&sock);
   1700 		} else {
   1701 			isc_socket_close(sock);
   1702 		}
   1703 		return (result);
   1704 	}
   1705 
   1706 	*sockp = sock;
   1707 	return (ISC_R_SUCCESS);
   1708 }
   1709 
   1710 /*%
   1711  * Create a temporary port list to set the initial default set of dispatch
   1712  * ports: [1024, 65535].  This is almost meaningless as the application will
   1713  * normally set the ports explicitly, but is provided to fill some minor corner
   1714  * cases.
   1715  */
   1716 static isc_result_t
   1717 create_default_portset(isc_mem_t *mctx, isc_portset_t **portsetp) {
   1718 	isc_result_t result;
   1719 
   1720 	result = isc_portset_create(mctx, portsetp);
   1721 	if (result != ISC_R_SUCCESS) {
   1722 		return (result);
   1723 	}
   1724 	isc_portset_addrange(*portsetp, 1024, 65535);
   1725 
   1726 	return (ISC_R_SUCCESS);
   1727 }
   1728 
   1729 /*
   1730  * Publics.
   1731  */
   1732 
   1733 isc_result_t
   1734 dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) {
   1735 	dns_dispatchmgr_t *mgr;
   1736 	isc_result_t result;
   1737 	isc_portset_t *v4portset = NULL;
   1738 	isc_portset_t *v6portset = NULL;
   1739 
   1740 	REQUIRE(mctx != NULL);
   1741 	REQUIRE(mgrp != NULL && *mgrp == NULL);
   1742 
   1743 	mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
   1744 	*mgr = (dns_dispatchmgr_t){ 0 };
   1745 
   1746 	isc_mem_attach(mctx, &mgr->mctx);
   1747 
   1748 	isc_mutex_init(&mgr->lock);
   1749 	isc_mutex_init(&mgr->buffer_lock);
   1750 
   1751 	isc_refcount_init(&mgr->irefs, 0);
   1752 
   1753 	ISC_LIST_INIT(mgr->list);
   1754 
   1755 	mgr->magic = DNS_DISPATCHMGR_MAGIC;
   1756 
   1757 	result = create_default_portset(mctx, &v4portset);
   1758 	if (result == ISC_R_SUCCESS) {
   1759 		result = create_default_portset(mctx, &v6portset);
   1760 		if (result == ISC_R_SUCCESS) {
   1761 			result = dns_dispatchmgr_setavailports(mgr, v4portset,
   1762 							       v6portset);
   1763 		}
   1764 	}
   1765 	if (v4portset != NULL) {
   1766 		isc_portset_destroy(mctx, &v4portset);
   1767 	}
   1768 	if (v6portset != NULL) {
   1769 		isc_portset_destroy(mctx, &v6portset);
   1770 	}
   1771 	if (result != ISC_R_SUCCESS) {
   1772 		goto kill_dpool;
   1773 	}
   1774 
   1775 	*mgrp = mgr;
   1776 	return (ISC_R_SUCCESS);
   1777 
   1778 kill_dpool:
   1779 	isc_mutex_destroy(&mgr->buffer_lock);
   1780 	isc_mutex_destroy(&mgr->lock);
   1781 	isc_mem_putanddetach(&mctx, mgr, sizeof(dns_dispatchmgr_t));
   1782 
   1783 	return (result);
   1784 }
   1785 
   1786 void
   1787 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) {
   1788 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1789 	if (mgr->blackhole != NULL) {
   1790 		dns_acl_detach(&mgr->blackhole);
   1791 	}
   1792 	dns_acl_attach(blackhole, &mgr->blackhole);
   1793 }
   1794 
   1795 dns_acl_t *
   1796 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr) {
   1797 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1798 	return (mgr->blackhole);
   1799 }
   1800 
   1801 void
   1802 dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
   1803 				 dns_portlist_t *portlist) {
   1804 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1805 	UNUSED(portlist);
   1806 
   1807 	/* This function is deprecated: use dns_dispatchmgr_setavailports(). */
   1808 	return;
   1809 }
   1810 
   1811 dns_portlist_t *
   1812 dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr) {
   1813 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1814 	return (NULL); /* this function is deprecated */
   1815 }
   1816 
   1817 isc_result_t
   1818 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
   1819 			      isc_portset_t *v6portset) {
   1820 	in_port_t *v4ports, *v6ports, p;
   1821 	unsigned int nv4ports, nv6ports, i4, i6;
   1822 
   1823 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1824 
   1825 	nv4ports = isc_portset_nports(v4portset);
   1826 	nv6ports = isc_portset_nports(v6portset);
   1827 
   1828 	v4ports = NULL;
   1829 	if (nv4ports != 0) {
   1830 		v4ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv4ports);
   1831 	}
   1832 	v6ports = NULL;
   1833 	if (nv6ports != 0) {
   1834 		v6ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv6ports);
   1835 	}
   1836 
   1837 	p = 0;
   1838 	i4 = 0;
   1839 	i6 = 0;
   1840 	do {
   1841 		if (isc_portset_isset(v4portset, p)) {
   1842 			INSIST(i4 < nv4ports);
   1843 			v4ports[i4++] = p;
   1844 		}
   1845 		if (isc_portset_isset(v6portset, p)) {
   1846 			INSIST(i6 < nv6ports);
   1847 			v6ports[i6++] = p;
   1848 		}
   1849 	} while (p++ < 65535);
   1850 	INSIST(i4 == nv4ports && i6 == nv6ports);
   1851 
   1852 	PORTBUFLOCK(mgr);
   1853 	if (mgr->v4ports != NULL) {
   1854 		isc_mem_put(mgr->mctx, mgr->v4ports,
   1855 			    mgr->nv4ports * sizeof(in_port_t));
   1856 	}
   1857 	mgr->v4ports = v4ports;
   1858 	mgr->nv4ports = nv4ports;
   1859 
   1860 	if (mgr->v6ports != NULL) {
   1861 		isc_mem_put(mgr->mctx, mgr->v6ports,
   1862 			    mgr->nv6ports * sizeof(in_port_t));
   1863 	}
   1864 	mgr->v6ports = v6ports;
   1865 	mgr->nv6ports = nv6ports;
   1866 	PORTBUFUNLOCK(mgr);
   1867 
   1868 	return (ISC_R_SUCCESS);
   1869 }
   1870 
   1871 static isc_result_t
   1872 dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, unsigned int buffersize,
   1873 		       unsigned int maxbuffers, unsigned int maxrequests,
   1874 		       unsigned int buckets, unsigned int increment) {
   1875 	isc_result_t result;
   1876 
   1877 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1878 	REQUIRE(buffersize >= 512 && buffersize < (64 * 1024));
   1879 	REQUIRE(maxbuffers > 0);
   1880 	REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
   1881 	REQUIRE(increment > buckets);
   1882 	UNUSED(maxrequests);
   1883 
   1884 	/*
   1885 	 * Keep some number of items around.  This should be a config
   1886 	 * option.  For now, keep 8, but later keep at least two even
   1887 	 * if the caller wants less.  This allows us to ensure certain
   1888 	 * things, like an event can be "freed" and the next allocation
   1889 	 * will always succeed.
   1890 	 *
   1891 	 * Note that if limits are placed on anything here, we use one
   1892 	 * event internally, so the actual limit should be "wanted + 1."
   1893 	 *
   1894 	 * XXXMLG
   1895 	 */
   1896 
   1897 	if (maxbuffers < 8) {
   1898 		maxbuffers = 8;
   1899 	}
   1900 
   1901 	LOCK(&mgr->buffer_lock);
   1902 
   1903 	if (maxbuffers > mgr->maxbuffers) {
   1904 		mgr->maxbuffers = maxbuffers;
   1905 	}
   1906 
   1907 	/* Create or adjust socket pool */
   1908 	if (mgr->qid != NULL) {
   1909 		UNLOCK(&mgr->buffer_lock);
   1910 		return (ISC_R_SUCCESS);
   1911 	}
   1912 
   1913 	result = qid_allocate(mgr, buckets, increment, &mgr->qid, true);
   1914 	if (result != ISC_R_SUCCESS) {
   1915 		goto cleanup;
   1916 	}
   1917 
   1918 	mgr->buffersize = buffersize;
   1919 	mgr->maxbuffers = maxbuffers;
   1920 	UNLOCK(&mgr->buffer_lock);
   1921 	return (ISC_R_SUCCESS);
   1922 
   1923 cleanup:
   1924 	UNLOCK(&mgr->buffer_lock);
   1925 	return (result);
   1926 }
   1927 
   1928 void
   1929 dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
   1930 	dns_dispatchmgr_t *mgr;
   1931 	bool killit;
   1932 
   1933 	REQUIRE(mgrp != NULL);
   1934 	REQUIRE(VALID_DISPATCHMGR(*mgrp));
   1935 
   1936 	mgr = *mgrp;
   1937 	*mgrp = NULL;
   1938 
   1939 	LOCK(&mgr->lock);
   1940 	mgr->state |= MGR_SHUTTINGDOWN;
   1941 	killit = destroy_mgr_ok(mgr);
   1942 	UNLOCK(&mgr->lock);
   1943 
   1944 	mgr_log(mgr, LVL(90), "destroy: killit=%d", killit);
   1945 
   1946 	if (killit) {
   1947 		destroy_mgr(&mgr);
   1948 	}
   1949 }
   1950 
   1951 void
   1952 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
   1953 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1954 	REQUIRE(ISC_LIST_EMPTY(mgr->list));
   1955 	REQUIRE(mgr->stats == NULL);
   1956 
   1957 	isc_stats_attach(stats, &mgr->stats);
   1958 }
   1959 
   1960 static int
   1961 port_cmp(const void *key, const void *ent) {
   1962 	in_port_t p1 = *(const in_port_t *)key;
   1963 	in_port_t p2 = *(const in_port_t *)ent;
   1964 
   1965 	if (p1 < p2) {
   1966 		return (-1);
   1967 	} else if (p1 == p2) {
   1968 		return (0);
   1969 	} else {
   1970 		return (1);
   1971 	}
   1972 }
   1973 
   1974 static bool
   1975 portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
   1976 	      isc_sockaddr_t *sockaddrp) {
   1977 	isc_sockaddr_t sockaddr;
   1978 	isc_result_t result;
   1979 	in_port_t *ports, port;
   1980 	unsigned int nports;
   1981 	bool available = false;
   1982 
   1983 	REQUIRE(sock != NULL || sockaddrp != NULL);
   1984 
   1985 	PORTBUFLOCK(mgr);
   1986 	if (sock != NULL) {
   1987 		sockaddrp = &sockaddr;
   1988 		result = isc_socket_getsockname(sock, sockaddrp);
   1989 		if (result != ISC_R_SUCCESS) {
   1990 			goto unlock;
   1991 		}
   1992 	}
   1993 
   1994 	if (isc_sockaddr_pf(sockaddrp) == AF_INET) {
   1995 		ports = mgr->v4ports;
   1996 		nports = mgr->nv4ports;
   1997 	} else {
   1998 		ports = mgr->v6ports;
   1999 		nports = mgr->nv6ports;
   2000 	}
   2001 	if (ports == NULL) {
   2002 		goto unlock;
   2003 	}
   2004 
   2005 	port = isc_sockaddr_getport(sockaddrp);
   2006 	if (bsearch(&port, ports, nports, sizeof(in_port_t), port_cmp) != NULL)
   2007 	{
   2008 		available = true;
   2009 	}
   2010 
   2011 unlock:
   2012 	PORTBUFUNLOCK(mgr);
   2013 	return (available);
   2014 }
   2015 
   2016 #define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
   2017 
   2018 static bool
   2019 local_addr_match(dns_dispatch_t *disp, const isc_sockaddr_t *addr) {
   2020 	isc_sockaddr_t sockaddr;
   2021 	isc_result_t result;
   2022 
   2023 	REQUIRE(disp->socket != NULL);
   2024 
   2025 	if (addr == NULL) {
   2026 		return (true);
   2027 	}
   2028 
   2029 	/*
   2030 	 * Don't match wildcard ports unless the port is available in the
   2031 	 * current configuration.
   2032 	 */
   2033 	if (isc_sockaddr_getport(addr) == 0 &&
   2034 	    isc_sockaddr_getport(&disp->local) == 0 &&
   2035 	    !portavailable(disp->mgr, disp->socket, NULL))
   2036 	{
   2037 		return (false);
   2038 	}
   2039 
   2040 	/*
   2041 	 * Check if we match the binding <address,port>.
   2042 	 * Wildcard ports match/fail here.
   2043 	 */
   2044 	if (isc_sockaddr_equal(&disp->local, addr)) {
   2045 		return (true);
   2046 	}
   2047 	if (isc_sockaddr_getport(addr) == 0) {
   2048 		return (false);
   2049 	}
   2050 
   2051 	/*
   2052 	 * Check if we match a bound wildcard port <address,port>.
   2053 	 */
   2054 	if (!isc_sockaddr_eqaddr(&disp->local, addr)) {
   2055 		return (false);
   2056 	}
   2057 	result = isc_socket_getsockname(disp->socket, &sockaddr);
   2058 	if (result != ISC_R_SUCCESS) {
   2059 		return (false);
   2060 	}
   2061 
   2062 	return (isc_sockaddr_equal(&sockaddr, addr));
   2063 }
   2064 
   2065 /*
   2066  * Requires mgr be locked.
   2067  *
   2068  * No dispatcher can be locked by this thread when calling this function.
   2069  *
   2070  *
   2071  * NOTE:
   2072  *	If a matching dispatcher is found, it is locked after this function
   2073  *	returns, and must be unlocked by the caller.
   2074  */
   2075 static isc_result_t
   2076 dispatch_find(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *local,
   2077 	      unsigned int attributes, unsigned int mask,
   2078 	      dns_dispatch_t **dispp) {
   2079 	dns_dispatch_t *disp;
   2080 	isc_result_t result;
   2081 
   2082 	/*
   2083 	 * Make certain that we will not match a private or exclusive dispatch.
   2084 	 */
   2085 	attributes &= ~(DNS_DISPATCHATTR_PRIVATE | DNS_DISPATCHATTR_EXCLUSIVE);
   2086 	mask |= (DNS_DISPATCHATTR_PRIVATE | DNS_DISPATCHATTR_EXCLUSIVE);
   2087 
   2088 	disp = ISC_LIST_HEAD(mgr->list);
   2089 	while (disp != NULL) {
   2090 		LOCK(&disp->lock);
   2091 		if ((disp->shutting_down == 0) &&
   2092 		    ATTRMATCH(disp->attributes, attributes, mask) &&
   2093 		    local_addr_match(disp, local))
   2094 		{
   2095 			break;
   2096 		}
   2097 		UNLOCK(&disp->lock);
   2098 		disp = ISC_LIST_NEXT(disp, link);
   2099 	}
   2100 
   2101 	if (disp == NULL) {
   2102 		result = ISC_R_NOTFOUND;
   2103 		goto out;
   2104 	}
   2105 
   2106 	*dispp = disp;
   2107 	result = ISC_R_SUCCESS;
   2108 out:
   2109 
   2110 	return (result);
   2111 }
   2112 
   2113 static isc_result_t
   2114 qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
   2115 	     unsigned int increment, dns_qid_t **qidp, bool needsocktable) {
   2116 	dns_qid_t *qid;
   2117 	unsigned int i;
   2118 
   2119 	REQUIRE(VALID_DISPATCHMGR(mgr));
   2120 	REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
   2121 	REQUIRE(increment > buckets);
   2122 	REQUIRE(qidp != NULL && *qidp == NULL);
   2123 
   2124 	qid = isc_mem_get(mgr->mctx, sizeof(*qid));
   2125 
   2126 	qid->qid_table = isc_mem_get(mgr->mctx,
   2127 				     buckets * sizeof(dns_displist_t));
   2128 
   2129 	qid->sock_table = NULL;
   2130 	if (needsocktable) {
   2131 		qid->sock_table = isc_mem_get(
   2132 			mgr->mctx, buckets * sizeof(dispsocketlist_t));
   2133 	}
   2134 
   2135 	isc_mutex_init(&qid->lock);
   2136 
   2137 	for (i = 0; i < buckets; i++) {
   2138 		ISC_LIST_INIT(qid->qid_table[i]);
   2139 		if (qid->sock_table != NULL) {
   2140 			ISC_LIST_INIT(qid->sock_table[i]);
   2141 		}
   2142 	}
   2143 
   2144 	qid->qid_nbuckets = buckets;
   2145 	qid->qid_increment = increment;
   2146 	qid->magic = QID_MAGIC;
   2147 	*qidp = qid;
   2148 	return (ISC_R_SUCCESS);
   2149 }
   2150 
   2151 static void
   2152 qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
   2153 	dns_qid_t *qid;
   2154 
   2155 	REQUIRE(qidp != NULL);
   2156 	qid = *qidp;
   2157 	*qidp = NULL;
   2158 
   2159 	REQUIRE(VALID_QID(qid));
   2160 
   2161 	qid->magic = 0;
   2162 	isc_mem_put(mctx, qid->qid_table,
   2163 		    qid->qid_nbuckets * sizeof(dns_displist_t));
   2164 	if (qid->sock_table != NULL) {
   2165 		isc_mem_put(mctx, qid->sock_table,
   2166 			    qid->qid_nbuckets * sizeof(dispsocketlist_t));
   2167 	}
   2168 	isc_mutex_destroy(&qid->lock);
   2169 	isc_mem_put(mctx, qid, sizeof(*qid));
   2170 }
   2171 
   2172 /*
   2173  * Allocate and set important limits.
   2174  */
   2175 static isc_result_t
   2176 dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
   2177 		  dns_dispatch_t **dispp) {
   2178 	dns_dispatch_t *disp;
   2179 	isc_result_t result;
   2180 
   2181 	REQUIRE(VALID_DISPATCHMGR(mgr));
   2182 	REQUIRE(dispp != NULL && *dispp == NULL);
   2183 
   2184 	/*
   2185 	 * Set up the dispatcher, mostly.  Don't bother setting some of
   2186 	 * the options that are controlled by tcp vs. udp, etc.
   2187 	 */
   2188 
   2189 	disp = isc_mem_get(mgr->mctx, sizeof(*disp));
   2190 	isc_refcount_increment0(&mgr->irefs);
   2191 
   2192 	disp->magic = 0;
   2193 	disp->mgr = mgr;
   2194 	disp->maxrequests = maxrequests;
   2195 	disp->attributes = 0;
   2196 	ISC_LINK_INIT(disp, link);
   2197 	disp->refcount = 1;
   2198 	disp->recv_pending = 0;
   2199 	memset(&disp->local, 0, sizeof(disp->local));
   2200 	memset(&disp->peer, 0, sizeof(disp->peer));
   2201 	disp->localport = 0;
   2202 	disp->shutting_down = 0;
   2203 	disp->shutdown_out = 0;
   2204 	disp->connected = 0;
   2205 	disp->tcpmsg_valid = 0;
   2206 	disp->shutdown_why = ISC_R_UNEXPECTED;
   2207 	disp->requests = 0;
   2208 	disp->tcpbuffers = 0;
   2209 	disp->qid = NULL;
   2210 	ISC_LIST_INIT(disp->activesockets);
   2211 	ISC_LIST_INIT(disp->inactivesockets);
   2212 	disp->nsockets = 0;
   2213 	disp->port_table = NULL;
   2214 	disp->dscp = -1;
   2215 
   2216 	isc_mutex_init(&disp->lock);
   2217 
   2218 	disp->failsafe_ev = allocate_devent(disp);
   2219 	if (disp->failsafe_ev == NULL) {
   2220 		result = ISC_R_NOMEMORY;
   2221 		goto kill_lock;
   2222 	}
   2223 
   2224 	disp->magic = DISPATCH_MAGIC;
   2225 
   2226 	*dispp = disp;
   2227 	return (ISC_R_SUCCESS);
   2228 
   2229 	/*
   2230 	 * error returns
   2231 	 */
   2232 kill_lock:
   2233 	isc_mutex_destroy(&disp->lock);
   2234 	isc_refcount_decrement(&mgr->irefs);
   2235 	isc_mem_put(mgr->mctx, disp, sizeof(*disp));
   2236 
   2237 	return (result);
   2238 }
   2239 
   2240 /*
   2241  * MUST be unlocked, and not used by anything.
   2242  */
   2243 static void
   2244 dispatch_free(dns_dispatch_t **dispp) {
   2245 	dns_dispatch_t *disp;
   2246 	dns_dispatchmgr_t *mgr;
   2247 
   2248 	REQUIRE(VALID_DISPATCH(*dispp));
   2249 	disp = *dispp;
   2250 	*dispp = NULL;
   2251 
   2252 	mgr = disp->mgr;
   2253 	REQUIRE(VALID_DISPATCHMGR(mgr));
   2254 
   2255 	if (disp->tcpmsg_valid) {
   2256 		dns_tcpmsg_invalidate(&disp->tcpmsg);
   2257 		disp->tcpmsg_valid = 0;
   2258 	}
   2259 
   2260 	INSIST(disp->tcpbuffers == 0);
   2261 	INSIST(disp->requests == 0);
   2262 	INSIST(disp->recv_pending == 0);
   2263 	INSIST(ISC_LIST_EMPTY(disp->activesockets));
   2264 	INSIST(ISC_LIST_EMPTY(disp->inactivesockets));
   2265 
   2266 	isc_refcount_decrement(&mgr->irefs);
   2267 	isc_mem_put(mgr->mctx, disp->failsafe_ev, sizeof(*disp->failsafe_ev));
   2268 	disp->failsafe_ev = NULL;
   2269 
   2270 	if (disp->qid != NULL) {
   2271 		qid_destroy(mgr->mctx, &disp->qid);
   2272 	}
   2273 
   2274 	if (disp->port_table != NULL) {
   2275 		for (int i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
   2276 			INSIST(ISC_LIST_EMPTY(disp->port_table[i]));
   2277 		}
   2278 		isc_mem_put(mgr->mctx, disp->port_table,
   2279 			    sizeof(disp->port_table[0]) *
   2280 				    DNS_DISPATCH_PORTTABLESIZE);
   2281 	}
   2282 
   2283 	disp->mgr = NULL;
   2284 	isc_mutex_destroy(&disp->lock);
   2285 	disp->magic = 0;
   2286 	isc_refcount_decrement(&mgr->irefs);
   2287 	isc_mem_put(mgr->mctx, disp, sizeof(*disp));
   2288 }
   2289 
   2290 isc_result_t
   2291 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
   2292 		       isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
   2293 		       const isc_sockaddr_t *destaddr, unsigned int buffersize,
   2294 		       unsigned int maxbuffers, unsigned int maxrequests,
   2295 		       unsigned int buckets, unsigned int increment,
   2296 		       unsigned int attributes, dns_dispatch_t **dispp) {
   2297 	isc_result_t result;
   2298 	dns_dispatch_t *disp;
   2299 
   2300 	UNUSED(maxbuffers);
   2301 	UNUSED(buffersize);
   2302 
   2303 	REQUIRE(VALID_DISPATCHMGR(mgr));
   2304 	REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp);
   2305 	REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0);
   2306 	REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0);
   2307 
   2308 	if (destaddr == NULL) {
   2309 		attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */
   2310 	}
   2311 
   2312 	LOCK(&mgr->lock);
   2313 
   2314 	/*
   2315 	 * dispatch_allocate() checks mgr for us.
   2316 	 * qid_allocate() checks buckets and increment for us.
   2317 	 */
   2318 	disp = NULL;
   2319 	result = dispatch_allocate(mgr, maxrequests, &disp);
   2320 	if (result != ISC_R_SUCCESS) {
   2321 		UNLOCK(&mgr->lock);
   2322 		return (result);
   2323 	}
   2324 
   2325 	result = qid_allocate(mgr, buckets, increment, &disp->qid, false);
   2326 	if (result != ISC_R_SUCCESS) {
   2327 		goto deallocate_dispatch;
   2328 	}
   2329 
   2330 	disp->socktype = isc_sockettype_tcp;
   2331 	disp->socket = NULL;
   2332 	isc_socket_attach(sock, &disp->socket);
   2333 
   2334 	disp->sepool = NULL;
   2335 
   2336 	disp->ntasks = 1;
   2337 	disp->task[0] = NULL;
   2338 	result = isc_task_create(taskmgr, 50, &disp->task[0]);
   2339 	if (result != ISC_R_SUCCESS) {
   2340 		goto kill_socket;
   2341 	}
   2342 
   2343 	disp->ctlevent =
   2344 		isc_event_allocate(mgr->mctx, disp, DNS_EVENT_DISPATCHCONTROL,
   2345 				   destroy_disp, disp, sizeof(isc_event_t));
   2346 
   2347 	isc_task_setname(disp->task[0], "tcpdispatch", disp);
   2348 
   2349 	dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
   2350 	disp->tcpmsg_valid = 1;
   2351 
   2352 	disp->attributes = attributes;
   2353 
   2354 	if (localaddr == NULL) {
   2355 		if (destaddr != NULL) {
   2356 			switch (isc_sockaddr_pf(destaddr)) {
   2357 			case AF_INET:
   2358 				isc_sockaddr_any(&disp->local);
   2359 				break;
   2360 			case AF_INET6:
   2361 				isc_sockaddr_any6(&disp->local);
   2362 				break;
   2363 			}
   2364 		}
   2365 	} else {
   2366 		disp->local = *localaddr;
   2367 	}
   2368 
   2369 	if (destaddr != NULL) {
   2370 		disp->peer = *destaddr;
   2371 	}
   2372 
   2373 	/*
   2374 	 * Append it to the dispatcher list.
   2375 	 */
   2376 	ISC_LIST_APPEND(mgr->list, disp, link);
   2377 	UNLOCK(&mgr->lock);
   2378 
   2379 	mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp);
   2380 	dispatch_log(disp, LVL(90), "created task %p", disp->task[0]);
   2381 	*dispp = disp;
   2382 
   2383 	return (ISC_R_SUCCESS);
   2384 
   2385 kill_socket:
   2386 	isc_socket_detach(&disp->socket);
   2387 deallocate_dispatch:
   2388 	dispatch_free(&disp);
   2389 
   2390 	UNLOCK(&mgr->lock);
   2391 
   2392 	return (result);
   2393 }
   2394 
   2395 isc_result_t
   2396 dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
   2397 		    const isc_sockaddr_t *localaddr, bool *connected,
   2398 		    dns_dispatch_t **dispp) {
   2399 	dns_dispatch_t *disp;
   2400 	isc_result_t result;
   2401 	isc_sockaddr_t peeraddr;
   2402 	isc_sockaddr_t sockname;
   2403 	unsigned int attributes, mask;
   2404 	bool match = false;
   2405 
   2406 	REQUIRE(VALID_DISPATCHMGR(mgr));
   2407 	REQUIRE(destaddr != NULL);
   2408 	REQUIRE(dispp != NULL && *dispp == NULL);
   2409 
   2410 	/* First pass  */
   2411 	attributes = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_CONNECTED;
   2412 	mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE |
   2413 	       DNS_DISPATCHATTR_EXCLUSIVE | DNS_DISPATCHATTR_CONNECTED;
   2414 
   2415 	LOCK(&mgr->lock);
   2416 	disp = ISC_LIST_HEAD(mgr->list);
   2417 	while (disp != NULL && !match) {
   2418 		LOCK(&disp->lock);
   2419 		if ((disp->shutting_down == 0) &&
   2420 		    ATTRMATCH(disp->attributes, attributes, mask) &&
   2421 		    (localaddr == NULL ||
   2422 		     isc_sockaddr_eqaddr(localaddr, &disp->local)))
   2423 		{
   2424 			result = isc_socket_getsockname(disp->socket,
   2425 							&sockname);
   2426 			if (result == ISC_R_SUCCESS) {
   2427 				result = isc_socket_getpeername(disp->socket,
   2428 								&peeraddr);
   2429 			}
   2430 			if (result == ISC_R_SUCCESS &&
   2431 			    isc_sockaddr_equal(destaddr, &peeraddr) &&
   2432 			    (localaddr == NULL ||
   2433 			     isc_sockaddr_eqaddr(localaddr, &sockname)))
   2434 			{
   2435 				/* attach */
   2436 				disp->refcount++;
   2437 				*dispp = disp;
   2438 				match = true;
   2439 				if (connected != NULL) {
   2440 					*connected = true;
   2441 				}
   2442 			}
   2443 		}
   2444 		UNLOCK(&disp->lock);
   2445 		disp = ISC_LIST_NEXT(disp, link);
   2446 	}
   2447 	if (match || connected == NULL) {
   2448 		UNLOCK(&mgr->lock);
   2449 		return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND);
   2450 	}
   2451 
   2452 	/* Second pass, only if connected != NULL */
   2453 	attributes = DNS_DISPATCHATTR_TCP;
   2454 
   2455 	disp = ISC_LIST_HEAD(mgr->list);
   2456 	while (disp != NULL && !match) {
   2457 		LOCK(&disp->lock);
   2458 		if ((disp->shutting_down == 0) &&
   2459 		    ATTRMATCH(disp->attributes, attributes, mask) &&
   2460 		    (localaddr == NULL ||
   2461 		     isc_sockaddr_eqaddr(localaddr, &disp->local)) &&
   2462 		    isc_sockaddr_equal(destaddr, &disp->peer))
   2463 		{
   2464 			/* attach */
   2465 			disp->refcount++;
   2466 			*dispp = disp;
   2467 			match = true;
   2468 		}
   2469 		UNLOCK(&disp->lock);
   2470 		disp = ISC_LIST_NEXT(disp, link);
   2471 	}
   2472 	UNLOCK(&mgr->lock);
   2473 	return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND);
   2474 }
   2475 
   2476 isc_result_t
   2477 dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
   2478 			isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
   2479 			unsigned int buffersize, unsigned int maxbuffers,
   2480 			unsigned int maxrequests, unsigned int buckets,
   2481 			unsigned int increment, unsigned int attributes,
   2482 			unsigned int mask, dns_dispatch_t **dispp,
   2483 			dns_dispatch_t *dup_dispatch) {
   2484 	isc_result_t result;
   2485 	dns_dispatch_t *disp = NULL;
   2486 
   2487 	REQUIRE(VALID_DISPATCHMGR(mgr));
   2488 	REQUIRE(sockmgr != NULL);
   2489 	REQUIRE(localaddr != NULL);
   2490 	REQUIRE(taskmgr != NULL);
   2491 	REQUIRE(buffersize >= 512 && buffersize < (64 * 1024));
   2492 	REQUIRE(maxbuffers > 0);
   2493 	REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
   2494 	REQUIRE(increment > buckets);
   2495 	REQUIRE(dispp != NULL && *dispp == NULL);
   2496 	REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0);
   2497 
   2498 	result = dns_dispatchmgr_setudp(mgr, buffersize, maxbuffers,
   2499 					maxrequests, buckets, increment);
   2500 	if (result != ISC_R_SUCCESS) {
   2501 		return (result);
   2502 	}
   2503 
   2504 	LOCK(&mgr->lock);
   2505 
   2506 	if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
   2507 		REQUIRE(isc_sockaddr_getport(localaddr) == 0);
   2508 		goto createudp;
   2509 	}
   2510 
   2511 	/*
   2512 	 * See if we have a dispatcher that matches.
   2513 	 */
   2514 	if (dup_dispatch == NULL) {
   2515 		result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
   2516 		if (result == ISC_R_SUCCESS) {
   2517 			disp->refcount++;
   2518 
   2519 			if (disp->maxrequests < maxrequests) {
   2520 				disp->maxrequests = maxrequests;
   2521 			}
   2522 
   2523 			if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) ==
   2524 				    0 &&
   2525 			    (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
   2526 			{
   2527 				disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
   2528 				if (disp->recv_pending != 0) {
   2529 					isc_socket_cancel(disp->socket,
   2530 							  disp->task[0],
   2531 							  ISC_SOCKCANCEL_RECV);
   2532 				}
   2533 			}
   2534 
   2535 			UNLOCK(&disp->lock);
   2536 			UNLOCK(&mgr->lock);
   2537 
   2538 			*dispp = disp;
   2539 
   2540 			return (ISC_R_SUCCESS);
   2541 		}
   2542 	}
   2543 
   2544 createudp:
   2545 	/*
   2546 	 * Nope, create one.
   2547 	 */
   2548 	result = dispatch_createudp(
   2549 		mgr, sockmgr, taskmgr, localaddr, maxrequests, attributes,
   2550 		&disp, dup_dispatch == NULL ? NULL : dup_dispatch->socket);
   2551 
   2552 	if (result != ISC_R_SUCCESS) {
   2553 		UNLOCK(&mgr->lock);
   2554 		return (result);
   2555 	}
   2556 
   2557 	UNLOCK(&mgr->lock);
   2558 	*dispp = disp;
   2559 
   2560 	return (ISC_R_SUCCESS);
   2561 }
   2562 
   2563 isc_result_t
   2564 dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
   2565 		    isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
   2566 		    unsigned int buffersize, unsigned int maxbuffers,
   2567 		    unsigned int maxrequests, unsigned int buckets,
   2568 		    unsigned int increment, unsigned int attributes,
   2569 		    unsigned int mask, dns_dispatch_t **dispp) {
   2570 	return (dns_dispatch_getudp_dup(mgr, sockmgr, taskmgr, localaddr,
   2571 					buffersize, maxbuffers, maxrequests,
   2572 					buckets, increment, attributes, mask,
   2573 					dispp, NULL));
   2574 }
   2575 
   2576 /*
   2577  * mgr should be locked.
   2578  */
   2579 
   2580 #ifndef DNS_DISPATCH_HELD
   2581 #define DNS_DISPATCH_HELD 20U
   2582 #endif /* ifndef DNS_DISPATCH_HELD */
   2583 
   2584 static isc_result_t
   2585 get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
   2586 	      isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr,
   2587 	      isc_socket_t **sockp, isc_socket_t *dup_socket, bool duponly) {
   2588 	unsigned int i, j;
   2589 	isc_socket_t *held[DNS_DISPATCH_HELD];
   2590 	isc_sockaddr_t localaddr_bound;
   2591 	isc_socket_t *sock = NULL;
   2592 	isc_result_t result = ISC_R_SUCCESS;
   2593 	bool anyport;
   2594 
   2595 	INSIST(sockp != NULL && *sockp == NULL);
   2596 
   2597 	localaddr_bound = *localaddr;
   2598 	anyport = (isc_sockaddr_getport(localaddr) == 0);
   2599 
   2600 	if (anyport) {
   2601 		unsigned int nports;
   2602 		in_port_t *ports;
   2603 
   2604 		/*
   2605 		 * If no port is specified, we first try to pick up a random
   2606 		 * port by ourselves.
   2607 		 */
   2608 		if (isc_sockaddr_pf(localaddr) == AF_INET) {
   2609 			nports = disp->mgr->nv4ports;
   2610 			ports = disp->mgr->v4ports;
   2611 		} else {
   2612 			nports = disp->mgr->nv6ports;
   2613 			ports = disp->mgr->v6ports;
   2614 		}
   2615 		if (nports == 0) {
   2616 			return (ISC_R_ADDRNOTAVAIL);
   2617 		}
   2618 
   2619 		for (i = 0; i < 1024; i++) {
   2620 			in_port_t prt;
   2621 
   2622 			prt = ports[isc_random_uniform(nports)];
   2623 			isc_sockaddr_setport(&localaddr_bound, prt);
   2624 			result = open_socket(sockmgr, &localaddr_bound, 0,
   2625 					     &sock, NULL, false);
   2626 			/*
   2627 			 * Continue if the port chosen is already in use
   2628 			 * or the OS has reserved it.
   2629 			 */
   2630 			if (result == ISC_R_NOPERM || result == ISC_R_ADDRINUSE)
   2631 			{
   2632 				continue;
   2633 			}
   2634 			disp->localport = prt;
   2635 			*sockp = sock;
   2636 			return (result);
   2637 		}
   2638 
   2639 		/*
   2640 		 * If this fails 1024 times, we then ask the kernel for
   2641 		 * choosing one.
   2642 		 */
   2643 	} else {
   2644 		/* Allow to reuse address for non-random ports. */
   2645 		result = open_socket(sockmgr, localaddr,
   2646 				     ISC_SOCKET_REUSEADDRESS, &sock, dup_socket,
   2647 				     duponly);
   2648 
   2649 		if (result == ISC_R_SUCCESS) {
   2650 			*sockp = sock;
   2651 		}
   2652 
   2653 		return (result);
   2654 	}
   2655 
   2656 	memset(held, 0, sizeof(held));
   2657 	i = 0;
   2658 
   2659 	for (j = 0; j < 0xffffU; j++) {
   2660 		result = open_socket(sockmgr, localaddr, 0, &sock, NULL, false);
   2661 		if (result != ISC_R_SUCCESS) {
   2662 			goto end;
   2663 		} else if (portavailable(mgr, sock, NULL)) {
   2664 			break;
   2665 		}
   2666 		if (held[i] != NULL) {
   2667 			isc_socket_detach(&held[i]);
   2668 		}
   2669 		held[i++] = sock;
   2670 		sock = NULL;
   2671 		if (i == DNS_DISPATCH_HELD) {
   2672 			i = 0;
   2673 		}
   2674 	}
   2675 	if (j == 0xffffU) {
   2676 		mgr_log(mgr, ISC_LOG_ERROR,
   2677 			"avoid-v%s-udp-ports: unable to allocate "
   2678 			"an available port",
   2679 			isc_sockaddr_pf(localaddr) == AF_INET ? "4" : "6");
   2680 		result = ISC_R_FAILURE;
   2681 		goto end;
   2682 	}
   2683 	*sockp = sock;
   2684 
   2685 end:
   2686 	for (i = 0; i < DNS_DISPATCH_HELD; i++) {
   2687 		if (held[i] != NULL) {
   2688 			isc_socket_detach(&held[i]);
   2689 		}
   2690 	}
   2691 
   2692 	return (result);
   2693 }
   2694 
   2695 static isc_result_t
   2696 dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
   2697 		   isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
   2698 		   unsigned int maxrequests, unsigned int attributes,
   2699 		   dns_dispatch_t **dispp, isc_socket_t *dup_socket) {
   2700 	isc_result_t result;
   2701 	dns_dispatch_t *disp;
   2702 	isc_socket_t *sock = NULL;
   2703 	int i = 0;
   2704 	bool duponly = ((attributes & DNS_DISPATCHATTR_CANREUSE) == 0);
   2705 
   2706 	/* This is an attribute needed only at creation time */
   2707 	attributes &= ~DNS_DISPATCHATTR_CANREUSE;
   2708 	/*
   2709 	 * dispatch_allocate() checks mgr for us.
   2710 	 */
   2711 	disp = NULL;
   2712 	result = dispatch_allocate(mgr, maxrequests, &disp);
   2713 	if (result != ISC_R_SUCCESS) {
   2714 		return (result);
   2715 	}
   2716 
   2717 	disp->socktype = isc_sockettype_udp;
   2718 
   2719 	if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
   2720 		result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock,
   2721 				       dup_socket, duponly);
   2722 		if (result != ISC_R_SUCCESS) {
   2723 			goto deallocate_dispatch;
   2724 		}
   2725 
   2726 		if (isc_log_wouldlog(dns_lctx, 90)) {
   2727 			char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   2728 
   2729 			isc_sockaddr_format(localaddr, addrbuf,
   2730 					    ISC_SOCKADDR_FORMATSIZE);
   2731 			mgr_log(mgr, LVL(90),
   2732 				"dns_dispatch_createudp: Created"
   2733 				" UDP dispatch for %s with socket fd %d",
   2734 				addrbuf, isc_socket_getfd(sock));
   2735 		}
   2736 	} else {
   2737 		isc_sockaddr_t sa_any;
   2738 
   2739 		/*
   2740 		 * For dispatches using exclusive sockets with a specific
   2741 		 * source address, we only check if the specified address is
   2742 		 * available on the system.  Query sockets will be created later
   2743 		 * on demand.
   2744 		 */
   2745 		isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
   2746 		if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
   2747 			result = open_socket(sockmgr, localaddr, 0, &sock, NULL,
   2748 					     false);
   2749 			if (sock != NULL) {
   2750 				isc_socket_detach(&sock);
   2751 			}
   2752 			if (result != ISC_R_SUCCESS) {
   2753 				goto deallocate_dispatch;
   2754 			}
   2755 		}
   2756 
   2757 		disp->port_table = isc_mem_get(
   2758 			mgr->mctx, sizeof(disp->port_table[0]) *
   2759 					   DNS_DISPATCH_PORTTABLESIZE);
   2760 		for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
   2761 			ISC_LIST_INIT(disp->port_table[i]);
   2762 		}
   2763 	}
   2764 	disp->socket = sock;
   2765 	disp->local = *localaddr;
   2766 
   2767 	if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
   2768 		disp->ntasks = MAX_INTERNAL_TASKS;
   2769 	} else {
   2770 		disp->ntasks = 1;
   2771 	}
   2772 	for (i = 0; i < disp->ntasks; i++) {
   2773 		disp->task[i] = NULL;
   2774 		result = isc_task_create(taskmgr, 0, &disp->task[i]);
   2775 		if (result != ISC_R_SUCCESS) {
   2776 			while (--i >= 0) {
   2777 				isc_task_shutdown(disp->task[i]);
   2778 				isc_task_detach(&disp->task[i]);
   2779 			}
   2780 			goto kill_socket;
   2781 		}
   2782 		isc_task_setname(disp->task[i], "udpdispatch", disp);
   2783 	}
   2784 
   2785 	disp->ctlevent =
   2786 		isc_event_allocate(mgr->mctx, disp, DNS_EVENT_DISPATCHCONTROL,
   2787 				   destroy_disp, disp, sizeof(isc_event_t));
   2788 
   2789 	disp->sepool = NULL;
   2790 	isc_mem_create(&disp->sepool);
   2791 	isc_mem_setname(disp->sepool, "disp_sepool", NULL);
   2792 
   2793 	attributes &= ~DNS_DISPATCHATTR_TCP;
   2794 	attributes |= DNS_DISPATCHATTR_UDP;
   2795 	disp->attributes = attributes;
   2796 
   2797 	/*
   2798 	 * Append it to the dispatcher list.
   2799 	 */
   2800 	ISC_LIST_APPEND(mgr->list, disp, link);
   2801 
   2802 	mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
   2803 	dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); /* XXX */
   2804 	if (disp->socket != NULL) {
   2805 		dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
   2806 	}
   2807 
   2808 	*dispp = disp;
   2809 
   2810 	return (result);
   2811 
   2812 	/*
   2813 	 * Error returns.
   2814 	 */
   2815 kill_socket:
   2816 	if (disp->socket != NULL) {
   2817 		isc_socket_detach(&disp->socket);
   2818 	}
   2819 deallocate_dispatch:
   2820 	dispatch_free(&disp);
   2821 
   2822 	return (result);
   2823 }
   2824 
   2825 void
   2826 dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {
   2827 	REQUIRE(VALID_DISPATCH(disp));
   2828 	REQUIRE(dispp != NULL && *dispp == NULL);
   2829 
   2830 	LOCK(&disp->lock);
   2831 	disp->refcount++;
   2832 	UNLOCK(&disp->lock);
   2833 
   2834 	*dispp = disp;
   2835 }
   2836 
   2837 /*
   2838  * It is important to lock the manager while we are deleting the dispatch,
   2839  * since dns_dispatch_getudp will call dispatch_find, which returns to
   2840  * the caller a dispatch but does not attach to it until later.  _getudp
   2841  * locks the manager, however, so locking it here will keep us from attaching
   2842  * to a dispatcher that is in the process of going away.
   2843  */
   2844 void
   2845 dns_dispatch_detach(dns_dispatch_t **dispp) {
   2846 	dns_dispatch_t *disp;
   2847 	dispsocket_t *dispsock;
   2848 	bool killit;
   2849 
   2850 	REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));
   2851 
   2852 	disp = *dispp;
   2853 	*dispp = NULL;
   2854 
   2855 	LOCK(&disp->lock);
   2856 
   2857 	INSIST(disp->refcount > 0);
   2858 	disp->refcount--;
   2859 	if (disp->refcount == 0) {
   2860 		if (disp->recv_pending > 0) {
   2861 			isc_socket_cancel(disp->socket, disp->task[0],
   2862 					  ISC_SOCKCANCEL_RECV);
   2863 		}
   2864 		for (dispsock = ISC_LIST_HEAD(disp->activesockets);
   2865 		     dispsock != NULL; dispsock = ISC_LIST_NEXT(dispsock, link))
   2866 		{
   2867 			isc_socket_cancel(dispsock->socket, dispsock->task,
   2868 					  ISC_SOCKCANCEL_RECV);
   2869 		}
   2870 		disp->shutting_down = 1;
   2871 	}
   2872 
   2873 	dispatch_log(disp, LVL(90), "detach: refcount %d", disp->refcount);
   2874 
   2875 	killit = destroy_disp_ok(disp);
   2876 	UNLOCK(&disp->lock);
   2877 	if (killit) {
   2878 		isc_task_send(disp->task[0], &disp->ctlevent);
   2879 	}
   2880 }
   2881 
   2882 isc_result_t
   2883 dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
   2884 			 const isc_sockaddr_t *dest, isc_task_t *task,
   2885 			 isc_taskaction_t action, void *arg,
   2886 			 dns_messageid_t *idp, dns_dispentry_t **resp,
   2887 			 isc_socketmgr_t *sockmgr) {
   2888 	dns_dispentry_t *res;
   2889 	unsigned int bucket;
   2890 	in_port_t localport = 0;
   2891 	dns_messageid_t id;
   2892 	int i;
   2893 	bool ok;
   2894 	dns_qid_t *qid;
   2895 	dispsocket_t *dispsocket = NULL;
   2896 	isc_result_t result;
   2897 
   2898 	REQUIRE(VALID_DISPATCH(disp));
   2899 	REQUIRE(task != NULL);
   2900 	REQUIRE(dest != NULL);
   2901 	REQUIRE(resp != NULL && *resp == NULL);
   2902 	REQUIRE(idp != NULL);
   2903 	if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
   2904 		REQUIRE(sockmgr != NULL);
   2905 	}
   2906 
   2907 	LOCK(&disp->lock);
   2908 
   2909 	if (disp->shutting_down == 1) {
   2910 		UNLOCK(&disp->lock);
   2911 		return (ISC_R_SHUTTINGDOWN);
   2912 	}
   2913 
   2914 	if (disp->requests >= disp->maxrequests) {
   2915 		UNLOCK(&disp->lock);
   2916 		return (ISC_R_QUOTA);
   2917 	}
   2918 
   2919 	if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 &&
   2920 	    disp->nsockets > DNS_DISPATCH_SOCKSQUOTA)
   2921 	{
   2922 		dispsocket_t *oldestsocket;
   2923 		dns_dispentry_t *oldestresp;
   2924 		dns_dispatchevent_t *rev;
   2925 
   2926 		/*
   2927 		 * Kill oldest outstanding query if the number of sockets
   2928 		 * exceeds the quota to keep the room for new queries.
   2929 		 */
   2930 		oldestsocket = ISC_LIST_HEAD(disp->activesockets);
   2931 		oldestresp = oldestsocket->resp;
   2932 		if (oldestresp != NULL && !oldestresp->item_out) {
   2933 			rev = allocate_devent(oldestresp->disp);
   2934 			if (rev != NULL) {
   2935 				rev->buffer.base = NULL;
   2936 				rev->result = ISC_R_CANCELED;
   2937 				rev->id = oldestresp->id;
   2938 				ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL,
   2939 					       DNS_EVENT_DISPATCH,
   2940 					       oldestresp->action,
   2941 					       oldestresp->arg, oldestresp,
   2942 					       NULL, NULL);
   2943 				oldestresp->item_out = true;
   2944 				isc_task_send(oldestresp->task,
   2945 					      ISC_EVENT_PTR(&rev));
   2946 				inc_stats(disp->mgr,
   2947 					  dns_resstatscounter_dispabort);
   2948 			}
   2949 		}
   2950 
   2951 		/*
   2952 		 * Move this entry to the tail so that it won't (easily) be
   2953 		 * examined before actually being canceled.
   2954 		 */
   2955 		ISC_LIST_UNLINK(disp->activesockets, oldestsocket, link);
   2956 		ISC_LIST_APPEND(disp->activesockets, oldestsocket, link);
   2957 	}
   2958 
   2959 	qid = DNS_QID(disp);
   2960 
   2961 	if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
   2962 		/*
   2963 		 * Get a separate UDP socket with a random port number.
   2964 		 */
   2965 		result = get_dispsocket(disp, dest, sockmgr, &dispsocket,
   2966 					&localport);
   2967 		if (result != ISC_R_SUCCESS) {
   2968 			UNLOCK(&disp->lock);
   2969 			inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
   2970 			return (result);
   2971 		}
   2972 	} else {
   2973 		localport = disp->localport;
   2974 	}
   2975 
   2976 	/*
   2977 	 * Try somewhat hard to find an unique ID unless FIXEDID is set
   2978 	 * in which case we use the id passed in via *idp.
   2979 	 */
   2980 	LOCK(&qid->lock);
   2981 	if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
   2982 		id = *idp;
   2983 	} else {
   2984 		id = (dns_messageid_t)isc_random16();
   2985 	}
   2986 	ok = false;
   2987 	i = 0;
   2988 	do {
   2989 		bucket = dns_hash(qid, dest, id, localport);
   2990 		if (entry_search(qid, dest, id, localport, bucket) == NULL) {
   2991 			ok = true;
   2992 			break;
   2993 		}
   2994 		if ((disp->attributes & DNS_DISPATCHATTR_FIXEDID) != 0) {
   2995 			break;
   2996 		}
   2997 		id += qid->qid_increment;
   2998 		id &= 0x0000ffff;
   2999 	} while (i++ < 64);
   3000 	UNLOCK(&qid->lock);
   3001 
   3002 	if (!ok) {
   3003 		UNLOCK(&disp->lock);
   3004 		return (ISC_R_NOMORE);
   3005 	}
   3006 
   3007 	res = isc_mem_get(disp->mgr->mctx, sizeof(*res));
   3008 	isc_refcount_increment0(&disp->mgr->irefs);
   3009 
   3010 	disp->refcount++;
   3011 	disp->requests++;
   3012 	res->task = NULL;
   3013 	isc_task_attach(task, &res->task);
   3014 	res->disp = disp;
   3015 	res->id = id;
   3016 	res->port = localport;
   3017 	res->bucket = bucket;
   3018 	res->host = *dest;
   3019 	res->action = action;
   3020 	res->arg = arg;
   3021 	res->dispsocket = dispsocket;
   3022 	if (dispsocket != NULL) {
   3023 		dispsocket->resp = res;
   3024 	}
   3025 	res->item_out = false;
   3026 	ISC_LIST_INIT(res->items);
   3027 	ISC_LINK_INIT(res, link);
   3028 	res->magic = RESPONSE_MAGIC;
   3029 
   3030 	LOCK(&qid->lock);
   3031 	ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
   3032 	UNLOCK(&qid->lock);
   3033 
   3034 	inc_stats(disp->mgr, (qid == disp->mgr->qid)
   3035 				     ? dns_resstatscounter_disprequdp
   3036 				     : dns_resstatscounter_dispreqtcp);
   3037 
   3038 	request_log(disp, res, LVL(90), "attached to task %p", res->task);
   3039 
   3040 	if (((disp->attributes & DNS_DISPATCHATTR_UDP) != 0) ||
   3041 	    ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0))
   3042 	{
   3043 		result = startrecv(disp, dispsocket);
   3044 		if (result != ISC_R_SUCCESS) {
   3045 			LOCK(&qid->lock);
   3046 			ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
   3047 			UNLOCK(&qid->lock);
   3048 
   3049 			if (dispsocket != NULL) {
   3050 				destroy_dispsocket(disp, &dispsocket);
   3051 			}
   3052 
   3053 			disp->refcount--;
   3054 			disp->requests--;
   3055 
   3056 			dec_stats(disp->mgr,
   3057 				  (qid == disp->mgr->qid)
   3058 					  ? dns_resstatscounter_disprequdp
   3059 					  : dns_resstatscounter_dispreqtcp);
   3060 
   3061 			UNLOCK(&disp->lock);
   3062 			isc_task_detach(&res->task);
   3063 			isc_refcount_decrement(&disp->mgr->irefs);
   3064 			isc_mem_put(disp->mgr->mctx, res, sizeof(*res));
   3065 			return (result);
   3066 		}
   3067 	}
   3068 
   3069 	if (dispsocket != NULL) {
   3070 		ISC_LIST_APPEND(disp->activesockets, dispsocket, link);
   3071 	}
   3072 
   3073 	UNLOCK(&disp->lock);
   3074 
   3075 	*idp = id;
   3076 	*resp = res;
   3077 
   3078 	if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
   3079 		INSIST(res->dispsocket != NULL);
   3080 	}
   3081 
   3082 	return (ISC_R_SUCCESS);
   3083 }
   3084 
   3085 void
   3086 dns_dispatch_starttcp(dns_dispatch_t *disp) {
   3087 	REQUIRE(VALID_DISPATCH(disp));
   3088 
   3089 	dispatch_log(disp, LVL(90), "starttcp %p", disp->task[0]);
   3090 
   3091 	LOCK(&disp->lock);
   3092 	if ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) == 0) {
   3093 		disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
   3094 		(void)startrecv(disp, NULL);
   3095 	}
   3096 	UNLOCK(&disp->lock);
   3097 }
   3098 
   3099 isc_result_t
   3100 dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) {
   3101 	dns_dispatch_t *disp;
   3102 	dns_dispatchevent_t *ev;
   3103 
   3104 	REQUIRE(VALID_RESPONSE(resp));
   3105 	REQUIRE(sockevent != NULL && *sockevent != NULL);
   3106 
   3107 	disp = resp->disp;
   3108 	REQUIRE(VALID_DISPATCH(disp));
   3109 
   3110 	ev = *sockevent;
   3111 	*sockevent = NULL;
   3112 
   3113 	LOCK(&disp->lock);
   3114 
   3115 	REQUIRE(resp->item_out);
   3116 	resp->item_out = false;
   3117 
   3118 	if (ev->buffer.base != NULL) {
   3119 		free_buffer(disp, ev->buffer.base, ev->buffer.length);
   3120 	}
   3121 	free_devent(disp, ev);
   3122 
   3123 	if (disp->shutting_down == 1) {
   3124 		UNLOCK(&disp->lock);
   3125 		return (ISC_R_SHUTTINGDOWN);
   3126 	}
   3127 	ev = ISC_LIST_HEAD(resp->items);
   3128 	if (ev != NULL) {
   3129 		ISC_LIST_UNLINK(resp->items, ev, ev_link);
   3130 		ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH,
   3131 			       resp->action, resp->arg, resp, NULL, NULL);
   3132 		request_log(disp, resp, LVL(90),
   3133 			    "[c] Sent event %p buffer %p len %d to task %p", ev,
   3134 			    ev->buffer.base, ev->buffer.length, resp->task);
   3135 		resp->item_out = true;
   3136 		isc_task_send(resp->task, ISC_EVENT_PTR(&ev));
   3137 	}
   3138 	UNLOCK(&disp->lock);
   3139 	return (ISC_R_SUCCESS);
   3140 }
   3141 
   3142 void
   3143 dns_dispatch_removeresponse(dns_dispentry_t **resp,
   3144 			    dns_dispatchevent_t **sockevent) {
   3145 	dns_dispatchmgr_t *mgr;
   3146 	dns_dispatch_t *disp;
   3147 	dns_dispentry_t *res;
   3148 	dispsocket_t *dispsock;
   3149 	dns_dispatchevent_t *ev;
   3150 	unsigned int bucket;
   3151 	bool killit;
   3152 	unsigned int n;
   3153 	isc_eventlist_t events;
   3154 	dns_qid_t *qid;
   3155 
   3156 	REQUIRE(resp != NULL);
   3157 	REQUIRE(VALID_RESPONSE(*resp));
   3158 
   3159 	res = *resp;
   3160 	*resp = NULL;
   3161 
   3162 	disp = res->disp;
   3163 	REQUIRE(VALID_DISPATCH(disp));
   3164 	mgr = disp->mgr;
   3165 	REQUIRE(VALID_DISPATCHMGR(mgr));
   3166 
   3167 	qid = DNS_QID(disp);
   3168 
   3169 	if (sockevent != NULL) {
   3170 		REQUIRE(*sockevent != NULL);
   3171 		ev = *sockevent;
   3172 		*sockevent = NULL;
   3173 	} else {
   3174 		ev = NULL;
   3175 	}
   3176 
   3177 	LOCK(&disp->lock);
   3178 
   3179 	INSIST(disp->requests > 0);
   3180 	disp->requests--;
   3181 	dec_stats(disp->mgr, (qid == disp->mgr->qid)
   3182 				     ? dns_resstatscounter_disprequdp
   3183 				     : dns_resstatscounter_dispreqtcp);
   3184 	INSIST(disp->refcount > 0);
   3185 	disp->refcount--;
   3186 	if (disp->refcount == 0) {
   3187 		if (disp->recv_pending > 0) {
   3188 			isc_socket_cancel(disp->socket, disp->task[0],
   3189 					  ISC_SOCKCANCEL_RECV);
   3190 		}
   3191 		for (dispsock = ISC_LIST_HEAD(disp->activesockets);
   3192 		     dispsock != NULL; dispsock = ISC_LIST_NEXT(dispsock, link))
   3193 		{
   3194 			isc_socket_cancel(dispsock->socket, dispsock->task,
   3195 					  ISC_SOCKCANCEL_RECV);
   3196 		}
   3197 		disp->shutting_down = 1;
   3198 	}
   3199 
   3200 	bucket = res->bucket;
   3201 
   3202 	LOCK(&qid->lock);
   3203 	ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
   3204 	UNLOCK(&qid->lock);
   3205 
   3206 	if (ev == NULL && res->item_out) {
   3207 		/*
   3208 		 * We've posted our event, but the caller hasn't gotten it
   3209 		 * yet.  Take it back.
   3210 		 */
   3211 		ISC_LIST_INIT(events);
   3212 		n = isc_task_unsend(res->task, res, DNS_EVENT_DISPATCH, NULL,
   3213 				    &events);
   3214 		/*
   3215 		 * We had better have gotten it back.
   3216 		 */
   3217 		INSIST(n == 1);
   3218 		ev = (dns_dispatchevent_t *)ISC_LIST_HEAD(events);
   3219 	}
   3220 
   3221 	if (ev != NULL) {
   3222 		REQUIRE(res->item_out);
   3223 		res->item_out = false;
   3224 		if (ev->buffer.base != NULL) {
   3225 			free_buffer(disp, ev->buffer.base, ev->buffer.length);
   3226 		}
   3227 		free_devent(disp, ev);
   3228 	}
   3229 
   3230 	request_log(disp, res, LVL(90), "detaching from task %p", res->task);
   3231 	isc_task_detach(&res->task);
   3232 
   3233 	if (res->dispsocket != NULL) {
   3234 		isc_socket_cancel(res->dispsocket->socket,
   3235 				  res->dispsocket->task, ISC_SOCKCANCEL_RECV);
   3236 		res->dispsocket->resp = NULL;
   3237 	}
   3238 
   3239 	/*
   3240 	 * Free any buffered responses as well
   3241 	 */
   3242 	ev = ISC_LIST_HEAD(res->items);
   3243 	while (ev != NULL) {
   3244 		ISC_LIST_UNLINK(res->items, ev, ev_link);
   3245 		if (ev->buffer.base != NULL) {
   3246 			free_buffer(disp, ev->buffer.base, ev->buffer.length);
   3247 		}
   3248 		free_devent(disp, ev);
   3249 		ev = ISC_LIST_HEAD(res->items);
   3250 	}
   3251 	res->magic = 0;
   3252 	isc_refcount_decrement(&disp->mgr->irefs);
   3253 	isc_mem_put(disp->mgr->mctx, res, sizeof(*res));
   3254 	if (disp->shutting_down == 1) {
   3255 		do_cancel(disp);
   3256 	} else {
   3257 		(void)startrecv(disp, NULL);
   3258 	}
   3259 
   3260 	killit = destroy_disp_ok(disp);
   3261 	UNLOCK(&disp->lock);
   3262 	if (killit) {
   3263 		isc_task_send(disp->task[0], &disp->ctlevent);
   3264 	}
   3265 }
   3266 
   3267 /*
   3268  * disp must be locked.
   3269  */
   3270 static void
   3271 do_cancel(dns_dispatch_t *disp) {
   3272 	dns_dispatchevent_t *ev;
   3273 	dns_dispentry_t *resp;
   3274 	dns_qid_t *qid;
   3275 
   3276 	if (disp->shutdown_out == 1) {
   3277 		return;
   3278 	}
   3279 
   3280 	qid = DNS_QID(disp);
   3281 
   3282 	/*
   3283 	 * Search for the first response handler without packets outstanding
   3284 	 * unless a specific handler is given.
   3285 	 */
   3286 	LOCK(&qid->lock);
   3287 	for (resp = linear_first(qid); resp != NULL && resp->item_out;
   3288 	     /* Empty. */)
   3289 	{
   3290 		resp = linear_next(qid, resp);
   3291 	}
   3292 
   3293 	/*
   3294 	 * No one to send the cancel event to, so nothing to do.
   3295 	 */
   3296 	if (resp == NULL) {
   3297 		goto unlock;
   3298 	}
   3299 
   3300 	/*
   3301 	 * Send the shutdown failsafe event to this resp.
   3302 	 */
   3303 	ev = disp->failsafe_ev;
   3304 	ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH,
   3305 		       resp->action, resp->arg, resp, NULL, NULL);
   3306 	ev->result = disp->shutdown_why;
   3307 	ev->buffer.base = NULL;
   3308 	ev->buffer.length = 0;
   3309 	disp->shutdown_out = 1;
   3310 	request_log(disp, resp, LVL(10), "cancel: failsafe event %p -> task %p",
   3311 		    ev, resp->task);
   3312 	resp->item_out = true;
   3313 	isc_task_send(resp->task, ISC_EVENT_PTR(&ev));
   3314 unlock:
   3315 	UNLOCK(&qid->lock);
   3316 }
   3317 
   3318 isc_socket_t *
   3319 dns_dispatch_getsocket(dns_dispatch_t *disp) {
   3320 	REQUIRE(VALID_DISPATCH(disp));
   3321 
   3322 	return (disp->socket);
   3323 }
   3324 
   3325 isc_socket_t *
   3326 dns_dispatch_getentrysocket(dns_dispentry_t *resp) {
   3327 	REQUIRE(VALID_RESPONSE(resp));
   3328 
   3329 	if (resp->dispsocket != NULL) {
   3330 		return (resp->dispsocket->socket);
   3331 	} else {
   3332 		return (NULL);
   3333 	}
   3334 }
   3335 
   3336 isc_result_t
   3337 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {
   3338 	REQUIRE(VALID_DISPATCH(disp));
   3339 	REQUIRE(addrp != NULL);
   3340 
   3341 	if (disp->socktype == isc_sockettype_udp) {
   3342 		*addrp = disp->local;
   3343 		return (ISC_R_SUCCESS);
   3344 	}
   3345 	return (ISC_R_NOTIMPLEMENTED);
   3346 }
   3347 
   3348 void
   3349 dns_dispatch_cancel(dns_dispatch_t *disp) {
   3350 	REQUIRE(VALID_DISPATCH(disp));
   3351 
   3352 	LOCK(&disp->lock);
   3353 
   3354 	if (disp->shutting_down == 1) {
   3355 		UNLOCK(&disp->lock);
   3356 		return;
   3357 	}
   3358 
   3359 	disp->shutdown_why = ISC_R_CANCELED;
   3360 	disp->shutting_down = 1;
   3361 	do_cancel(disp);
   3362 
   3363 	UNLOCK(&disp->lock);
   3364 
   3365 	return;
   3366 }
   3367 
   3368 unsigned int
   3369 dns_dispatch_getattributes(dns_dispatch_t *disp) {
   3370 	REQUIRE(VALID_DISPATCH(disp));
   3371 
   3372 	/*
   3373 	 * We don't bother locking disp here; it's the caller's responsibility
   3374 	 * to use only non volatile flags.
   3375 	 */
   3376 	return (disp->attributes);
   3377 }
   3378 
   3379 void
   3380 dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes,
   3381 			      unsigned int mask) {
   3382 	REQUIRE(VALID_DISPATCH(disp));
   3383 	/* Exclusive attribute can only be set on creation */
   3384 	REQUIRE((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0);
   3385 	/* Also, a dispatch with randomport specified cannot start listening */
   3386 	REQUIRE((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0 ||
   3387 		(attributes & DNS_DISPATCHATTR_NOLISTEN) == 0);
   3388 
   3389 	/* XXXMLG
   3390 	 * Should check for valid attributes here!
   3391 	 */
   3392 
   3393 	LOCK(&disp->lock);
   3394 
   3395 	if ((mask & DNS_DISPATCHATTR_NOLISTEN) != 0) {
   3396 		if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 &&
   3397 		    (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0)
   3398 		{
   3399 			disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN;
   3400 			(void)startrecv(disp, NULL);
   3401 		} else if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) ==
   3402 				   0 &&
   3403 			   (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
   3404 		{
   3405 			disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
   3406 			if (disp->recv_pending != 0) {
   3407 				isc_socket_cancel(disp->socket, disp->task[0],
   3408 						  ISC_SOCKCANCEL_RECV);
   3409 			}
   3410 		}
   3411 	}
   3412 
   3413 	disp->attributes &= ~mask;
   3414 	disp->attributes |= (attributes & mask);
   3415 	UNLOCK(&disp->lock);
   3416 }
   3417 
   3418 void
   3419 dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
   3420 	void *buf;
   3421 	isc_socketevent_t *sevent, *newsevent;
   3422 
   3423 	REQUIRE(VALID_DISPATCH(disp));
   3424 	REQUIRE(event != NULL);
   3425 
   3426 	if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) {
   3427 		return;
   3428 	}
   3429 
   3430 	sevent = (isc_socketevent_t *)event;
   3431 	INSIST(sevent->n <= disp->mgr->buffersize);
   3432 
   3433 	newsevent = (isc_socketevent_t *)isc_event_allocate(
   3434 		disp->mgr->mctx, NULL, DNS_EVENT_IMPORTRECVDONE, udp_shrecv,
   3435 		disp, sizeof(isc_socketevent_t));
   3436 
   3437 	buf = allocate_udp_buffer(disp);
   3438 	if (buf == NULL) {
   3439 		isc_event_free(ISC_EVENT_PTR(&newsevent));
   3440 		return;
   3441 	}
   3442 	memmove(buf, sevent->region.base, sevent->n);
   3443 	newsevent->region.base = buf;
   3444 	newsevent->region.length = disp->mgr->buffersize;
   3445 	newsevent->n = sevent->n;
   3446 	newsevent->result = sevent->result;
   3447 	newsevent->address = sevent->address;
   3448 	newsevent->timestamp = sevent->timestamp;
   3449 	newsevent->pktinfo = sevent->pktinfo;
   3450 	newsevent->attributes = sevent->attributes;
   3451 
   3452 	isc_task_send(disp->task[0], ISC_EVENT_PTR(&newsevent));
   3453 }
   3454 
   3455 dns_dispatch_t *
   3456 dns_dispatchset_get(dns_dispatchset_t *dset) {
   3457 	dns_dispatch_t *disp;
   3458 
   3459 	/* check that dispatch set is configured */
   3460 	if (dset == NULL || dset->ndisp == 0) {
   3461 		return (NULL);
   3462 	}
   3463 
   3464 	LOCK(&dset->lock);
   3465 	disp = dset->dispatches[dset->cur];
   3466 	dset->cur++;
   3467 	if (dset->cur == dset->ndisp) {
   3468 		dset->cur = 0;
   3469 	}
   3470 	UNLOCK(&dset->lock);
   3471 
   3472 	return (disp);
   3473 }
   3474 
   3475 isc_result_t
   3476 dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
   3477 		       isc_taskmgr_t *taskmgr, dns_dispatch_t *source,
   3478 		       dns_dispatchset_t **dsetp, int n) {
   3479 	isc_result_t result;
   3480 	dns_dispatchset_t *dset;
   3481 	dns_dispatchmgr_t *mgr;
   3482 	int i, j;
   3483 
   3484 	REQUIRE(VALID_DISPATCH(source));
   3485 	REQUIRE((source->attributes & DNS_DISPATCHATTR_UDP) != 0);
   3486 	REQUIRE(dsetp != NULL && *dsetp == NULL);
   3487 
   3488 	mgr = source->mgr;
   3489 
   3490 	dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t));
   3491 	memset(dset, 0, sizeof(*dset));
   3492 
   3493 	isc_mutex_init(&dset->lock);
   3494 
   3495 	dset->dispatches = isc_mem_get(mctx, sizeof(dns_dispatch_t *) * n);
   3496 
   3497 	isc_mem_attach(mctx, &dset->mctx);
   3498 	dset->ndisp = n;
   3499 	dset->cur = 0;
   3500 
   3501 	dset->dispatches[0] = NULL;
   3502 	dns_dispatch_attach(source, &dset->dispatches[0]);
   3503 
   3504 	LOCK(&mgr->lock);
   3505 	for (i = 1; i < n; i++) {
   3506 		dset->dispatches[i] = NULL;
   3507 		result = dispatch_createudp(
   3508 			mgr, sockmgr, taskmgr, &source->local,
   3509 			source->maxrequests, source->attributes,
   3510 			&dset->dispatches[i], source->socket);
   3511 		if (result != ISC_R_SUCCESS) {
   3512 			goto fail;
   3513 		}
   3514 	}
   3515 
   3516 	UNLOCK(&mgr->lock);
   3517 	*dsetp = dset;
   3518 
   3519 	return (ISC_R_SUCCESS);
   3520 
   3521 fail:
   3522 	UNLOCK(&mgr->lock);
   3523 
   3524 	for (j = 0; j < i; j++) {
   3525 		dns_dispatch_detach(&(dset->dispatches[j]));
   3526 	}
   3527 	isc_mem_put(mctx, dset->dispatches, sizeof(dns_dispatch_t *) * n);
   3528 	if (dset->mctx == mctx) {
   3529 		isc_mem_detach(&dset->mctx);
   3530 	}
   3531 
   3532 	isc_mutex_destroy(&dset->lock);
   3533 	isc_mem_put(mctx, dset, sizeof(dns_dispatchset_t));
   3534 	return (result);
   3535 }
   3536 
   3537 void
   3538 dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task) {
   3539 	int i;
   3540 
   3541 	REQUIRE(dset != NULL);
   3542 
   3543 	for (i = 0; i < dset->ndisp; i++) {
   3544 		isc_socket_t *sock;
   3545 		sock = dns_dispatch_getsocket(dset->dispatches[i]);
   3546 		isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
   3547 	}
   3548 }
   3549 
   3550 void
   3551 dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
   3552 	dns_dispatchset_t *dset;
   3553 	int i;
   3554 
   3555 	REQUIRE(dsetp != NULL && *dsetp != NULL);
   3556 
   3557 	dset = *dsetp;
   3558 	*dsetp = NULL;
   3559 	for (i = 0; i < dset->ndisp; i++) {
   3560 		dns_dispatch_detach(&(dset->dispatches[i]));
   3561 	}
   3562 	isc_mem_put(dset->mctx, dset->dispatches,
   3563 		    sizeof(dns_dispatch_t *) * dset->ndisp);
   3564 	isc_mutex_destroy(&dset->lock);
   3565 	isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
   3566 }
   3567 
   3568 void
   3569 dns_dispatch_setdscp(dns_dispatch_t *disp, isc_dscp_t dscp) {
   3570 	REQUIRE(VALID_DISPATCH(disp));
   3571 	disp->dscp = dscp;
   3572 }
   3573 
   3574 isc_dscp_t
   3575 dns_dispatch_getdscp(dns_dispatch_t *disp) {
   3576 	REQUIRE(VALID_DISPATCH(disp));
   3577 	return (disp->dscp);
   3578 }
   3579 
   3580 #if 0
   3581 void
   3582 dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {
   3583 	dns_dispatch_t *disp;
   3584 	char foo[1024];
   3585 
   3586 	disp = ISC_LIST_HEAD(mgr->list);
   3587 	while (disp != NULL) {
   3588 		isc_sockaddr_format(&disp->local, foo, sizeof(foo));
   3589 		printf("\tdispatch %p, addr %s\n", disp, foo);
   3590 		disp = ISC_LIST_NEXT(disp, link);
   3591 	}
   3592 }
   3593 #endif /* if 0 */
   3594