Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / bind-9.3 / lib / dns / dispatch.c
1 /*
2  * Copyright (C) 2004, 2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.101.2.6.2.13 2006/07/19 00:44:04 marka Exp $ */
19
20 #include <config.h>
21
22 #include <stdlib.h>
23
24 #include <isc/entropy.h>
25 #include <isc/lfsr.h>
26 #include <isc/mem.h>
27 #include <isc/mutex.h>
28 #include <isc/print.h>
29 #include <isc/string.h>
30 #include <isc/task.h>
31 #include <isc/util.h>
32
33 #include <dns/acl.h>
34 #include <dns/dispatch.h>
35 #include <dns/events.h>
36 #include <dns/log.h>
37 #include <dns/message.h>
38 #include <dns/portlist.h>
39 #include <dns/tcpmsg.h>
40 #include <dns/types.h>
41
42 typedef ISC_LIST(dns_dispentry_t)       dns_displist_t;
43
44 typedef struct dns_qid {
45         unsigned int    magic;
46         unsigned int    qid_nbuckets;   /* hash table size */
47         unsigned int    qid_increment;  /* id increment on collision */
48         isc_mutex_t     lock;
49         isc_lfsr_t      qid_lfsr1;      /* state generator info */
50         isc_lfsr_t      qid_lfsr2;      /* state generator info */
51         dns_displist_t  *qid_table;     /* the table itself */
52 } dns_qid_t;
53
54 struct dns_dispatchmgr {
55         /* Unlocked. */
56         unsigned int                    magic;
57         isc_mem_t                      *mctx;
58         dns_acl_t                      *blackhole;
59         dns_portlist_t                 *portlist;
60
61         /* Locked by "lock". */
62         isc_mutex_t                     lock;
63         unsigned int                    state;
64         ISC_LIST(dns_dispatch_t)        list;
65
66         /* locked by buffer lock */
67         dns_qid_t                       *qid;
68         isc_mutex_t                     buffer_lock;
69         unsigned int                    buffers;    /* allocated buffers */
70         unsigned int                    buffersize; /* size of each buffer */
71         unsigned int                    maxbuffers; /* max buffers */
72
73         /* Locked internally. */
74         isc_mutex_t                     pool_lock;
75         isc_mempool_t                  *epool;  /* memory pool for events */
76         isc_mempool_t                  *rpool;  /* memory pool for replies */
77         isc_mempool_t                  *dpool;  /* dispatch allocations */
78         isc_mempool_t                  *bpool;  /* memory pool for buffers */
79
80         isc_entropy_t                  *entropy; /* entropy source */
81 };
82
83 #define MGR_SHUTTINGDOWN                0x00000001U
84 #define MGR_IS_SHUTTINGDOWN(l)  (((l)->state & MGR_SHUTTINGDOWN) != 0)
85
86 #define IS_PRIVATE(d)   (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
87
88 struct dns_dispentry {
89         unsigned int                    magic;
90         dns_dispatch_t                 *disp;
91         dns_messageid_t                 id;
92         unsigned int                    bucket;
93         isc_sockaddr_t                  host;
94         isc_task_t                     *task;
95         isc_taskaction_t                action;
96         void                           *arg;
97         isc_boolean_t                   item_out;
98         ISC_LIST(dns_dispatchevent_t)   items;
99         ISC_LINK(dns_dispentry_t)       link;
100 };
101
102 #define INVALID_BUCKET          (0xffffdead)
103
104 struct dns_dispatch {
105         /* Unlocked. */
106         unsigned int            magic;          /* magic */
107         dns_dispatchmgr_t      *mgr;            /* dispatch manager */
108         isc_task_t             *task;           /* internal task */
109         isc_socket_t           *socket;         /* isc socket attached to */
110         isc_sockaddr_t          local;          /* local address */
111         unsigned int            maxrequests;    /* max requests */
112         isc_event_t            *ctlevent;
113
114         /* Locked by mgr->lock. */
115         ISC_LINK(dns_dispatch_t) link;
116
117         /* Locked by "lock". */
118         isc_mutex_t             lock;           /* locks all below */
119         isc_sockettype_t        socktype;
120         unsigned int            attributes;
121         unsigned int            refcount;       /* number of users */
122         dns_dispatchevent_t    *failsafe_ev;    /* failsafe cancel event */
123         unsigned int            shutting_down : 1,
124                                 shutdown_out : 1,
125                                 connected : 1,
126                                 tcpmsg_valid : 1,
127                                 recv_pending : 1; /* is a recv() pending? */
128         isc_result_t            shutdown_why;
129         unsigned int            requests;       /* how many requests we have */
130         unsigned int            tcpbuffers;     /* allocated buffers */
131         dns_tcpmsg_t            tcpmsg;         /* for tcp streams */
132         dns_qid_t               *qid;
133 };
134
135 #define QID_MAGIC               ISC_MAGIC('Q', 'i', 'd', ' ')
136 #define VALID_QID(e)            ISC_MAGIC_VALID((e), QID_MAGIC)
137
138 #define RESPONSE_MAGIC          ISC_MAGIC('D', 'r', 's', 'p')
139 #define VALID_RESPONSE(e)       ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
140
141 #define DISPATCH_MAGIC          ISC_MAGIC('D', 'i', 's', 'p')
142 #define VALID_DISPATCH(e)       ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
143
144 #define DNS_DISPATCHMGR_MAGIC   ISC_MAGIC('D', 'M', 'g', 'r')
145 #define VALID_DISPATCHMGR(e)    ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
146
147 #define DNS_QID(disp) ((disp)->socktype == isc_sockettype_tcp) ? \
148                        (disp)->qid : (disp)->mgr->qid
149 /*
150  * Statics.
151  */
152 static dns_dispentry_t *bucket_search(dns_qid_t *, isc_sockaddr_t *,
153                                       dns_messageid_t, unsigned int);
154 static isc_boolean_t destroy_disp_ok(dns_dispatch_t *);
155 static void destroy_disp(isc_task_t *task, isc_event_t *event);
156 static void udp_recv(isc_task_t *, isc_event_t *);
157 static void tcp_recv(isc_task_t *, isc_event_t *);
158 static void startrecv(dns_dispatch_t *);
159 static dns_messageid_t dns_randomid(dns_qid_t *);
160 static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t);
161 static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
162 static void *allocate_udp_buffer(dns_dispatch_t *disp);
163 static inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
164 static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp);
165 static void do_cancel(dns_dispatch_t *disp);
166 static dns_dispentry_t *linear_first(dns_qid_t *disp);
167 static dns_dispentry_t *linear_next(dns_qid_t *disp,
168                                     dns_dispentry_t *resp);
169 static void dispatch_free(dns_dispatch_t **dispp);
170 static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
171                                        isc_socketmgr_t *sockmgr,
172                                        isc_taskmgr_t *taskmgr,
173                                        isc_sockaddr_t *localaddr,
174                                        unsigned int maxrequests,
175                                        unsigned int attributes,
176                                        dns_dispatch_t **dispp);
177 static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr);
178 static void destroy_mgr(dns_dispatchmgr_t **mgrp);
179 static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
180                                  unsigned int increment, dns_qid_t **qidp);
181 static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
182
183 #define LVL(x) ISC_LOG_DEBUG(x)
184
185 static void
186 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...)
187      ISC_FORMAT_PRINTF(3, 4);
188
189 static void
190 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {
191         char msgbuf[2048];
192         va_list ap;
193
194         if (! isc_log_wouldlog(dns_lctx, level))
195                 return;
196
197         va_start(ap, fmt);
198         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
199         va_end(ap);
200
201         isc_log_write(dns_lctx,
202                       DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH,
203                       level, "dispatchmgr %p: %s", mgr, msgbuf);
204 }
205
206 static void
207 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)
208      ISC_FORMAT_PRINTF(3, 4);
209
210 static void
211 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) {
212         char msgbuf[2048];
213         va_list ap;
214
215         if (! isc_log_wouldlog(dns_lctx, level))
216                 return;
217
218         va_start(ap, fmt);
219         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
220         va_end(ap);
221
222         isc_log_write(dns_lctx,
223                       DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH,
224                       level, "dispatch %p: %s", disp, msgbuf);
225 }
226
227 static void
228 request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
229             int level, const char *fmt, ...)
230      ISC_FORMAT_PRINTF(4, 5);
231
232 static void
233 request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
234             int level, const char *fmt, ...)
235 {
236         char msgbuf[2048];
237         char peerbuf[256];
238         va_list ap;
239
240         if (! isc_log_wouldlog(dns_lctx, level))
241                 return;
242
243         va_start(ap, fmt);
244         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
245         va_end(ap);
246
247         if (VALID_RESPONSE(resp)) {
248                 isc_sockaddr_format(&resp->host, peerbuf, sizeof(peerbuf));
249                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
250                               DNS_LOGMODULE_DISPATCH, level,
251                               "dispatch %p response %p %s: %s", disp, resp,
252                               peerbuf, msgbuf);
253         } else {
254                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
255                               DNS_LOGMODULE_DISPATCH, level,
256                               "dispatch %p req/resp %p: %s", disp, resp,
257                               msgbuf);
258         }
259 }
260
261 static void
262 reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
263 {
264         dns_dispatchmgr_t *mgr = arg;
265         isc_result_t result;
266         isc_uint32_t val;
267
268         REQUIRE(VALID_DISPATCHMGR(mgr));
269
270         if (mgr->entropy != NULL) {
271                 result = isc_entropy_getdata(mgr->entropy, &val, sizeof(val),
272                                              NULL, 0);
273                 INSIST(result == ISC_R_SUCCESS);
274                 lfsr->count = (val & 0x1f) + 32;
275                 lfsr->state = val;
276                 return;
277         }
278
279         lfsr->count = (random() & 0x1f) + 32;   /* From 32 to 63 states */
280         lfsr->state = random();
281 }
282
283 /*
284  * Return an unpredictable message ID.
285  */
286 static dns_messageid_t
287 dns_randomid(dns_qid_t *qid) {
288         isc_uint32_t id;
289
290         id = isc_lfsr_generate32(&qid->qid_lfsr1, &qid->qid_lfsr2);
291
292         return (dns_messageid_t)(id & 0xFFFF);
293 }
294
295 /*
296  * Return a hash of the destination and message id.
297  */
298 static isc_uint32_t
299 dns_hash(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id) {
300         unsigned int ret;
301
302         ret = isc_sockaddr_hash(dest, ISC_TRUE);
303         ret ^= id;
304         ret %= qid->qid_nbuckets;
305
306         INSIST(ret < qid->qid_nbuckets);
307
308         return (ret);
309 }
310
311 /*
312  * Find the first entry in 'qid'.  Returns NULL if there are no entries.
313  */
314 static dns_dispentry_t *
315 linear_first(dns_qid_t *qid) {
316         dns_dispentry_t *ret;
317         unsigned int bucket;
318
319         bucket = 0;
320
321         while (bucket < qid->qid_nbuckets) {
322                 ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
323                 if (ret != NULL)
324                         return (ret);
325                 bucket++;
326         }
327
328         return (NULL);
329 }
330
331 /*
332  * Find the next entry after 'resp' in 'qid'.  Return NULL if there are
333  * no more entries.
334  */
335 static dns_dispentry_t *
336 linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {
337         dns_dispentry_t *ret;
338         unsigned int bucket;
339
340         ret = ISC_LIST_NEXT(resp, link);
341         if (ret != NULL)
342                 return (ret);
343
344         bucket = resp->bucket;
345         bucket++;
346         while (bucket < qid->qid_nbuckets) {
347                 ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
348                 if (ret != NULL)
349                         return (ret);
350                 bucket++;
351         }
352
353         return (NULL);
354 }
355
356 /*
357  * The dispatch must be locked.
358  */
359 static isc_boolean_t
360 destroy_disp_ok(dns_dispatch_t *disp)
361 {
362         if (disp->refcount != 0)
363                 return (ISC_FALSE);
364
365         if (disp->recv_pending != 0)
366                 return (ISC_FALSE);
367
368         if (disp->shutting_down == 0)
369                 return (ISC_FALSE);
370
371         return (ISC_TRUE);
372 }
373
374
375 /*
376  * Called when refcount reaches 0 (and safe to destroy).
377  *
378  * The dispatcher must not be locked.
379  * The manager must be locked.
380  */
381 static void
382 destroy_disp(isc_task_t *task, isc_event_t *event) {
383         dns_dispatch_t *disp;
384         dns_dispatchmgr_t *mgr;
385         isc_boolean_t killmgr;
386
387         INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
388
389         UNUSED(task);
390
391         disp = event->ev_arg;
392         mgr = disp->mgr;
393
394         LOCK(&mgr->lock);
395         ISC_LIST_UNLINK(mgr->list, disp, link);
396
397         dispatch_log(disp, LVL(90),
398                      "shutting down; detaching from sock %p, task %p",
399                      disp->socket, disp->task);
400
401         isc_socket_detach(&disp->socket);
402         isc_task_detach(&disp->task);
403         isc_event_free(&event);
404
405         dispatch_free(&disp);
406
407         killmgr = destroy_mgr_ok(mgr);
408         UNLOCK(&mgr->lock);
409         if (killmgr)
410                 destroy_mgr(&mgr);
411 }
412
413
414 /*
415  * Find an entry for query ID 'id' and socket address 'dest' in 'qid'.
416  * Return NULL if no such entry exists.
417  */
418 static dns_dispentry_t *
419 bucket_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
420               unsigned int bucket)
421 {
422         dns_dispentry_t *res;
423
424         REQUIRE(bucket < qid->qid_nbuckets);
425
426         res = ISC_LIST_HEAD(qid->qid_table[bucket]);
427
428         while (res != NULL) {
429                 if ((res->id == id) && isc_sockaddr_equal(dest, &res->host))
430                         return (res);
431                 res = ISC_LIST_NEXT(res, link);
432         }
433
434         return (NULL);
435 }
436
437 static void
438 free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
439         INSIST(buf != NULL && len != 0);
440
441
442         switch (disp->socktype) {
443         case isc_sockettype_tcp:
444                 INSIST(disp->tcpbuffers > 0);
445                 disp->tcpbuffers--;
446                 isc_mem_put(disp->mgr->mctx, buf, len);
447                 break;
448         case isc_sockettype_udp:
449                 LOCK(&disp->mgr->buffer_lock);
450                 INSIST(disp->mgr->buffers > 0);
451                 INSIST(len == disp->mgr->buffersize);
452                 disp->mgr->buffers--;
453                 isc_mempool_put(disp->mgr->bpool, buf);
454                 UNLOCK(&disp->mgr->buffer_lock);
455                 break;
456         default:
457                 INSIST(0);
458                 break;
459         }
460 }
461
462 static void *
463 allocate_udp_buffer(dns_dispatch_t *disp) {
464         void *temp;
465
466         LOCK(&disp->mgr->buffer_lock);
467         temp = isc_mempool_get(disp->mgr->bpool);
468
469         if (temp != NULL)
470                 disp->mgr->buffers++;
471         UNLOCK(&disp->mgr->buffer_lock);
472
473         return (temp);
474 }
475
476 static inline void
477 free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
478         if (disp->failsafe_ev == ev) {
479                 INSIST(disp->shutdown_out == 1);
480                 disp->shutdown_out = 0;
481
482                 return;
483         }
484
485         isc_mempool_put(disp->mgr->epool, ev);
486 }
487
488 static inline dns_dispatchevent_t *
489 allocate_event(dns_dispatch_t *disp) {
490         dns_dispatchevent_t *ev;
491
492         ev = isc_mempool_get(disp->mgr->epool);
493         if (ev == NULL)
494                 return (NULL);
495         ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0,
496                        NULL, NULL, NULL, NULL, NULL);
497
498         return (ev);
499 }
500
501 /*
502  * General flow:
503  *
504  * If I/O result == CANCELED or error, free the buffer.
505  *
506  * If query, free the buffer, restart.
507  *
508  * If response:
509  *      Allocate event, fill in details.
510  *              If cannot allocate, free buffer, restart.
511  *      find target.  If not found, free buffer, restart.
512  *      if event queue is not empty, queue.  else, send.
513  *      restart.
514  */
515 static void
516 udp_recv(isc_task_t *task, isc_event_t *ev_in) {
517         isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
518         dns_dispatch_t *disp = ev_in->ev_arg;
519         dns_messageid_t id;
520         isc_result_t dres;
521         isc_buffer_t source;
522         unsigned int flags;
523         dns_dispentry_t *resp;
524         dns_dispatchevent_t *rev;
525         unsigned int bucket;
526         isc_boolean_t killit;
527         isc_boolean_t queue_response;
528         dns_dispatchmgr_t *mgr;
529         dns_qid_t *qid;
530         isc_netaddr_t netaddr;
531         int match;
532
533         UNUSED(task);
534
535         LOCK(&disp->lock);
536
537         mgr = disp->mgr;
538         qid = mgr->qid;
539
540         dispatch_log(disp, LVL(90),
541                      "got packet: requests %d, buffers %d, recvs %d",
542                      disp->requests, disp->mgr->buffers, disp->recv_pending);
543
544         if (ev->ev_type == ISC_SOCKEVENT_RECVDONE) {
545                 /*
546                  * Unless the receive event was imported from a listening
547                  * interface, in which case the event type is
548                  * DNS_EVENT_IMPORTRECVDONE, receive operation must be pending.
549                  */
550                 INSIST(disp->recv_pending != 0);
551                 disp->recv_pending = 0;
552         }
553
554         if (disp->shutting_down) {
555                 /*
556                  * This dispatcher is shutting down.
557                  */
558                 free_buffer(disp, ev->region.base, ev->region.length);
559
560                 isc_event_free(&ev_in);
561                 ev = NULL;
562
563                 killit = destroy_disp_ok(disp);
564                 UNLOCK(&disp->lock);
565                 if (killit)
566                         isc_task_send(disp->task, &disp->ctlevent);
567
568                 return;
569         }
570
571         if (ev->result != ISC_R_SUCCESS) {
572                 free_buffer(disp, ev->region.base, ev->region.length);
573
574                 if (ev->result != ISC_R_CANCELED)
575                         dispatch_log(disp, ISC_LOG_ERROR,
576                                      "odd socket result in udp_recv(): %s",
577                                      isc_result_totext(ev->result));
578
579                 UNLOCK(&disp->lock);
580                 isc_event_free(&ev_in);
581                 return;
582         }
583
584         /*
585          * If this is from a blackholed address, drop it.
586          */
587         isc_netaddr_fromsockaddr(&netaddr, &ev->address);
588         if (disp->mgr->blackhole != NULL &&
589             dns_acl_match(&netaddr, NULL, disp->mgr->blackhole,
590                           NULL, &match, NULL) == ISC_R_SUCCESS &&
591             match > 0)
592         {
593                 if (isc_log_wouldlog(dns_lctx, LVL(10))) {
594                         char netaddrstr[ISC_NETADDR_FORMATSIZE];
595                         isc_netaddr_format(&netaddr, netaddrstr,
596                                            sizeof(netaddrstr));
597                         dispatch_log(disp, LVL(10),
598                                      "blackholed packet from %s",
599                                      netaddrstr);
600                 }
601                 free_buffer(disp, ev->region.base, ev->region.length);
602                 goto restart;
603         }
604
605         /*
606          * Peek into the buffer to see what we can see.
607          */
608         isc_buffer_init(&source, ev->region.base, ev->region.length);
609         isc_buffer_add(&source, ev->n);
610         dres = dns_message_peekheader(&source, &id, &flags);
611         if (dres != ISC_R_SUCCESS) {
612                 free_buffer(disp, ev->region.base, ev->region.length);
613                 dispatch_log(disp, LVL(10), "got garbage packet");
614                 goto restart;
615         }
616
617         dispatch_log(disp, LVL(92),
618                      "got valid DNS message header, /QR %c, id %u",
619                      ((flags & DNS_MESSAGEFLAG_QR) ? '1' : '0'), id);
620
621         /*
622          * Look at flags.  If query, drop it. If response,
623          * look to see where it goes.
624          */
625         queue_response = ISC_FALSE;
626         if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
627                 /* query */
628                 free_buffer(disp, ev->region.base, ev->region.length);
629                 goto restart;
630         }
631
632         /* response */
633         bucket = dns_hash(qid, &ev->address, id);
634         LOCK(&qid->lock);
635         resp = bucket_search(qid, &ev->address, id, bucket);
636         dispatch_log(disp, LVL(90),
637                      "search for response in bucket %d: %s",
638                      bucket, (resp == NULL ? "not found" : "found"));
639
640         if (resp == NULL) {
641                 free_buffer(disp, ev->region.base, ev->region.length);
642                 goto unlock;
643         } 
644
645         /*
646          * Now that we have the original dispatch the query was sent
647          * from check that the address and port the response was
648          * sent to make sense.
649          */
650         if (disp != resp->disp) {
651                 isc_sockaddr_t a1;
652                 isc_sockaddr_t a2;
653                 
654                 /*
655                  * Check that the socket types and ports match.
656                  */
657                 if (disp->socktype != resp->disp->socktype ||
658                     isc_sockaddr_getport(&disp->local) !=
659                     isc_sockaddr_getport(&resp->disp->local)) {
660                         free_buffer(disp, ev->region.base, ev->region.length);
661                         goto unlock;
662                 }
663
664                 /*
665                  * If both dispatches are bound to an address then fail as
666                  * the addresses can't be equal (enforced by the IP stack).  
667                  *
668                  * Note under Linux a packet can be sent out via IPv4 socket
669                  * and the response be received via a IPv6 socket.
670                  * 
671                  * Requests sent out via IPv6 should always come back in
672                  * via IPv6.
673                  */
674                 if (isc_sockaddr_pf(&resp->disp->local) == PF_INET6 &&
675                     isc_sockaddr_pf(&disp->local) != PF_INET6) {
676                         free_buffer(disp, ev->region.base, ev->region.length);
677                         goto unlock;
678                 }
679                 isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local));
680                 isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local));
681                 if (!isc_sockaddr_eqaddr(&a1, &resp->disp->local) &&
682                     !isc_sockaddr_eqaddr(&a2, &disp->local)) {
683                         free_buffer(disp, ev->region.base, ev->region.length);
684                         goto unlock;
685                 }
686         }
687
688         queue_response = resp->item_out;
689         rev = allocate_event(resp->disp);
690         if (rev == NULL) {
691                 free_buffer(disp, ev->region.base, ev->region.length);
692                 goto unlock;
693         }
694
695         /*
696          * At this point, rev contains the event we want to fill in, and
697          * resp contains the information on the place to send it to.
698          * Send the event off.
699          */
700         isc_buffer_init(&rev->buffer, ev->region.base, ev->region.length);
701         isc_buffer_add(&rev->buffer, ev->n);
702         rev->result = ISC_R_SUCCESS;
703         rev->id = id;
704         rev->addr = ev->address;
705         rev->pktinfo = ev->pktinfo;
706         rev->attributes = ev->attributes;
707         if (queue_response) {
708                 ISC_LIST_APPEND(resp->items, rev, ev_link);
709         } else {
710                 ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL,
711                                DNS_EVENT_DISPATCH,
712                                resp->action, resp->arg, resp, NULL, NULL);
713                 request_log(disp, resp, LVL(90),
714                             "[a] Sent event %p buffer %p len %d to task %p",
715                             rev, rev->buffer.base, rev->buffer.length,
716                             resp->task);
717                 resp->item_out = ISC_TRUE;
718                 isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
719         }
720  unlock:
721         UNLOCK(&qid->lock);
722
723         /*
724          * Restart recv() to get the next packet.
725          */
726  restart:
727         startrecv(disp);
728
729         UNLOCK(&disp->lock);
730
731         isc_event_free(&ev_in);
732 }
733
734 /*
735  * General flow:
736  *
737  * If I/O result == CANCELED, EOF, or error, notify everyone as the
738  * various queues drain.
739  *
740  * If query, restart.
741  *
742  * If response:
743  *      Allocate event, fill in details.
744  *              If cannot allocate, restart.
745  *      find target.  If not found, restart.
746  *      if event queue is not empty, queue.  else, send.
747  *      restart.
748  */
749 static void
750 tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
751         dns_dispatch_t *disp = ev_in->ev_arg;
752         dns_tcpmsg_t *tcpmsg = &disp->tcpmsg;
753         dns_messageid_t id;
754         isc_result_t dres;
755         unsigned int flags;
756         dns_dispentry_t *resp;
757         dns_dispatchevent_t *rev;
758         unsigned int bucket;
759         isc_boolean_t killit;
760         isc_boolean_t queue_response;
761         dns_qid_t *qid;
762         int level;
763         char buf[ISC_SOCKADDR_FORMATSIZE];
764
765         UNUSED(task);
766
767         REQUIRE(VALID_DISPATCH(disp));
768
769         qid = disp->qid;
770
771         dispatch_log(disp, LVL(90),
772                      "got TCP packet: requests %d, buffers %d, recvs %d",
773                      disp->requests, disp->tcpbuffers, disp->recv_pending);
774
775         LOCK(&disp->lock);
776
777         INSIST(disp->recv_pending != 0);
778         disp->recv_pending = 0;
779
780         if (disp->refcount == 0) {
781                 /*
782                  * This dispatcher is shutting down.  Force cancelation.
783                  */
784                 tcpmsg->result = ISC_R_CANCELED;
785         }
786
787         if (tcpmsg->result != ISC_R_SUCCESS) {
788                 switch (tcpmsg->result) {
789                 case ISC_R_CANCELED:
790                         break;
791                         
792                 case ISC_R_EOF:
793                         dispatch_log(disp, LVL(90), "shutting down on EOF");
794                         do_cancel(disp);
795                         break;
796
797                 case ISC_R_CONNECTIONRESET:
798                         level = ISC_LOG_INFO;
799                         goto logit;
800
801                 default:
802                         level = ISC_LOG_ERROR;
803                 logit:
804                         isc_sockaddr_format(&tcpmsg->address, buf, sizeof(buf));
805                         dispatch_log(disp, level, "shutting down due to TCP "
806                                      "receive error: %s: %s", buf,
807                                      isc_result_totext(tcpmsg->result));
808                         do_cancel(disp);
809                         break;
810                 }
811
812                 /*
813                  * The event is statically allocated in the tcpmsg
814                  * structure, and destroy_disp() frees the tcpmsg, so we must
815                  * free the event *before* calling destroy_disp().
816                  */
817                 isc_event_free(&ev_in);
818
819                 disp->shutting_down = 1;
820                 disp->shutdown_why = tcpmsg->result;
821
822                 /*
823                  * If the recv() was canceled pass the word on.
824                  */
825                 killit = destroy_disp_ok(disp);
826                 UNLOCK(&disp->lock);
827                 if (killit)
828                         isc_task_send(disp->task, &disp->ctlevent);
829                 return;
830         }
831
832         dispatch_log(disp, LVL(90), "result %d, length == %d, addr = %p",
833                      tcpmsg->result,
834                      tcpmsg->buffer.length, tcpmsg->buffer.base);
835
836         /*
837          * Peek into the buffer to see what we can see.
838          */
839         dres = dns_message_peekheader(&tcpmsg->buffer, &id, &flags);
840         if (dres != ISC_R_SUCCESS) {
841                 dispatch_log(disp, LVL(10), "got garbage packet");
842                 goto restart;
843         }
844
845         dispatch_log(disp, LVL(92),
846                      "got valid DNS message header, /QR %c, id %u",
847                      ((flags & DNS_MESSAGEFLAG_QR) ? '1' : '0'), id);
848
849         /*
850          * Allocate an event to send to the query or response client, and
851          * allocate a new buffer for our use.
852          */
853
854         /*
855          * Look at flags.  If query, drop it. If response,
856          * look to see where it goes.
857          */
858         queue_response = ISC_FALSE;
859         if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
860                 /*
861                  * Query.
862                  */
863                 goto restart;
864         }
865
866         /*
867          * Response.
868          */
869         bucket = dns_hash(qid, &tcpmsg->address, id);
870         LOCK(&qid->lock);
871         resp = bucket_search(qid, &tcpmsg->address, id, bucket);
872         dispatch_log(disp, LVL(90),
873                      "search for response in bucket %d: %s",
874                      bucket, (resp == NULL ? "not found" : "found"));
875
876         if (resp == NULL)
877                 goto unlock;
878         queue_response = resp->item_out;
879         rev = allocate_event(disp);
880         if (rev == NULL)
881                 goto unlock;
882
883         /*
884          * At this point, rev contains the event we want to fill in, and
885          * resp contains the information on the place to send it to.
886          * Send the event off.
887          */
888         dns_tcpmsg_keepbuffer(tcpmsg, &rev->buffer);
889         disp->tcpbuffers++;
890         rev->result = ISC_R_SUCCESS;
891         rev->id = id;
892         rev->addr = tcpmsg->address;
893         if (queue_response) {
894                 ISC_LIST_APPEND(resp->items, rev, ev_link);
895         } else {
896                 ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
897                                resp->action, resp->arg, resp, NULL, NULL);
898                 request_log(disp, resp, LVL(90),
899                             "[b] Sent event %p buffer %p len %d to task %p",
900                             rev, rev->buffer.base, rev->buffer.length,
901                             resp->task);
902                 resp->item_out = ISC_TRUE;
903                 isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
904         }
905  unlock:
906         UNLOCK(&qid->lock);
907
908         /*
909          * Restart recv() to get the next packet.
910          */
911  restart:
912         startrecv(disp);
913
914         UNLOCK(&disp->lock);
915
916         isc_event_free(&ev_in);
917 }
918
919 /*
920  * disp must be locked.
921  */
922 static void
923 startrecv(dns_dispatch_t *disp) {
924         isc_result_t res;
925         isc_region_t region;
926
927         if (disp->shutting_down == 1)
928                 return;
929
930         if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
931                 return;
932
933         if (disp->recv_pending != 0)
934                 return;
935
936         if (disp->mgr->buffers >= disp->mgr->maxbuffers)
937                 return;
938
939         switch (disp->socktype) {
940                 /*
941                  * UDP reads are always maximal.
942                  */
943         case isc_sockettype_udp:
944                 region.length = disp->mgr->buffersize;
945                 region.base = allocate_udp_buffer(disp);
946                 if (region.base == NULL)
947                         return;
948                 res = isc_socket_recv(disp->socket, &region, 1,
949                                       disp->task, udp_recv, disp);
950                 if (res != ISC_R_SUCCESS) {
951                         free_buffer(disp, region.base, region.length);
952                         disp->shutdown_why = res;
953                         disp->shutting_down = 1;
954                         do_cancel(disp);
955                         return;
956                 }
957                 INSIST(disp->recv_pending == 0);
958                 disp->recv_pending = 1;
959                 break;
960
961         case isc_sockettype_tcp:
962                 res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task,
963                                              tcp_recv, disp);
964                 if (res != ISC_R_SUCCESS) {
965                         disp->shutdown_why = res;
966                         disp->shutting_down = 1;
967                         do_cancel(disp);
968                         return;
969                 }
970                 INSIST(disp->recv_pending == 0);
971                 disp->recv_pending = 1;
972                 break;
973         }
974 }
975
976 /*
977  * Mgr must be locked when calling this function.
978  */
979 static isc_boolean_t
980 destroy_mgr_ok(dns_dispatchmgr_t *mgr) {
981         mgr_log(mgr, LVL(90),
982                 "destroy_mgr_ok: shuttingdown=%d, listnonempty=%d, "
983                 "epool=%d, rpool=%d, dpool=%d",
984                 MGR_IS_SHUTTINGDOWN(mgr), !ISC_LIST_EMPTY(mgr->list),
985                 isc_mempool_getallocated(mgr->epool),
986                 isc_mempool_getallocated(mgr->rpool),
987                 isc_mempool_getallocated(mgr->dpool));
988         if (!MGR_IS_SHUTTINGDOWN(mgr))
989                 return (ISC_FALSE);
990         if (!ISC_LIST_EMPTY(mgr->list))
991                 return (ISC_FALSE);
992         if (isc_mempool_getallocated(mgr->epool) != 0)
993                 return (ISC_FALSE);
994         if (isc_mempool_getallocated(mgr->rpool) != 0)
995                 return (ISC_FALSE);
996         if (isc_mempool_getallocated(mgr->dpool) != 0)
997                 return (ISC_FALSE);
998
999         return (ISC_TRUE);
1000 }
1001
1002 /*
1003  * Mgr must be unlocked when calling this function.
1004  */
1005 static void
1006 destroy_mgr(dns_dispatchmgr_t **mgrp) {
1007         isc_mem_t *mctx;
1008         dns_dispatchmgr_t *mgr;
1009
1010         mgr = *mgrp;
1011         *mgrp = NULL;
1012
1013         mctx = mgr->mctx;
1014
1015         mgr->magic = 0;
1016         mgr->mctx = NULL;
1017         DESTROYLOCK(&mgr->lock);
1018         mgr->state = 0;
1019
1020         isc_mempool_destroy(&mgr->epool);
1021         isc_mempool_destroy(&mgr->rpool);
1022         isc_mempool_destroy(&mgr->dpool);
1023         isc_mempool_destroy(&mgr->bpool);
1024
1025         DESTROYLOCK(&mgr->pool_lock);
1026
1027         if (mgr->entropy != NULL)
1028                 isc_entropy_detach(&mgr->entropy);
1029         if (mgr->qid != NULL)
1030                 qid_destroy(mctx, &mgr->qid);
1031
1032         DESTROYLOCK(&mgr->buffer_lock);
1033
1034         if (mgr->blackhole != NULL)
1035                 dns_acl_detach(&mgr->blackhole);
1036
1037         if (mgr->portlist != NULL)
1038                 dns_portlist_detach(&mgr->portlist);
1039
1040         isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
1041         isc_mem_detach(&mctx);
1042 }
1043
1044 static isc_result_t
1045 create_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
1046               isc_socket_t **sockp)
1047 {
1048         isc_socket_t *sock;
1049         isc_result_t result;
1050
1051         sock = NULL;
1052         result = isc_socket_create(mgr, isc_sockaddr_pf(local),
1053                                    isc_sockettype_udp, &sock);
1054         if (result != ISC_R_SUCCESS)
1055                 return (result);
1056
1057 #ifndef ISC_ALLOW_MAPPED
1058         isc_socket_ipv6only(sock, ISC_TRUE);
1059 #endif
1060         result = isc_socket_bind(sock, local);
1061         if (result != ISC_R_SUCCESS) {
1062                 isc_socket_detach(&sock);
1063                 return (result);
1064         }
1065
1066         *sockp = sock;
1067         return (ISC_R_SUCCESS);
1068 }
1069
1070 /*
1071  * Publics.
1072  */
1073
1074 isc_result_t
1075 dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
1076                        dns_dispatchmgr_t **mgrp)
1077 {
1078         dns_dispatchmgr_t *mgr;
1079         isc_result_t result;
1080
1081         REQUIRE(mctx != NULL);
1082         REQUIRE(mgrp != NULL && *mgrp == NULL);
1083
1084         mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
1085         if (mgr == NULL)
1086                 return (ISC_R_NOMEMORY);
1087
1088         mgr->mctx = NULL;
1089         isc_mem_attach(mctx, &mgr->mctx);
1090
1091         mgr->blackhole = NULL;
1092         mgr->portlist = NULL;
1093
1094         result = isc_mutex_init(&mgr->lock);
1095         if (result != ISC_R_SUCCESS)
1096                 goto deallocate;
1097
1098         result = isc_mutex_init(&mgr->buffer_lock);
1099         if (result != ISC_R_SUCCESS)
1100                 goto kill_lock;
1101
1102         result = isc_mutex_init(&mgr->pool_lock);
1103         if (result != ISC_R_SUCCESS)
1104                 goto kill_buffer_lock;
1105
1106         mgr->epool = NULL;
1107         if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatchevent_t),
1108                                &mgr->epool) != ISC_R_SUCCESS) {
1109                 result = ISC_R_NOMEMORY;
1110                 goto kill_pool_lock;
1111         }
1112
1113         mgr->rpool = NULL;
1114         if (isc_mempool_create(mgr->mctx, sizeof(dns_dispentry_t),
1115                                &mgr->rpool) != ISC_R_SUCCESS) {
1116                 result = ISC_R_NOMEMORY;
1117                 goto kill_epool;
1118         }
1119
1120         mgr->dpool = NULL;
1121         if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatch_t),
1122                                &mgr->dpool) != ISC_R_SUCCESS) {
1123                 result = ISC_R_NOMEMORY;
1124                 goto kill_rpool;
1125         }
1126
1127         isc_mempool_setname(mgr->epool, "dispmgr_epool");
1128         isc_mempool_setfreemax(mgr->epool, 1024);
1129         isc_mempool_associatelock(mgr->epool, &mgr->pool_lock);
1130
1131         isc_mempool_setname(mgr->rpool, "dispmgr_rpool");
1132         isc_mempool_setfreemax(mgr->rpool, 1024);
1133         isc_mempool_associatelock(mgr->rpool, &mgr->pool_lock);
1134
1135         isc_mempool_setname(mgr->dpool, "dispmgr_dpool");
1136         isc_mempool_setfreemax(mgr->dpool, 1024);
1137         isc_mempool_associatelock(mgr->dpool, &mgr->pool_lock);
1138
1139         mgr->buffers = 0;
1140         mgr->buffersize = 0;
1141         mgr->maxbuffers = 0;
1142         mgr->bpool = NULL;
1143         mgr->entropy = NULL;
1144         mgr->qid = NULL;
1145         mgr->state = 0;
1146         ISC_LIST_INIT(mgr->list);
1147         mgr->magic = DNS_DISPATCHMGR_MAGIC;
1148
1149         if (entropy != NULL)
1150                 isc_entropy_attach(entropy, &mgr->entropy);
1151
1152         *mgrp = mgr;
1153         return (ISC_R_SUCCESS);
1154
1155  kill_rpool:
1156         isc_mempool_destroy(&mgr->rpool);
1157  kill_epool:
1158         isc_mempool_destroy(&mgr->epool);
1159  kill_pool_lock:
1160         DESTROYLOCK(&mgr->pool_lock);
1161  kill_buffer_lock:
1162         DESTROYLOCK(&mgr->buffer_lock);
1163  kill_lock:
1164         DESTROYLOCK(&mgr->lock);
1165  deallocate:
1166         isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
1167         isc_mem_detach(&mctx);
1168
1169         return (result);
1170 }
1171
1172 void
1173 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) {
1174         REQUIRE(VALID_DISPATCHMGR(mgr));
1175         if (mgr->blackhole != NULL)
1176                 dns_acl_detach(&mgr->blackhole);
1177         dns_acl_attach(blackhole, &mgr->blackhole);
1178 }
1179
1180 dns_acl_t *
1181 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr) {
1182         REQUIRE(VALID_DISPATCHMGR(mgr));
1183         return (mgr->blackhole);
1184 }
1185
1186 void
1187 dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
1188                                  dns_portlist_t *portlist)
1189 {
1190         REQUIRE(VALID_DISPATCHMGR(mgr));
1191         if (mgr->portlist != NULL)
1192                 dns_portlist_detach(&mgr->portlist);
1193         if (portlist != NULL)
1194                 dns_portlist_attach(portlist, &mgr->portlist);
1195 }
1196
1197 dns_portlist_t *
1198 dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr) {
1199         REQUIRE(VALID_DISPATCHMGR(mgr));
1200         return (mgr->portlist);
1201 }
1202
1203 static isc_result_t
1204 dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
1205                         unsigned int buffersize, unsigned int maxbuffers,
1206                         unsigned int buckets, unsigned int increment)
1207 {
1208         isc_result_t result;
1209
1210         REQUIRE(VALID_DISPATCHMGR(mgr));
1211         REQUIRE(buffersize >= 512 && buffersize < (64 * 1024));
1212         REQUIRE(maxbuffers > 0);
1213         REQUIRE(buckets < 2097169);  /* next prime > 65536 * 32 */
1214         REQUIRE(increment > buckets);
1215
1216         /*
1217          * Keep some number of items around.  This should be a config
1218          * option.  For now, keep 8, but later keep at least two even
1219          * if the caller wants less.  This allows us to ensure certain
1220          * things, like an event can be "freed" and the next allocation
1221          * will always succeed.
1222          *
1223          * Note that if limits are placed on anything here, we use one
1224          * event internally, so the actual limit should be "wanted + 1."
1225          *
1226          * XXXMLG
1227          */
1228
1229         if (maxbuffers < 8)
1230                 maxbuffers = 8;
1231
1232         LOCK(&mgr->buffer_lock);
1233         if (mgr->bpool != NULL) {
1234                 isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
1235                 mgr->maxbuffers = maxbuffers;
1236                 UNLOCK(&mgr->buffer_lock);
1237                 return (ISC_R_SUCCESS);
1238         }
1239
1240         if (isc_mempool_create(mgr->mctx, buffersize,
1241                                &mgr->bpool) != ISC_R_SUCCESS) {
1242                 return (ISC_R_NOMEMORY);
1243         }
1244
1245         isc_mempool_setname(mgr->bpool, "dispmgr_bpool");
1246         isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
1247         isc_mempool_associatelock(mgr->bpool, &mgr->pool_lock);
1248
1249         result = qid_allocate(mgr, buckets, increment, &mgr->qid);
1250         if (result != ISC_R_SUCCESS)
1251                 goto cleanup;
1252
1253         mgr->buffersize = buffersize;
1254         mgr->maxbuffers = maxbuffers;
1255         UNLOCK(&mgr->buffer_lock);
1256         return (ISC_R_SUCCESS);
1257
1258  cleanup:
1259         isc_mempool_destroy(&mgr->bpool);
1260         UNLOCK(&mgr->buffer_lock);
1261         return (ISC_R_NOMEMORY);
1262 }
1263
1264 void
1265 dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
1266         dns_dispatchmgr_t *mgr;
1267         isc_boolean_t killit;
1268
1269         REQUIRE(mgrp != NULL);
1270         REQUIRE(VALID_DISPATCHMGR(*mgrp));
1271
1272         mgr = *mgrp;
1273         *mgrp = NULL;
1274
1275         LOCK(&mgr->lock);
1276         mgr->state |= MGR_SHUTTINGDOWN;
1277
1278         killit = destroy_mgr_ok(mgr);
1279         UNLOCK(&mgr->lock);
1280
1281         mgr_log(mgr, LVL(90), "destroy: killit=%d", killit);
1282
1283         if (killit)
1284                 destroy_mgr(&mgr);
1285 }
1286
1287 static isc_boolean_t
1288 blacklisted(dns_dispatchmgr_t *mgr, isc_socket_t *sock) {
1289         isc_sockaddr_t sockaddr;
1290         isc_result_t result;
1291
1292         if (mgr->portlist == NULL)
1293                 return (ISC_FALSE);
1294
1295         result = isc_socket_getsockname(sock, &sockaddr);
1296         if (result != ISC_R_SUCCESS)
1297                 return (ISC_FALSE);
1298
1299         if (mgr->portlist != NULL &&
1300             dns_portlist_match(mgr->portlist, isc_sockaddr_pf(&sockaddr),
1301                                isc_sockaddr_getport(&sockaddr)))
1302                 return (ISC_TRUE);
1303         return (ISC_FALSE);
1304 }
1305
1306 #define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
1307
1308 static isc_boolean_t
1309 local_addr_match(dns_dispatch_t *disp, isc_sockaddr_t *addr) {
1310         isc_sockaddr_t sockaddr;
1311         isc_result_t result;
1312
1313         if (addr == NULL)
1314                 return (ISC_TRUE);
1315
1316         /*
1317          * Don't match wildcard ports against newly blacklisted ports.
1318          */
1319         if (disp->mgr->portlist != NULL &&
1320             isc_sockaddr_getport(addr) == 0 &&
1321             isc_sockaddr_getport(&disp->local) == 0 &&
1322             blacklisted(disp->mgr, disp->socket))
1323                 return (ISC_FALSE);
1324
1325         /*
1326          * Check if we match the binding <address,port>.
1327          * Wildcard ports match/fail here.
1328          */
1329         if (isc_sockaddr_equal(&disp->local, addr))
1330                 return (ISC_TRUE);
1331         if (isc_sockaddr_getport(addr) == 0)
1332                 return (ISC_FALSE);
1333
1334         /*
1335          * Check if we match a bound wildcard port <address,port>.
1336          */
1337         if (!isc_sockaddr_eqaddr(&disp->local, addr))
1338                 return (ISC_FALSE);
1339         result = isc_socket_getsockname(disp->socket, &sockaddr);
1340         if (result != ISC_R_SUCCESS)
1341                 return (ISC_FALSE);
1342
1343         return (isc_sockaddr_equal(&sockaddr, addr));
1344 }
1345
1346 /*
1347  * Requires mgr be locked.
1348  *
1349  * No dispatcher can be locked by this thread when calling this function.
1350  *
1351  *
1352  * NOTE:
1353  *      If a matching dispatcher is found, it is locked after this function
1354  *      returns, and must be unlocked by the caller.
1355  */
1356 static isc_result_t
1357 dispatch_find(dns_dispatchmgr_t *mgr, isc_sockaddr_t *local,
1358               unsigned int attributes, unsigned int mask,
1359               dns_dispatch_t **dispp)
1360 {
1361         dns_dispatch_t *disp;
1362         isc_result_t result;
1363
1364         /*
1365          * Make certain that we will not match a private dispatch.
1366          */
1367         attributes &= ~DNS_DISPATCHATTR_PRIVATE;
1368         mask |= DNS_DISPATCHATTR_PRIVATE;
1369
1370         disp = ISC_LIST_HEAD(mgr->list);
1371         while (disp != NULL) {
1372                 LOCK(&disp->lock);
1373                 if ((disp->shutting_down == 0)
1374                     && ATTRMATCH(disp->attributes, attributes, mask)
1375                     && local_addr_match(disp, local))
1376                         break;
1377                 UNLOCK(&disp->lock);
1378                 disp = ISC_LIST_NEXT(disp, link);
1379         }
1380
1381         if (disp == NULL) {
1382                 result = ISC_R_NOTFOUND;
1383                 goto out;
1384         }
1385
1386         *dispp = disp;
1387         result = ISC_R_SUCCESS;
1388  out:
1389
1390         return (result);
1391 }
1392
1393 static isc_result_t
1394 qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
1395              unsigned int increment, dns_qid_t **qidp)
1396 {
1397         dns_qid_t *qid;
1398         unsigned int i;
1399
1400         REQUIRE(VALID_DISPATCHMGR(mgr));
1401         REQUIRE(buckets < 2097169);  /* next prime > 65536 * 32 */
1402         REQUIRE(increment > buckets);
1403         REQUIRE(qidp != NULL && *qidp == NULL);
1404
1405         qid = isc_mem_get(mgr->mctx, sizeof(*qid));
1406         if (qid == NULL)
1407                 return (ISC_R_NOMEMORY);
1408
1409         qid->qid_table = isc_mem_get(mgr->mctx,
1410                                      buckets * sizeof(dns_displist_t));
1411         if (qid->qid_table == NULL) {
1412                 isc_mem_put(mgr->mctx, qid, sizeof(*qid));
1413                 return (ISC_R_NOMEMORY);
1414         }
1415
1416         if (isc_mutex_init(&qid->lock) != ISC_R_SUCCESS) {
1417                 UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init failed");
1418                 isc_mem_put(mgr->mctx, qid->qid_table,
1419                             buckets * sizeof(dns_displist_t));
1420                 isc_mem_put(mgr->mctx, qid, sizeof(*qid));
1421                 return (ISC_R_UNEXPECTED);
1422         }
1423
1424         for (i = 0; i < buckets; i++)
1425                 ISC_LIST_INIT(qid->qid_table[i]);
1426
1427         qid->qid_nbuckets = buckets;
1428         qid->qid_increment = increment;
1429         qid->magic = QID_MAGIC;
1430
1431         /*
1432          * Initialize to a 32-bit LFSR.  Both of these are from Applied
1433          * Cryptography.
1434          *
1435          * lfsr1:
1436          *      x^32 + x^7 + x^5 + x^3 + x^2 + x + 1
1437          *
1438          * lfsr2:
1439          *      x^32 + x^7 + x^6 + x^2 + 1
1440          */
1441         isc_lfsr_init(&qid->qid_lfsr1, 0, 32, 0x80000057U,
1442                       0, reseed_lfsr, mgr);
1443         isc_lfsr_init(&qid->qid_lfsr2, 0, 32, 0x80000062U,
1444                       0, reseed_lfsr, mgr);
1445         *qidp = qid;
1446         return (ISC_R_SUCCESS);
1447 }
1448
1449 static void
1450 qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
1451         dns_qid_t *qid;
1452
1453         REQUIRE(qidp != NULL);
1454         qid = *qidp;
1455
1456         REQUIRE(VALID_QID(qid));
1457
1458         *qidp = NULL;
1459         qid->magic = 0;
1460         isc_mem_put(mctx, qid->qid_table,
1461                     qid->qid_nbuckets * sizeof(dns_displist_t));
1462         DESTROYLOCK(&qid->lock);
1463         isc_mem_put(mctx, qid, sizeof(*qid));
1464 }
1465
1466 /*
1467  * Allocate and set important limits.
1468  */
1469 static isc_result_t
1470 dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
1471                   dns_dispatch_t **dispp)
1472 {
1473         dns_dispatch_t *disp;
1474         isc_result_t res;
1475
1476         REQUIRE(VALID_DISPATCHMGR(mgr));
1477         REQUIRE(dispp != NULL && *dispp == NULL);
1478
1479         /*
1480          * Set up the dispatcher, mostly.  Don't bother setting some of
1481          * the options that are controlled by tcp vs. udp, etc.
1482          */
1483
1484         disp = isc_mempool_get(mgr->dpool);
1485         if (disp == NULL)
1486                 return (ISC_R_NOMEMORY);
1487
1488         disp->magic = 0;
1489         disp->mgr = mgr;
1490         disp->maxrequests = maxrequests;
1491         disp->attributes = 0;
1492         ISC_LINK_INIT(disp, link);
1493         disp->refcount = 1;
1494         disp->recv_pending = 0;
1495         memset(&disp->local, 0, sizeof(disp->local));
1496         disp->shutting_down = 0;
1497         disp->shutdown_out = 0;
1498         disp->connected = 0;
1499         disp->tcpmsg_valid = 0;
1500         disp->shutdown_why = ISC_R_UNEXPECTED;
1501         disp->requests = 0;
1502         disp->tcpbuffers = 0;
1503         disp->qid = NULL;
1504
1505         if (isc_mutex_init(&disp->lock) != ISC_R_SUCCESS) {
1506                 res = ISC_R_UNEXPECTED;
1507                 UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init failed");
1508                 goto deallocate;
1509         }
1510
1511         disp->failsafe_ev = allocate_event(disp);
1512         if (disp->failsafe_ev == NULL) {
1513                 res = ISC_R_NOMEMORY;
1514                 goto kill_lock;
1515         }
1516
1517         disp->magic = DISPATCH_MAGIC;
1518
1519         *dispp = disp;
1520         return (ISC_R_SUCCESS);
1521
1522         /*
1523          * error returns
1524          */
1525  kill_lock:
1526         DESTROYLOCK(&disp->lock);
1527  deallocate:
1528         isc_mempool_put(mgr->dpool, disp);
1529
1530         return (res);
1531 }
1532
1533
1534 /*
1535  * MUST be unlocked, and not used by anthing.
1536  */
1537 static void
1538 dispatch_free(dns_dispatch_t **dispp)
1539 {
1540         dns_dispatch_t *disp;
1541         dns_dispatchmgr_t *mgr;
1542
1543         REQUIRE(VALID_DISPATCH(*dispp));
1544         disp = *dispp;
1545         *dispp = NULL;
1546
1547         mgr = disp->mgr;
1548         REQUIRE(VALID_DISPATCHMGR(mgr));
1549
1550         if (disp->tcpmsg_valid) {
1551                 dns_tcpmsg_invalidate(&disp->tcpmsg);
1552                 disp->tcpmsg_valid = 0;
1553         }
1554
1555         INSIST(disp->tcpbuffers == 0);
1556         INSIST(disp->requests == 0);
1557         INSIST(disp->recv_pending == 0);
1558
1559         isc_mempool_put(mgr->epool, disp->failsafe_ev);
1560         disp->failsafe_ev = NULL;
1561
1562         if (disp->qid != NULL)
1563                 qid_destroy(mgr->mctx, &disp->qid);
1564         disp->mgr = NULL;
1565         DESTROYLOCK(&disp->lock);
1566         disp->magic = 0;
1567         isc_mempool_put(mgr->dpool, disp);
1568 }
1569
1570 isc_result_t
1571 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
1572                        isc_taskmgr_t *taskmgr, unsigned int buffersize,
1573                        unsigned int maxbuffers, unsigned int maxrequests,
1574                        unsigned int buckets, unsigned int increment,
1575                        unsigned int attributes, dns_dispatch_t **dispp)
1576 {
1577         isc_result_t result;
1578         dns_dispatch_t *disp;
1579
1580         UNUSED(maxbuffers);
1581         UNUSED(buffersize);
1582
1583         REQUIRE(VALID_DISPATCHMGR(mgr));
1584         REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp);
1585         REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0);
1586         REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0);
1587
1588         attributes |= DNS_DISPATCHATTR_PRIVATE;  /* XXXMLG */
1589
1590         LOCK(&mgr->lock);
1591
1592         /*
1593          * dispatch_allocate() checks mgr for us.
1594          * qid_allocate() checks buckets and increment for us.
1595          */
1596         disp = NULL;
1597         result = dispatch_allocate(mgr, maxrequests, &disp);
1598         if (result != ISC_R_SUCCESS) {
1599                 UNLOCK(&mgr->lock);
1600                 return (result);
1601         }
1602
1603         result = qid_allocate(mgr, buckets, increment, &disp->qid);
1604         if (result != ISC_R_SUCCESS)
1605                 goto deallocate_dispatch;
1606
1607         disp->socktype = isc_sockettype_tcp;
1608         disp->socket = NULL;
1609         isc_socket_attach(sock, &disp->socket);
1610
1611         disp->task = NULL;
1612         result = isc_task_create(taskmgr, 0, &disp->task);
1613         if (result != ISC_R_SUCCESS)
1614                 goto kill_socket;
1615
1616         disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
1617                                             DNS_EVENT_DISPATCHCONTROL,
1618                                             destroy_disp, disp,
1619                                             sizeof(isc_event_t));
1620         if (disp->ctlevent == NULL)
1621                 goto kill_task;
1622
1623         isc_task_setname(disp->task, "tcpdispatch", disp);
1624
1625         dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
1626         disp->tcpmsg_valid = 1;
1627
1628         disp->attributes = attributes;
1629
1630         /*
1631          * Append it to the dispatcher list.
1632          */
1633         ISC_LIST_APPEND(mgr->list, disp, link);
1634         UNLOCK(&mgr->lock);
1635
1636         mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp);
1637         dispatch_log(disp, LVL(90), "created task %p", disp->task);
1638
1639         *dispp = disp;
1640
1641         return (ISC_R_SUCCESS);
1642
1643         /*
1644          * Error returns.
1645          */
1646  kill_task:
1647         isc_task_detach(&disp->task);
1648  kill_socket:
1649         isc_socket_detach(&disp->socket);
1650  deallocate_dispatch:
1651         dispatch_free(&disp);
1652
1653         UNLOCK(&mgr->lock);
1654
1655         return (result);
1656 }
1657
1658 isc_result_t
1659 dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
1660                     isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
1661                     unsigned int buffersize,
1662                     unsigned int maxbuffers, unsigned int maxrequests,
1663                     unsigned int buckets, unsigned int increment,
1664                     unsigned int attributes, unsigned int mask,
1665                     dns_dispatch_t **dispp)
1666 {
1667         isc_result_t result;
1668         dns_dispatch_t *disp;
1669
1670         REQUIRE(VALID_DISPATCHMGR(mgr));
1671         REQUIRE(sockmgr != NULL);
1672         REQUIRE(localaddr != NULL);
1673         REQUIRE(taskmgr != NULL);
1674         REQUIRE(buffersize >= 512 && buffersize < (64 * 1024));
1675         REQUIRE(maxbuffers > 0);
1676         REQUIRE(buckets < 2097169);  /* next prime > 65536 * 32 */
1677         REQUIRE(increment > buckets);
1678         REQUIRE(dispp != NULL && *dispp == NULL);
1679         REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0);
1680
1681         result = dns_dispatchmgr_setudp(mgr, buffersize, maxbuffers,
1682                                         buckets, increment);
1683         if (result != ISC_R_SUCCESS)
1684                 return (result);
1685
1686         LOCK(&mgr->lock);
1687
1688         /*
1689          * First, see if we have a dispatcher that matches.
1690          */
1691         disp = NULL;
1692         result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
1693         if (result == ISC_R_SUCCESS) {
1694                 disp->refcount++;
1695
1696                 if (disp->maxrequests < maxrequests)
1697                         disp->maxrequests = maxrequests;
1698
1699                 if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 &&
1700                     (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
1701                 {
1702                         disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
1703                         if (disp->recv_pending != 0)
1704                                 isc_socket_cancel(disp->socket, disp->task,
1705                                                   ISC_SOCKCANCEL_RECV);
1706                 }
1707
1708                 UNLOCK(&disp->lock);
1709                 UNLOCK(&mgr->lock);
1710
1711                 *dispp = disp;
1712
1713                 return (ISC_R_SUCCESS);
1714         }
1715
1716         /*
1717          * Nope, create one.
1718          */
1719         result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr,
1720                                     maxrequests, attributes, &disp);
1721         if (result != ISC_R_SUCCESS) {
1722                 UNLOCK(&mgr->lock);
1723                 return (result);
1724         }
1725
1726         UNLOCK(&mgr->lock);
1727         *dispp = disp;
1728         return (ISC_R_SUCCESS);
1729 }
1730
1731 /*
1732  * mgr should be locked.
1733  */
1734
1735 #ifndef DNS_DISPATCH_HELD
1736 #define DNS_DISPATCH_HELD 20U
1737 #endif
1738
1739 static isc_result_t
1740 dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
1741                    isc_taskmgr_t *taskmgr,
1742                    isc_sockaddr_t *localaddr,
1743                    unsigned int maxrequests,
1744                    unsigned int attributes,
1745                    dns_dispatch_t **dispp)
1746 {
1747         isc_result_t result;
1748         dns_dispatch_t *disp;
1749         isc_socket_t *sock = NULL;
1750         isc_socket_t *held[DNS_DISPATCH_HELD];
1751         unsigned int i = 0, j = 0;
1752
1753         /*
1754          * dispatch_allocate() checks mgr for us.
1755          */
1756         disp = NULL;
1757         result = dispatch_allocate(mgr, maxrequests, &disp);
1758         if (result != ISC_R_SUCCESS)
1759                 return (result);
1760
1761         /*
1762          * Try to allocate a socket that is not on the blacklist.
1763          * Hold up to DNS_DISPATCH_HELD sockets to prevent the OS
1764          * from returning the same port to us too quickly.
1765          */
1766         memset(held, 0, sizeof(held));
1767  getsocket:
1768         result = create_socket(sockmgr, localaddr, &sock);
1769         if (result != ISC_R_SUCCESS)
1770                 goto deallocate_dispatch;
1771         if (isc_sockaddr_getport(localaddr) == 0 && blacklisted(mgr, sock)) {
1772                 if (held[i] != NULL)
1773                         isc_socket_detach(&held[i]);
1774                 held[i++] = sock;
1775                 sock = NULL;
1776                 if (i == DNS_DISPATCH_HELD)
1777                         i = 0;
1778                 if (j++ == 0xffffU) {
1779                         mgr_log(mgr, ISC_LOG_ERROR, "avoid-v%s-udp-ports: "
1780                                 "unable to allocate a non-blacklisted port",
1781                                 isc_sockaddr_pf(localaddr) == AF_INET ?
1782                                         "4" : "6");
1783                         result = ISC_R_FAILURE;
1784                         goto deallocate_dispatch;
1785                 }
1786                 goto getsocket;
1787         }
1788
1789         disp->socktype = isc_sockettype_udp;
1790         disp->socket = sock;
1791         disp->local = *localaddr;
1792
1793         disp->task = NULL;
1794         result = isc_task_create(taskmgr, 0, &disp->task);
1795         if (result != ISC_R_SUCCESS)
1796                 goto kill_socket;
1797
1798         disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
1799                                             DNS_EVENT_DISPATCHCONTROL,
1800                                             destroy_disp, disp,
1801                                             sizeof(isc_event_t));
1802         if (disp->ctlevent == NULL)
1803                 goto kill_task;
1804
1805         isc_task_setname(disp->task, "udpdispatch", disp);
1806
1807         attributes &= ~DNS_DISPATCHATTR_TCP;
1808         attributes |= DNS_DISPATCHATTR_UDP;
1809         disp->attributes = attributes;
1810
1811         /*
1812          * Append it to the dispatcher list.
1813          */
1814         ISC_LIST_APPEND(mgr->list, disp, link);
1815
1816         mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
1817         dispatch_log(disp, LVL(90), "created task %p", disp->task);
1818         dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
1819
1820         *dispp = disp;
1821
1822         goto cleanheld;
1823
1824         /*
1825          * Error returns.
1826          */
1827  kill_task:
1828         isc_task_detach(&disp->task);
1829  kill_socket:
1830         isc_socket_detach(&disp->socket);
1831  deallocate_dispatch:
1832         dispatch_free(&disp);
1833  cleanheld:
1834         for (i = 0; i < DNS_DISPATCH_HELD; i++)
1835                 if (held[i] != NULL)
1836                         isc_socket_detach(&held[i]);
1837         return (result);
1838 }
1839
1840 void
1841 dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {
1842         REQUIRE(VALID_DISPATCH(disp));
1843         REQUIRE(dispp != NULL && *dispp == NULL);
1844
1845         LOCK(&disp->lock);
1846         disp->refcount++;
1847         UNLOCK(&disp->lock);
1848
1849         *dispp = disp;
1850 }
1851
1852 /*
1853  * It is important to lock the manager while we are deleting the dispatch,
1854  * since dns_dispatch_getudp will call dispatch_find, which returns to
1855  * the caller a dispatch but does not attach to it until later.  _getudp
1856  * locks the manager, however, so locking it here will keep us from attaching
1857  * to a dispatcher that is in the process of going away.
1858  */
1859 void
1860 dns_dispatch_detach(dns_dispatch_t **dispp) {
1861         dns_dispatch_t *disp;
1862         isc_boolean_t killit;
1863
1864         REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));
1865
1866         disp = *dispp;
1867         *dispp = NULL;
1868
1869         LOCK(&disp->lock);
1870
1871         INSIST(disp->refcount > 0);
1872         disp->refcount--;
1873         killit = ISC_FALSE;
1874         if (disp->refcount == 0) {
1875                 if (disp->recv_pending > 0)
1876                         isc_socket_cancel(disp->socket, disp->task,
1877                                           ISC_SOCKCANCEL_RECV);
1878                 disp->shutting_down = 1;
1879         }
1880
1881         dispatch_log(disp, LVL(90), "detach: refcount %d", disp->refcount);
1882
1883         killit = destroy_disp_ok(disp);
1884         UNLOCK(&disp->lock);
1885         if (killit)
1886                 isc_task_send(disp->task, &disp->ctlevent);
1887 }
1888
1889 isc_result_t
1890 dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
1891                          isc_task_t *task, isc_taskaction_t action, void *arg,
1892                          dns_messageid_t *idp, dns_dispentry_t **resp)
1893 {
1894         dns_dispentry_t *res;
1895         unsigned int bucket;
1896         dns_messageid_t id;
1897         int i;
1898         isc_boolean_t ok;
1899         dns_qid_t *qid;
1900
1901         REQUIRE(VALID_DISPATCH(disp));
1902         REQUIRE(task != NULL);
1903         REQUIRE(dest != NULL);
1904         REQUIRE(resp != NULL && *resp == NULL);
1905         REQUIRE(idp != NULL);
1906
1907         LOCK(&disp->lock);
1908
1909         if (disp->shutting_down == 1) {
1910                 UNLOCK(&disp->lock);
1911                 return (ISC_R_SHUTTINGDOWN);
1912         }
1913
1914         if (disp->requests >= disp->maxrequests) {
1915                 UNLOCK(&disp->lock);
1916                 return (ISC_R_QUOTA);
1917         }
1918
1919         /*
1920          * Try somewhat hard to find an unique ID.
1921          */
1922         qid = DNS_QID(disp);
1923         LOCK(&qid->lock);
1924         id = dns_randomid(qid);
1925         bucket = dns_hash(qid, dest, id);
1926         ok = ISC_FALSE;
1927         for (i = 0; i < 64; i++) {
1928                 if (bucket_search(qid, dest, id, bucket) == NULL) {
1929                         ok = ISC_TRUE;
1930                         break;
1931                 }
1932                 id += qid->qid_increment;
1933                 id &= 0x0000ffff;
1934                 bucket = dns_hash(qid, dest, id);
1935         }
1936
1937         if (!ok) {
1938                 UNLOCK(&qid->lock);
1939                 UNLOCK(&disp->lock);
1940                 return (ISC_R_NOMORE);
1941         }
1942
1943         res = isc_mempool_get(disp->mgr->rpool);
1944         if (res == NULL) {
1945                 UNLOCK(&qid->lock);
1946                 UNLOCK(&disp->lock);
1947                 return (ISC_R_NOMEMORY);
1948         }
1949
1950         disp->refcount++;
1951         disp->requests++;
1952         res->task = NULL;
1953         isc_task_attach(task, &res->task);
1954         res->disp = disp;
1955         res->id = id;
1956         res->bucket = bucket;
1957         res->host = *dest;
1958         res->action = action;
1959         res->arg = arg;
1960         res->item_out = ISC_FALSE;
1961         ISC_LIST_INIT(res->items);
1962         ISC_LINK_INIT(res, link);
1963         res->magic = RESPONSE_MAGIC;
1964         ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
1965         UNLOCK(&qid->lock);
1966
1967         request_log(disp, res, LVL(90),
1968                     "attached to task %p", res->task);
1969
1970         if (((disp->attributes & DNS_DISPATCHATTR_UDP) != 0) ||
1971             ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0))
1972                 startrecv(disp);
1973
1974         UNLOCK(&disp->lock);
1975
1976         *idp = id;
1977         *resp = res;
1978
1979         return (ISC_R_SUCCESS);
1980 }
1981
1982 void
1983 dns_dispatch_starttcp(dns_dispatch_t *disp) {
1984
1985         REQUIRE(VALID_DISPATCH(disp));
1986
1987         dispatch_log(disp, LVL(90), "starttcp %p", disp->task);
1988
1989         LOCK(&disp->lock);
1990         disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
1991         startrecv(disp);
1992         UNLOCK(&disp->lock);
1993 }
1994
1995 void
1996 dns_dispatch_removeresponse(dns_dispentry_t **resp,
1997                             dns_dispatchevent_t **sockevent)
1998 {
1999         dns_dispatchmgr_t *mgr;
2000         dns_dispatch_t *disp;
2001         dns_dispentry_t *res;
2002         dns_dispatchevent_t *ev;
2003         unsigned int bucket;
2004         isc_boolean_t killit;
2005         unsigned int n;
2006         isc_eventlist_t events;
2007         dns_qid_t *qid;
2008
2009         REQUIRE(resp != NULL);
2010         REQUIRE(VALID_RESPONSE(*resp));
2011
2012         res = *resp;
2013         *resp = NULL;
2014
2015         disp = res->disp;
2016         REQUIRE(VALID_DISPATCH(disp));
2017         mgr = disp->mgr;
2018         REQUIRE(VALID_DISPATCHMGR(mgr));
2019
2020         qid = DNS_QID(disp);
2021
2022         if (sockevent != NULL) {
2023                 REQUIRE(*sockevent != NULL);
2024                 ev = *sockevent;
2025                 *sockevent = NULL;
2026         } else {
2027                 ev = NULL;
2028         }
2029
2030         LOCK(&disp->lock);
2031
2032         INSIST(disp->requests > 0);
2033         disp->requests--;
2034         INSIST(disp->refcount > 0);
2035         disp->refcount--;
2036         killit = ISC_FALSE;
2037         if (disp->refcount == 0) {
2038                 if (disp->recv_pending > 0)
2039                         isc_socket_cancel(disp->socket, disp->task,
2040                                           ISC_SOCKCANCEL_RECV);
2041                 disp->shutting_down = 1;
2042         }
2043
2044         bucket = res->bucket;
2045
2046         LOCK(&qid->lock);
2047         ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
2048         UNLOCK(&qid->lock);
2049
2050         if (ev == NULL && res->item_out) {
2051                 /*
2052                  * We've posted our event, but the caller hasn't gotten it
2053                  * yet.  Take it back.
2054                  */
2055                 ISC_LIST_INIT(events);
2056                 n = isc_task_unsend(res->task, res, DNS_EVENT_DISPATCH,
2057                                     NULL, &events);
2058                 /*
2059                  * We had better have gotten it back.
2060                  */
2061                 INSIST(n == 1);
2062                 ev = (dns_dispatchevent_t *)ISC_LIST_HEAD(events);
2063         }
2064
2065         if (ev != NULL) {
2066                 REQUIRE(res->item_out == ISC_TRUE);
2067                 res->item_out = ISC_FALSE;
2068                 if (ev->buffer.base != NULL)
2069                         free_buffer(disp, ev->buffer.base, ev->buffer.length);
2070                 free_event(disp, ev);
2071         }
2072
2073         request_log(disp, res, LVL(90), "detaching from task %p", res->task);
2074         isc_task_detach(&res->task);
2075
2076         /*
2077          * Free any buffered requests as well
2078          */
2079         ev = ISC_LIST_HEAD(res->items);
2080         while (ev != NULL) {
2081                 ISC_LIST_UNLINK(res->items, ev, ev_link);
2082                 if (ev->buffer.base != NULL)
2083                         free_buffer(disp, ev->buffer.base, ev->buffer.length);
2084                 free_event(disp, ev);
2085                 ev = ISC_LIST_HEAD(res->items);
2086         }
2087         res->magic = 0;
2088         isc_mempool_put(disp->mgr->rpool, res);
2089         if (disp->shutting_down == 1)
2090                 do_cancel(disp);
2091         else
2092                 startrecv(disp);
2093
2094         killit = destroy_disp_ok(disp);
2095         UNLOCK(&disp->lock);
2096         if (killit)
2097                 isc_task_send(disp->task, &disp->ctlevent);
2098 }
2099
2100 static void
2101 do_cancel(dns_dispatch_t *disp) {
2102         dns_dispatchevent_t *ev;
2103         dns_dispentry_t *resp;
2104         dns_qid_t *qid;
2105
2106         if (disp->shutdown_out == 1)
2107                 return;
2108
2109         qid = DNS_QID(disp);
2110
2111         /*
2112          * Search for the first response handler without packets outstanding.
2113          */
2114         LOCK(&qid->lock);
2115         for (resp = linear_first(qid);
2116              resp != NULL && resp->item_out != ISC_FALSE;
2117              /* Empty. */)
2118                 resp = linear_next(qid, resp);
2119         /*
2120          * No one to send the cancel event to, so nothing to do.
2121          */
2122         if (resp == NULL)
2123                 goto unlock;
2124
2125         /*
2126          * Send the shutdown failsafe event to this resp.
2127          */
2128         ev = disp->failsafe_ev;
2129         ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH,
2130                        resp->action, resp->arg, resp, NULL, NULL);
2131         ev->result = disp->shutdown_why;
2132         ev->buffer.base = NULL;
2133         ev->buffer.length = 0;
2134         disp->shutdown_out = 1;
2135         request_log(disp, resp, LVL(10),
2136                     "cancel: failsafe event %p -> task %p",
2137                     ev, resp->task);
2138         resp->item_out = ISC_TRUE;
2139         isc_task_send(resp->task, ISC_EVENT_PTR(&ev));
2140  unlock:
2141         UNLOCK(&qid->lock);
2142 }
2143
2144 isc_socket_t *
2145 dns_dispatch_getsocket(dns_dispatch_t *disp) {
2146         REQUIRE(VALID_DISPATCH(disp));
2147
2148         return (disp->socket);
2149 }
2150
2151 isc_result_t
2152 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {
2153
2154         REQUIRE(VALID_DISPATCH(disp));
2155         REQUIRE(addrp != NULL);
2156
2157         if (disp->socktype == isc_sockettype_udp) {
2158                 *addrp = disp->local;
2159                 return (ISC_R_SUCCESS);
2160         }
2161         return (ISC_R_NOTIMPLEMENTED);
2162 }
2163
2164 void
2165 dns_dispatch_cancel(dns_dispatch_t *disp) {
2166         REQUIRE(VALID_DISPATCH(disp));
2167
2168         LOCK(&disp->lock);
2169
2170         if (disp->shutting_down == 1) {
2171                 UNLOCK(&disp->lock);
2172                 return;
2173         }
2174
2175         disp->shutdown_why = ISC_R_CANCELED;
2176         disp->shutting_down = 1;
2177         do_cancel(disp);
2178
2179         UNLOCK(&disp->lock);
2180
2181         return;
2182 }
2183
2184 void
2185 dns_dispatch_changeattributes(dns_dispatch_t *disp,
2186                               unsigned int attributes, unsigned int mask)
2187 {
2188         REQUIRE(VALID_DISPATCH(disp));
2189
2190         /* XXXMLG
2191          * Should check for valid attributes here!
2192          */
2193
2194         LOCK(&disp->lock);
2195
2196         if ((mask & DNS_DISPATCHATTR_NOLISTEN) != 0) {
2197                 if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 &&
2198                     (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) {
2199                         disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN;
2200                         startrecv(disp);
2201                 } else if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN)
2202                            == 0 &&
2203                            (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) {
2204                         disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
2205                         if (disp->recv_pending != 0)
2206                                 isc_socket_cancel(disp->socket, disp->task,
2207                                                   ISC_SOCKCANCEL_RECV);
2208                 }
2209         }
2210
2211         disp->attributes &= ~mask;
2212         disp->attributes |= (attributes & mask);
2213         UNLOCK(&disp->lock);
2214 }
2215
2216 void
2217 dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
2218         void *buf;
2219         isc_socketevent_t *sevent, *newsevent;
2220
2221         REQUIRE(VALID_DISPATCH(disp));
2222         REQUIRE((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0);
2223         REQUIRE(event != NULL);
2224
2225         sevent = (isc_socketevent_t *)event;
2226
2227         INSIST(sevent->n <= disp->mgr->buffersize);
2228         newsevent = (isc_socketevent_t *)
2229                     isc_event_allocate(disp->mgr->mctx, NULL,
2230                                       DNS_EVENT_IMPORTRECVDONE, udp_recv,
2231                                       disp, sizeof(isc_socketevent_t));
2232         if (newsevent == NULL)
2233                 return;
2234
2235         buf = allocate_udp_buffer(disp);
2236         if (buf == NULL) {
2237                 isc_event_free(ISC_EVENT_PTR(&newsevent));
2238                 return;
2239         }
2240         memcpy(buf, sevent->region.base, sevent->n);
2241         newsevent->region.base = buf;
2242         newsevent->region.length = disp->mgr->buffersize;
2243         newsevent->n = sevent->n;
2244         newsevent->result = sevent->result;
2245         newsevent->address = sevent->address;
2246         newsevent->timestamp = sevent->timestamp;
2247         newsevent->pktinfo = sevent->pktinfo;
2248         newsevent->attributes = sevent->attributes;
2249         
2250         isc_task_send(disp->task, ISC_EVENT_PTR(&newsevent));
2251 }
2252
2253 #if 0
2254 void
2255 dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {
2256         dns_dispatch_t *disp;
2257         char foo[1024];
2258
2259         disp = ISC_LIST_HEAD(mgr->list);
2260         while (disp != NULL) {
2261                 isc_sockaddr_format(&disp->local, foo, sizeof(foo));
2262                 printf("\tdispatch %p, addr %s\n", disp, foo);
2263                 disp = ISC_LIST_NEXT(disp, link);
2264         }
2265 }
2266 #endif