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