]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/bin/named/client.c
Update to version 9.6-ESV-R6, the latest from ISC, which contains numerous
[FreeBSD/stable/8.git] / contrib / bind9 / bin / named / client.c
1 /*
2  * Copyright (C) 2004-2012  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$ */
19
20 #include <config.h>
21
22 #include <isc/formatcheck.h>
23 #include <isc/mutex.h>
24 #include <isc/once.h>
25 #include <isc/platform.h>
26 #include <isc/print.h>
27 #include <isc/stats.h>
28 #include <isc/stdio.h>
29 #include <isc/string.h>
30 #include <isc/task.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
33
34 #include <dns/db.h>
35 #include <dns/dispatch.h>
36 #include <dns/events.h>
37 #include <dns/message.h>
38 #include <dns/peer.h>
39 #include <dns/rcode.h>
40 #include <dns/rdata.h>
41 #include <dns/rdataclass.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/resolver.h>
45 #include <dns/stats.h>
46 #include <dns/tsig.h>
47 #include <dns/view.h>
48 #include <dns/zone.h>
49
50 #include <named/interfacemgr.h>
51 #include <named/log.h>
52 #include <named/notify.h>
53 #include <named/os.h>
54 #include <named/server.h>
55 #include <named/update.h>
56
57 /***
58  *** Client
59  ***/
60
61 /*! \file
62  * Client Routines
63  *
64  * Important note!
65  *
66  * All client state changes, other than that from idle to listening, occur
67  * as a result of events.  This guarantees serialization and avoids the
68  * need for locking.
69  *
70  * If a routine is ever created that allows someone other than the client's
71  * task to change the client, then the client will have to be locked.
72  */
73
74 #define NS_CLIENT_TRACE
75 #ifdef NS_CLIENT_TRACE
76 #define CTRACE(m)       ns_client_log(client, \
77                                       NS_LOGCATEGORY_CLIENT, \
78                                       NS_LOGMODULE_CLIENT, \
79                                       ISC_LOG_DEBUG(3), \
80                                       "%s", (m))
81 #define MTRACE(m)       isc_log_write(ns_g_lctx, \
82                                       NS_LOGCATEGORY_GENERAL, \
83                                       NS_LOGMODULE_CLIENT, \
84                                       ISC_LOG_DEBUG(3), \
85                                       "clientmgr @%p: %s", manager, (m))
86 #else
87 #define CTRACE(m)       ((void)(m))
88 #define MTRACE(m)       ((void)(m))
89 #endif
90
91 #define TCP_CLIENT(c)   (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
92
93 #define TCP_BUFFER_SIZE                 (65535 + 2)
94 #define SEND_BUFFER_SIZE                4096
95 #define RECV_BUFFER_SIZE                4096
96
97 #ifdef ISC_PLATFORM_USETHREADS
98 #define NMCTXS                          100
99 /*%<
100  * Number of 'mctx pools' for clients. (Should this be configurable?)
101  * When enabling threads, we use a pool of memory contexts shared by
102  * client objects, since concurrent access to a shared context would cause
103  * heavy contentions.  The above constant is expected to be enough for
104  * completely avoiding contentions among threads for an authoritative-only
105  * server.
106  */
107 #else
108 #define NMCTXS                          0
109 /*%<
110  * If named with built without thread, simply share manager's context.  Using
111  * a separate context in this case would simply waste memory.
112  */
113 #endif
114
115 /*% nameserver client manager structure */
116 struct ns_clientmgr {
117         /* Unlocked. */
118         unsigned int                    magic;
119         isc_mem_t *                     mctx;
120         isc_taskmgr_t *                 taskmgr;
121         isc_timermgr_t *                timermgr;
122         isc_mutex_t                     lock;
123         /* Locked by lock. */
124         isc_boolean_t                   exiting;
125         client_list_t                   active;         /*%< Active clients */
126         client_list_t                   recursing;      /*%< Recursing clients */
127         client_list_t                   inactive;       /*%< To be recycled */
128 #if NMCTXS > 0
129         /*%< mctx pool for clients. */
130         unsigned int                    nextmctx;
131         isc_mem_t *                     mctxpool[NMCTXS];
132 #endif
133 };
134
135 #define MANAGER_MAGIC                   ISC_MAGIC('N', 'S', 'C', 'm')
136 #define VALID_MANAGER(m)                ISC_MAGIC_VALID(m, MANAGER_MAGIC)
137
138 /*!
139  * Client object states.  Ordering is significant: higher-numbered
140  * states are generally "more active", meaning that the client can
141  * have more dynamically allocated data, outstanding events, etc.
142  * In the list below, any such properties listed for state N
143  * also apply to any state > N.
144  *
145  * To force the client into a less active state, set client->newstate
146  * to that state and call exit_check().  This will cause any
147  * activities defined for higher-numbered states to be aborted.
148  */
149
150 #define NS_CLIENTSTATE_FREED    0
151 /*%<
152  * The client object no longer exists.
153  */
154
155 #define NS_CLIENTSTATE_INACTIVE 1
156 /*%<
157  * The client object exists and has a task and timer.
158  * Its "query" struct and sendbuf are initialized.
159  * It is on the client manager's list of inactive clients.
160  * It has a message and OPT, both in the reset state.
161  */
162
163 #define NS_CLIENTSTATE_READY    2
164 /*%<
165  * The client object is either a TCP or a UDP one, and
166  * it is associated with a network interface.  It is on the
167  * client manager's list of active clients.
168  *
169  * If it is a TCP client object, it has a TCP listener socket
170  * and an outstanding TCP listen request.
171  *
172  * If it is a UDP client object, it has a UDP listener socket
173  * and an outstanding UDP receive request.
174  */
175
176 #define NS_CLIENTSTATE_READING  3
177 /*%<
178  * The client object is a TCP client object that has received
179  * a connection.  It has a tcpsocket, tcpmsg, TCP quota, and an
180  * outstanding TCP read request.  This state is not used for
181  * UDP client objects.
182  */
183
184 #define NS_CLIENTSTATE_WORKING  4
185 /*%<
186  * The client object has received a request and is working
187  * on it.  It has a view, and it may have any of a non-reset OPT,
188  * recursion quota, and an outstanding write request.
189  */
190
191 #define NS_CLIENTSTATE_MAX      9
192 /*%<
193  * Sentinel value used to indicate "no state".  When client->newstate
194  * has this value, we are not attempting to exit the current state.
195  * Must be greater than any valid state.
196  */
197
198 /*
199  * Enable ns_client_dropport() by default.
200  */
201 #ifndef NS_CLIENT_DROPPORT
202 #define NS_CLIENT_DROPPORT 1
203 #endif
204
205 unsigned int ns_client_requests;
206
207 static void client_read(ns_client_t *client);
208 static void client_accept(ns_client_t *client);
209 static void client_udprecv(ns_client_t *client);
210 static void clientmgr_destroy(ns_clientmgr_t *manager);
211 static isc_boolean_t exit_check(ns_client_t *client);
212 static void ns_client_endrequest(ns_client_t *client);
213 static void ns_client_checkactive(ns_client_t *client);
214 static void client_start(isc_task_t *task, isc_event_t *event);
215 static void client_request(isc_task_t *task, isc_event_t *event);
216 static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
217
218 void
219 ns_client_recursing(ns_client_t *client) {
220         REQUIRE(NS_CLIENT_VALID(client));
221
222         LOCK(&client->manager->lock);
223         ISC_LIST_UNLINK(*client->list, client, link);
224         ISC_LIST_APPEND(client->manager->recursing, client, link);
225         client->list = &client->manager->recursing;
226         UNLOCK(&client->manager->lock);
227 }
228
229 void
230 ns_client_killoldestquery(ns_client_t *client) {
231         ns_client_t *oldest;
232         REQUIRE(NS_CLIENT_VALID(client));
233
234         LOCK(&client->manager->lock);
235         oldest = ISC_LIST_HEAD(client->manager->recursing);
236         if (oldest != NULL) {
237                 ns_query_cancel(oldest);
238                 ISC_LIST_UNLINK(*oldest->list, oldest, link);
239                 ISC_LIST_APPEND(client->manager->active, oldest, link);
240                 oldest->list = &client->manager->active;
241         }
242         UNLOCK(&client->manager->lock);
243 }
244
245 void
246 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
247         isc_result_t result;
248         isc_interval_t interval;
249
250         isc_interval_set(&interval, seconds, 0);
251         result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
252                                  &interval, ISC_FALSE);
253         client->timerset = ISC_TRUE;
254         if (result != ISC_R_SUCCESS) {
255                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
256                               NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
257                               "setting timeout: %s",
258                               isc_result_totext(result));
259                 /* Continue anyway. */
260         }
261 }
262
263 /*%
264  * Check for a deactivation or shutdown request and take appropriate
265  * action.  Returns ISC_TRUE if either is in progress; in this case
266  * the caller must no longer use the client object as it may have been
267  * freed.
268  */
269 static isc_boolean_t
270 exit_check(ns_client_t *client) {
271         ns_clientmgr_t *locked_manager = NULL;
272         ns_clientmgr_t *destroy_manager = NULL;
273
274         REQUIRE(NS_CLIENT_VALID(client));
275
276         if (client->state <= client->newstate)
277                 return (ISC_FALSE); /* Business as usual. */
278
279         INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
280
281         /*
282          * We need to detach from the view early when shutting down
283          * the server to break the following vicious circle:
284          *
285          *  - The resolver will not shut down until the view refcount is zero
286          *  - The view refcount does not go to zero until all clients detach
287          *  - The client does not detach from the view until references is zero
288          *  - references does not go to zero until the resolver has shut down
289          *
290          * Keep the view attached until any outstanding updates complete.
291          */
292         if (client->nupdates == 0 &&
293             client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
294                 dns_view_detach(&client->view);
295
296         if (client->state == NS_CLIENTSTATE_WORKING) {
297                 INSIST(client->newstate <= NS_CLIENTSTATE_READING);
298                 /*
299                  * Let the update processing complete.
300                  */
301                 if (client->nupdates > 0)
302                         return (ISC_TRUE);
303                 /*
304                  * We are trying to abort request processing.
305                  */
306                 if (client->nsends > 0) {
307                         isc_socket_t *socket;
308                         if (TCP_CLIENT(client))
309                                 socket = client->tcpsocket;
310                         else
311                                 socket = client->udpsocket;
312                         isc_socket_cancel(socket, client->task,
313                                           ISC_SOCKCANCEL_SEND);
314                 }
315
316                 if (! (client->nsends == 0 && client->nrecvs == 0 &&
317                        client->references == 0))
318                 {
319                         /*
320                          * Still waiting for I/O cancel completion.
321                          * or lingering references.
322                          */
323                         return (ISC_TRUE);
324                 }
325                 /*
326                  * I/O cancel is complete.  Burn down all state
327                  * related to the current request.  Ensure that
328                  * the client is on the active list and not the
329                  * recursing list.
330                  */
331                 LOCK(&client->manager->lock);
332                 if (client->list == &client->manager->recursing) {
333                         ISC_LIST_UNLINK(*client->list, client, link);
334                         ISC_LIST_APPEND(client->manager->active, client, link);
335                         client->list = &client->manager->active;
336                 }
337                 UNLOCK(&client->manager->lock);
338                 ns_client_endrequest(client);
339
340                 client->state = NS_CLIENTSTATE_READING;
341                 INSIST(client->recursionquota == NULL);
342                 if (NS_CLIENTSTATE_READING == client->newstate) {
343                         client_read(client);
344                         client->newstate = NS_CLIENTSTATE_MAX;
345                         return (ISC_TRUE); /* We're done. */
346                 }
347         }
348
349         if (client->state == NS_CLIENTSTATE_READING) {
350                 /*
351                  * We are trying to abort the current TCP connection,
352                  * if any.
353                  */
354                 INSIST(client->recursionquota == NULL);
355                 INSIST(client->newstate <= NS_CLIENTSTATE_READY);
356                 if (client->nreads > 0)
357                         dns_tcpmsg_cancelread(&client->tcpmsg);
358                 if (! client->nreads == 0) {
359                         /* Still waiting for read cancel completion. */
360                         return (ISC_TRUE);
361                 }
362
363                 if (client->tcpmsg_valid) {
364                         dns_tcpmsg_invalidate(&client->tcpmsg);
365                         client->tcpmsg_valid = ISC_FALSE;
366                 }
367                 if (client->tcpsocket != NULL) {
368                         CTRACE("closetcp");
369                         isc_socket_detach(&client->tcpsocket);
370                 }
371
372                 if (client->tcpquota != NULL)
373                         isc_quota_detach(&client->tcpquota);
374
375                 if (client->timerset) {
376                         (void)isc_timer_reset(client->timer,
377                                               isc_timertype_inactive,
378                                               NULL, NULL, ISC_TRUE);
379                         client->timerset = ISC_FALSE;
380                 }
381
382                 client->peeraddr_valid = ISC_FALSE;
383
384                 client->state = NS_CLIENTSTATE_READY;
385                 INSIST(client->recursionquota == NULL);
386
387                 /*
388                  * Now the client is ready to accept a new TCP connection
389                  * or UDP request, but we may have enough clients doing
390                  * that already.  Check whether this client needs to remain
391                  * active and force it to go inactive if not.
392                  */
393                 ns_client_checkactive(client);
394
395                 if (NS_CLIENTSTATE_READY == client->newstate) {
396                         if (TCP_CLIENT(client)) {
397                                 client_accept(client);
398                         } else
399                                 client_udprecv(client);
400                         client->newstate = NS_CLIENTSTATE_MAX;
401                         return (ISC_TRUE);
402                 }
403         }
404
405         if (client->state == NS_CLIENTSTATE_READY) {
406                 INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
407                 /*
408                  * We are trying to enter the inactive state.
409                  */
410                 if (client->naccepts > 0)
411                         isc_socket_cancel(client->tcplistener, client->task,
412                                           ISC_SOCKCANCEL_ACCEPT);
413
414                 if (! (client->naccepts == 0)) {
415                         /* Still waiting for accept cancel completion. */
416                         return (ISC_TRUE);
417                 }
418                 /* Accept cancel is complete. */
419
420                 if (client->nrecvs > 0)
421                         isc_socket_cancel(client->udpsocket, client->task,
422                                           ISC_SOCKCANCEL_RECV);
423                 if (! (client->nrecvs == 0)) {
424                         /* Still waiting for recv cancel completion. */
425                         return (ISC_TRUE);
426                 }
427                 /* Recv cancel is complete. */
428
429                 if (client->nctls > 0) {
430                         /* Still waiting for control event to be delivered */
431                         return (ISC_TRUE);
432                 }
433
434                 /* Deactivate the client. */
435                 if (client->interface)
436                         ns_interface_detach(&client->interface);
437
438                 INSIST(client->naccepts == 0);
439                 INSIST(client->recursionquota == NULL);
440                 if (client->tcplistener != NULL)
441                         isc_socket_detach(&client->tcplistener);
442
443                 if (client->udpsocket != NULL)
444                         isc_socket_detach(&client->udpsocket);
445
446                 if (client->dispatch != NULL)
447                         dns_dispatch_detach(&client->dispatch);
448
449                 client->attributes = 0;
450                 client->mortal = ISC_FALSE;
451
452                 LOCK(&client->manager->lock);
453                 /*
454                  * Put the client on the inactive list.  If we are aiming for
455                  * the "freed" state, it will be removed from the inactive
456                  * list shortly, and we need to keep the manager locked until
457                  * that has been done, lest the manager decide to reactivate
458                  * the dying client inbetween.
459                  */
460                 locked_manager = client->manager;
461                 ISC_LIST_UNLINK(*client->list, client, link);
462                 ISC_LIST_APPEND(client->manager->inactive, client, link);
463                 client->list = &client->manager->inactive;
464                 client->state = NS_CLIENTSTATE_INACTIVE;
465                 INSIST(client->recursionquota == NULL);
466
467                 if (client->state == client->newstate) {
468                         client->newstate = NS_CLIENTSTATE_MAX;
469                         if (client->needshutdown)
470                                 isc_task_shutdown(client->task);
471                         goto unlock;
472                 }
473         }
474
475         if (client->state == NS_CLIENTSTATE_INACTIVE) {
476                 INSIST(client->newstate == NS_CLIENTSTATE_FREED);
477                 /*
478                  * We are trying to free the client.
479                  *
480                  * When "shuttingdown" is true, either the task has received
481                  * its shutdown event or no shutdown event has ever been
482                  * set up.  Thus, we have no outstanding shutdown
483                  * event at this point.
484                  */
485                 REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
486
487                 INSIST(client->recursionquota == NULL);
488
489                 ns_query_free(client);
490                 isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
491                 isc_event_free((isc_event_t **)&client->sendevent);
492                 isc_event_free((isc_event_t **)&client->recvevent);
493                 isc_timer_detach(&client->timer);
494
495                 if (client->tcpbuf != NULL)
496                         isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
497                 if (client->opt != NULL) {
498                         INSIST(dns_rdataset_isassociated(client->opt));
499                         dns_rdataset_disassociate(client->opt);
500                         dns_message_puttemprdataset(client->message, &client->opt);
501                 }
502                 dns_message_destroy(&client->message);
503                 if (client->manager != NULL) {
504                         ns_clientmgr_t *manager = client->manager;
505                         if (locked_manager == NULL) {
506                                 LOCK(&manager->lock);
507                                 locked_manager = manager;
508                         }
509                         ISC_LIST_UNLINK(*client->list, client, link);
510                         client->list = NULL;
511                         if (manager->exiting &&
512                             ISC_LIST_EMPTY(manager->active) &&
513                             ISC_LIST_EMPTY(manager->inactive) &&
514                             ISC_LIST_EMPTY(manager->recursing))
515                                 destroy_manager = manager;
516                 }
517                 /*
518                  * Detaching the task must be done after unlinking from
519                  * the manager's lists because the manager accesses
520                  * client->task.
521                  */
522                 if (client->task != NULL)
523                         isc_task_detach(&client->task);
524
525                 CTRACE("free");
526                 client->magic = 0;
527                 /*
528                  * Check that there are no other external references to
529                  * the memory context.
530                  */
531                 if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
532                         isc_mem_stats(client->mctx, stderr);
533                         INSIST(0);
534                 }
535                 isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
536
537                 goto unlock;
538         }
539
540  unlock:
541         if (locked_manager != NULL) {
542                 UNLOCK(&locked_manager->lock);
543                 locked_manager = NULL;
544         }
545
546         /*
547          * Only now is it safe to destroy the client manager (if needed),
548          * because we have accessed its lock for the last time.
549          */
550         if (destroy_manager != NULL)
551                 clientmgr_destroy(destroy_manager);
552
553         return (ISC_TRUE);
554 }
555
556 /*%
557  * The client's task has received the client's control event
558  * as part of the startup process.
559  */
560 static void
561 client_start(isc_task_t *task, isc_event_t *event) {
562         ns_client_t *client = (ns_client_t *) event->ev_arg;
563
564         INSIST(task == client->task);
565
566         UNUSED(task);
567
568         INSIST(client->nctls == 1);
569         client->nctls--;
570
571         if (exit_check(client))
572                 return;
573
574         if (TCP_CLIENT(client)) {
575                 client_accept(client);
576         } else {
577                 client_udprecv(client);
578         }
579 }
580
581
582 /*%
583  * The client's task has received a shutdown event.
584  */
585 static void
586 client_shutdown(isc_task_t *task, isc_event_t *event) {
587         ns_client_t *client;
588
589         REQUIRE(event != NULL);
590         REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
591         client = event->ev_arg;
592         REQUIRE(NS_CLIENT_VALID(client));
593         REQUIRE(task == client->task);
594
595         UNUSED(task);
596
597         CTRACE("shutdown");
598
599         isc_event_free(&event);
600
601         if (client->shutdown != NULL) {
602                 (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
603                 client->shutdown = NULL;
604                 client->shutdown_arg = NULL;
605         }
606
607         client->newstate = NS_CLIENTSTATE_FREED;
608         client->needshutdown = ISC_FALSE;
609         (void)exit_check(client);
610 }
611
612 static void
613 ns_client_endrequest(ns_client_t *client) {
614         INSIST(client->naccepts == 0);
615         INSIST(client->nreads == 0);
616         INSIST(client->nsends == 0);
617         INSIST(client->nrecvs == 0);
618         INSIST(client->nupdates == 0);
619         INSIST(client->state == NS_CLIENTSTATE_WORKING);
620
621         CTRACE("endrequest");
622
623         if (client->next != NULL) {
624                 (client->next)(client);
625                 client->next = NULL;
626         }
627
628         if (client->view != NULL)
629                 dns_view_detach(&client->view);
630         if (client->opt != NULL) {
631                 INSIST(dns_rdataset_isassociated(client->opt));
632                 dns_rdataset_disassociate(client->opt);
633                 dns_message_puttemprdataset(client->message, &client->opt);
634         }
635
636         client->signer = NULL;
637         client->udpsize = 512;
638         client->extflags = 0;
639         client->ednsversion = -1;
640         dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
641
642         if (client->recursionquota != NULL)
643                 isc_quota_detach(&client->recursionquota);
644
645         /*
646          * Clear all client attributes that are specific to
647          * the request; that's all except the TCP flag.
648          */
649         client->attributes &= NS_CLIENTATTR_TCP;
650 }
651
652 static void
653 ns_client_checkactive(ns_client_t *client) {
654         if (client->mortal) {
655                 /*
656                  * This client object should normally go inactive
657                  * at this point, but if we have fewer active client
658                  * objects than desired due to earlier quota exhaustion,
659                  * keep it active to make up for the shortage.
660                  */
661                 isc_boolean_t need_another_client = ISC_FALSE;
662                 if (TCP_CLIENT(client) && !ns_g_clienttest) {
663                         LOCK(&client->interface->lock);
664                         if (client->interface->ntcpcurrent <
665                             client->interface->ntcptarget)
666                                 need_another_client = ISC_TRUE;
667                         UNLOCK(&client->interface->lock);
668                 } else {
669                         /*
670                          * The UDP client quota is enforced by making
671                          * requests fail rather than by not listening
672                          * for new ones.  Therefore, there is always a
673                          * full set of UDP clients listening.
674                          */
675                 }
676                 if (! need_another_client) {
677                         /*
678                          * We don't need this client object.  Recycle it.
679                          */
680                         if (client->newstate >= NS_CLIENTSTATE_INACTIVE)
681                                 client->newstate = NS_CLIENTSTATE_INACTIVE;
682                 }
683         }
684 }
685
686 void
687 ns_client_next(ns_client_t *client, isc_result_t result) {
688         int newstate;
689
690         REQUIRE(NS_CLIENT_VALID(client));
691         REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
692                 client->state == NS_CLIENTSTATE_READING);
693
694         CTRACE("next");
695
696         if (result != ISC_R_SUCCESS)
697                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
698                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
699                               "request failed: %s", isc_result_totext(result));
700
701         /*
702          * An error processing a TCP request may have left
703          * the connection out of sync.  To be safe, we always
704          * sever the connection when result != ISC_R_SUCCESS.
705          */
706         if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
707                 newstate = NS_CLIENTSTATE_READING;
708         else
709                 newstate = NS_CLIENTSTATE_READY;
710
711         if (client->newstate > newstate)
712                 client->newstate = newstate;
713         (void)exit_check(client);
714 }
715
716
717 static void
718 client_senddone(isc_task_t *task, isc_event_t *event) {
719         ns_client_t *client;
720         isc_socketevent_t *sevent = (isc_socketevent_t *) event;
721
722         REQUIRE(sevent != NULL);
723         REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
724         client = sevent->ev_arg;
725         REQUIRE(NS_CLIENT_VALID(client));
726         REQUIRE(task == client->task);
727         REQUIRE(sevent == client->sendevent);
728
729         UNUSED(task);
730
731         CTRACE("senddone");
732
733         if (sevent->result != ISC_R_SUCCESS)
734                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
735                               NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
736                               "error sending response: %s",
737                               isc_result_totext(sevent->result));
738
739         INSIST(client->nsends > 0);
740         client->nsends--;
741
742         if (client->tcpbuf != NULL) {
743                 INSIST(TCP_CLIENT(client));
744                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
745                 client->tcpbuf = NULL;
746         }
747
748         if (exit_check(client))
749                 return;
750
751         ns_client_next(client, ISC_R_SUCCESS);
752 }
753
754 /*%
755  * We only want to fail with ISC_R_NOSPACE when called from
756  * ns_client_sendraw() and not when called from ns_client_send(),
757  * tcpbuffer is NULL when called from ns_client_sendraw() and
758  * length != 0.  tcpbuffer != NULL when called from ns_client_send()
759  * and length == 0.
760  */
761
762 static isc_result_t
763 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
764                     isc_buffer_t *tcpbuffer, isc_uint32_t length,
765                     unsigned char *sendbuf, unsigned char **datap)
766 {
767         unsigned char *data;
768         isc_uint32_t bufsize;
769         isc_result_t result;
770
771         INSIST(datap != NULL);
772         INSIST((tcpbuffer == NULL && length != 0) ||
773                (tcpbuffer != NULL && length == 0));
774
775         if (TCP_CLIENT(client)) {
776                 INSIST(client->tcpbuf == NULL);
777                 if (length + 2 > TCP_BUFFER_SIZE) {
778                         result = ISC_R_NOSPACE;
779                         goto done;
780                 }
781                 client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
782                 if (client->tcpbuf == NULL) {
783                         result = ISC_R_NOMEMORY;
784                         goto done;
785                 }
786                 data = client->tcpbuf;
787                 if (tcpbuffer != NULL) {
788                         isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
789                         isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
790                 } else {
791                         isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
792                         INSIST(length <= 0xffff);
793                         isc_buffer_putuint16(buffer, (isc_uint16_t)length);
794                 }
795         } else {
796                 data = sendbuf;
797                 if (client->udpsize < SEND_BUFFER_SIZE)
798                         bufsize = client->udpsize;
799                 else
800                         bufsize = SEND_BUFFER_SIZE;
801                 if (length > bufsize) {
802                         result = ISC_R_NOSPACE;
803                         goto done;
804                 }
805                 isc_buffer_init(buffer, data, bufsize);
806         }
807         *datap = data;
808         result = ISC_R_SUCCESS;
809
810  done:
811         return (result);
812 }
813
814 static isc_result_t
815 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
816         struct in6_pktinfo *pktinfo;
817         isc_result_t result;
818         isc_region_t r;
819         isc_sockaddr_t *address;
820         isc_socket_t *socket;
821         isc_netaddr_t netaddr;
822         int match;
823         unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
824
825         if (TCP_CLIENT(client)) {
826                 socket = client->tcpsocket;
827                 address = NULL;
828         } else {
829                 socket = client->udpsocket;
830                 address = &client->peeraddr;
831
832                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
833                 if (ns_g_server->blackholeacl != NULL &&
834                     dns_acl_match(&netaddr, NULL,
835                                   ns_g_server->blackholeacl,
836                                   &ns_g_server->aclenv,
837                                   &match, NULL) == ISC_R_SUCCESS &&
838                     match > 0)
839                         return (DNS_R_BLACKHOLED);
840                 sockflags |= ISC_SOCKFLAG_NORETRY;
841         }
842
843         if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
844             (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
845                 pktinfo = &client->pktinfo;
846         else
847                 pktinfo = NULL;
848
849         isc_buffer_usedregion(buffer, &r);
850
851         CTRACE("sendto");
852
853         result = isc_socket_sendto2(socket, &r, client->task,
854                                     address, pktinfo,
855                                     client->sendevent, sockflags);
856         if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
857                 client->nsends++;
858                 if (result == ISC_R_SUCCESS)
859                         client_senddone(client->task,
860                                         (isc_event_t *)client->sendevent);
861                 result = ISC_R_SUCCESS;
862         }
863         return (result);
864 }
865
866 void
867 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
868         isc_result_t result;
869         unsigned char *data;
870         isc_buffer_t buffer;
871         isc_region_t r;
872         isc_region_t *mr;
873         unsigned char sendbuf[SEND_BUFFER_SIZE];
874
875         REQUIRE(NS_CLIENT_VALID(client));
876
877         CTRACE("sendraw");
878
879         mr = dns_message_getrawmessage(message);
880         if (mr == NULL) {
881                 result = ISC_R_UNEXPECTEDEND;
882                 goto done;
883         }
884
885         result = client_allocsendbuf(client, &buffer, NULL, mr->length,
886                                      sendbuf, &data);
887         if (result != ISC_R_SUCCESS)
888                 goto done;
889
890         /*
891          * Copy message to buffer and fixup id.
892          */
893         isc_buffer_availableregion(&buffer, &r);
894         result = isc_buffer_copyregion(&buffer, mr);
895         if (result != ISC_R_SUCCESS)
896                 goto done;
897         r.base[0] = (client->message->id >> 8) & 0xff;
898         r.base[1] = client->message->id & 0xff;
899
900         result = client_sendpkg(client, &buffer);
901         if (result == ISC_R_SUCCESS)
902                 return;
903
904  done:
905         if (client->tcpbuf != NULL) {
906                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
907                 client->tcpbuf = NULL;
908         }
909         ns_client_next(client, result);
910 }
911
912 void
913 ns_client_send(ns_client_t *client) {
914         isc_result_t result;
915         unsigned char *data;
916         isc_buffer_t buffer;
917         isc_buffer_t tcpbuffer;
918         isc_region_t r;
919         dns_compress_t cctx;
920         isc_boolean_t cleanup_cctx = ISC_FALSE;
921         unsigned char sendbuf[SEND_BUFFER_SIZE];
922         unsigned int dnssec_opts;
923         unsigned int preferred_glue;
924         isc_boolean_t opt_included = ISC_FALSE;
925
926         REQUIRE(NS_CLIENT_VALID(client));
927
928         CTRACE("send");
929
930         if ((client->attributes & NS_CLIENTATTR_RA) != 0)
931                 client->message->flags |= DNS_MESSAGEFLAG_RA;
932
933         if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
934                 dnssec_opts = 0;
935         else
936                 dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC;
937
938         preferred_glue = 0;
939         if (client->view != NULL) {
940                 if (client->view->preferred_glue == dns_rdatatype_a)
941                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
942                 else if (client->view->preferred_glue == dns_rdatatype_aaaa)
943                         preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
944         }
945
946         /*
947          * XXXRTH  The following doesn't deal with TCP buffer resizing.
948          */
949         result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
950                                      sendbuf, &data);
951         if (result != ISC_R_SUCCESS)
952                 goto done;
953
954         result = dns_compress_init(&cctx, -1, client->mctx);
955         if (result != ISC_R_SUCCESS)
956                 goto done;
957         cleanup_cctx = ISC_TRUE;
958
959         result = dns_message_renderbegin(client->message, &cctx, &buffer);
960         if (result != ISC_R_SUCCESS)
961                 goto done;
962
963         if (client->opt != NULL) {
964                 result = dns_message_setopt(client->message, client->opt);
965                 opt_included = ISC_TRUE;
966                 client->opt = NULL;
967                 if (result != ISC_R_SUCCESS)
968                         goto done;
969         }
970         result = dns_message_rendersection(client->message,
971                                            DNS_SECTION_QUESTION, 0);
972         if (result == ISC_R_NOSPACE) {
973                 client->message->flags |= DNS_MESSAGEFLAG_TC;
974                 goto renderend;
975         }
976         if (result != ISC_R_SUCCESS)
977                 goto done;
978         result = dns_message_rendersection(client->message,
979                                            DNS_SECTION_ANSWER,
980                                            DNS_MESSAGERENDER_PARTIAL |
981                                            dnssec_opts);
982         if (result == ISC_R_NOSPACE) {
983                 client->message->flags |= DNS_MESSAGEFLAG_TC;
984                 goto renderend;
985         }
986         if (result != ISC_R_SUCCESS)
987                 goto done;
988         result = dns_message_rendersection(client->message,
989                                            DNS_SECTION_AUTHORITY,
990                                            DNS_MESSAGERENDER_PARTIAL |
991                                            dnssec_opts);
992         if (result == ISC_R_NOSPACE) {
993                 client->message->flags |= DNS_MESSAGEFLAG_TC;
994                 goto renderend;
995         }
996         if (result != ISC_R_SUCCESS)
997                 goto done;
998         result = dns_message_rendersection(client->message,
999                                            DNS_SECTION_ADDITIONAL,
1000                                            preferred_glue | dnssec_opts);
1001         if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1002                 goto done;
1003  renderend:
1004         result = dns_message_renderend(client->message);
1005
1006         if (result != ISC_R_SUCCESS)
1007                 goto done;
1008
1009         if (cleanup_cctx) {
1010                 dns_compress_invalidate(&cctx);
1011                 cleanup_cctx = ISC_FALSE;
1012         }
1013
1014         if (TCP_CLIENT(client)) {
1015                 isc_buffer_usedregion(&buffer, &r);
1016                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1017                 isc_buffer_add(&tcpbuffer, r.length);
1018                 result = client_sendpkg(client, &tcpbuffer);
1019         } else
1020                 result = client_sendpkg(client, &buffer);
1021
1022         /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1023         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1024         if (opt_included) {
1025                 isc_stats_increment(ns_g_server->nsstats,
1026                                     dns_nsstatscounter_edns0out);
1027         }
1028         if (client->message->tsigkey != NULL) {
1029                 isc_stats_increment(ns_g_server->nsstats,
1030                                     dns_nsstatscounter_tsigout);
1031         }
1032         if (client->message->sig0key != NULL) {
1033                 isc_stats_increment(ns_g_server->nsstats,
1034                                     dns_nsstatscounter_sig0out);
1035         }
1036         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1037                 isc_stats_increment(ns_g_server->nsstats,
1038                                     dns_nsstatscounter_truncatedresp);
1039
1040         if (result == ISC_R_SUCCESS)
1041                 return;
1042
1043  done:
1044         if (client->tcpbuf != NULL) {
1045                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1046                 client->tcpbuf = NULL;
1047         }
1048
1049         if (cleanup_cctx)
1050                 dns_compress_invalidate(&cctx);
1051
1052         ns_client_next(client, result);
1053 }
1054
1055 #if NS_CLIENT_DROPPORT
1056 #define DROPPORT_NO             0
1057 #define DROPPORT_REQUEST        1
1058 #define DROPPORT_RESPONSE       2
1059 /*%
1060  * ns_client_dropport determines if certain requests / responses
1061  * should be dropped based on the port number.
1062  *
1063  * Returns:
1064  * \li  0:      Don't drop.
1065  * \li  1:      Drop request.
1066  * \li  2:      Drop (error) response.
1067  */
1068 static int
1069 ns_client_dropport(in_port_t port) {
1070         switch (port) {
1071         case 7: /* echo */
1072         case 13: /* daytime */
1073         case 19: /* chargen */
1074         case 37: /* time */
1075                 return (DROPPORT_REQUEST);
1076         case 464: /* kpasswd */
1077                 return (DROPPORT_RESPONSE);
1078         }
1079         return (DROPPORT_NO);
1080 }
1081 #endif
1082
1083 void
1084 ns_client_error(ns_client_t *client, isc_result_t result) {
1085         dns_rcode_t rcode;
1086         dns_message_t *message;
1087
1088         REQUIRE(NS_CLIENT_VALID(client));
1089
1090         CTRACE("error");
1091
1092         message = client->message;
1093         rcode = dns_result_torcode(result);
1094
1095 #if NS_CLIENT_DROPPORT
1096         /*
1097          * Don't send FORMERR to ports on the drop port list.
1098          */
1099         if (rcode == dns_rcode_formerr &&
1100             ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1101             DROPPORT_NO) {
1102                 char buf[64];
1103                 isc_buffer_t b;
1104
1105                 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1106                 if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1107                         isc_buffer_putstr(&b, "UNKNOWN RCODE");
1108                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1109                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1110                               "dropped error (%.*s) response: suspicious port",
1111                               (int)isc_buffer_usedlength(&b), buf);
1112                 ns_client_next(client, ISC_R_SUCCESS);
1113                 return;
1114         }
1115 #endif
1116
1117         /*
1118          * Message may be an in-progress reply that we had trouble
1119          * with, in which case QR will be set.  We need to clear QR before
1120          * calling dns_message_reply() to avoid triggering an assertion.
1121          */
1122         message->flags &= ~DNS_MESSAGEFLAG_QR;
1123         /*
1124          * AA and AD shouldn't be set.
1125          */
1126         message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1127         result = dns_message_reply(message, ISC_TRUE);
1128         if (result != ISC_R_SUCCESS) {
1129                 /*
1130                  * It could be that we've got a query with a good header,
1131                  * but a bad question section, so we try again with
1132                  * want_question_section set to ISC_FALSE.
1133                  */
1134                 result = dns_message_reply(message, ISC_FALSE);
1135                 if (result != ISC_R_SUCCESS) {
1136                         ns_client_next(client, result);
1137                         return;
1138                 }
1139         }
1140         message->rcode = rcode;
1141
1142         /*
1143          * FORMERR loop avoidance:  If we sent a FORMERR message
1144          * with the same ID to the same client less than two
1145          * seconds ago, assume that we are in an infinite error
1146          * packet dialog with a server for some protocol whose
1147          * error responses look enough like DNS queries to
1148          * elicit a FORMERR response.  Drop a packet to break
1149          * the loop.
1150          */
1151         if (rcode == dns_rcode_formerr) {
1152                 if (isc_sockaddr_equal(&client->peeraddr,
1153                                        &client->formerrcache.addr) &&
1154                     message->id == client->formerrcache.id &&
1155                     client->requesttime - client->formerrcache.time < 2) {
1156                         /* Drop packet. */
1157                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1158                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1159                                       "possible error packet loop, "
1160                                       "FORMERR dropped");
1161                         ns_client_next(client, result);
1162                         return;
1163                 }
1164                 client->formerrcache.addr = client->peeraddr;
1165                 client->formerrcache.time = client->requesttime;
1166                 client->formerrcache.id = message->id;
1167         }
1168         ns_client_send(client);
1169 }
1170
1171 static inline isc_result_t
1172 client_addopt(ns_client_t *client) {
1173         dns_rdataset_t *rdataset;
1174         dns_rdatalist_t *rdatalist;
1175         dns_rdata_t *rdata;
1176         isc_result_t result;
1177         dns_view_t *view;
1178         dns_resolver_t *resolver;
1179         isc_uint16_t udpsize;
1180
1181         REQUIRE(client->opt == NULL);   /* XXXRTH free old. */
1182
1183         rdatalist = NULL;
1184         result = dns_message_gettemprdatalist(client->message, &rdatalist);
1185         if (result != ISC_R_SUCCESS)
1186                 return (result);
1187         rdata = NULL;
1188         result = dns_message_gettemprdata(client->message, &rdata);
1189         if (result != ISC_R_SUCCESS)
1190                 return (result);
1191         rdataset = NULL;
1192         result = dns_message_gettemprdataset(client->message, &rdataset);
1193         if (result != ISC_R_SUCCESS)
1194                 return (result);
1195         dns_rdataset_init(rdataset);
1196
1197         rdatalist->type = dns_rdatatype_opt;
1198         rdatalist->covers = 0;
1199
1200         /*
1201          * Set the maximum UDP buffer size.
1202          */
1203         view = client->view;
1204         resolver = (view != NULL) ? view->resolver : NULL;
1205         if (resolver != NULL)
1206                 udpsize = dns_resolver_getudpsize(resolver);
1207         else
1208                 udpsize = ns_g_udpsize;
1209         rdatalist->rdclass = udpsize;
1210
1211         /*
1212          * Set EXTENDED-RCODE, VERSION and Z to 0.
1213          */
1214         rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1215
1216         /* Set EDNS options if applicable */
1217         if (client->attributes & NS_CLIENTATTR_WANTNSID &&
1218             (ns_g_server->server_id != NULL ||
1219              ns_g_server->server_usehostname)) {
1220                 /*
1221                  * Space required for NSID data:
1222                  *   2 bytes for opt code
1223                  * + 2 bytes for NSID length
1224                  * + NSID itself
1225                  */
1226                 char nsid[BUFSIZ], *nsidp;
1227                 isc_buffer_t *buffer = NULL;
1228
1229                 if (ns_g_server->server_usehostname) {
1230                         isc_result_t result;
1231                         result = ns_os_gethostname(nsid, sizeof(nsid));
1232                         if (result != ISC_R_SUCCESS) {
1233                                 goto no_nsid;
1234                         }
1235                         nsidp = nsid;
1236                 } else
1237                         nsidp = ns_g_server->server_id;
1238
1239                 rdata->length = strlen(nsidp) + 4;
1240                 result = isc_buffer_allocate(client->mctx, &buffer,
1241                                              rdata->length);
1242                 if (result != ISC_R_SUCCESS)
1243                         goto no_nsid;
1244
1245                 isc_buffer_putuint16(buffer, DNS_OPT_NSID);
1246                 isc_buffer_putuint16(buffer, strlen(nsidp));
1247                 isc_buffer_putstr(buffer, nsidp);
1248                 rdata->data = buffer->base;
1249                 dns_message_takebuffer(client->message, &buffer);
1250         } else {
1251 no_nsid:
1252                 rdata->data = NULL;
1253                 rdata->length = 0;
1254         }
1255
1256         rdata->rdclass = rdatalist->rdclass;
1257         rdata->type = rdatalist->type;
1258         rdata->flags = 0;
1259
1260         ISC_LIST_INIT(rdatalist->rdata);
1261         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1262         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1263                       == ISC_R_SUCCESS);
1264
1265         client->opt = rdataset;
1266
1267         return (ISC_R_SUCCESS);
1268 }
1269
1270 static inline isc_boolean_t
1271 allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1272         int match;
1273         isc_result_t result;
1274
1275         if (acl == NULL)
1276                 return (ISC_TRUE);
1277         result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1278                                &match, NULL);
1279         if (result == ISC_R_SUCCESS && match > 0)
1280                 return (ISC_TRUE);
1281         return (ISC_FALSE);
1282 }
1283
1284 /*
1285  * Callback to see if a non-recursive query coming from 'srcaddr' to
1286  * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1287  * delivered to 'myview'.
1288  *
1289  * We run this unlocked as both the view list and the interface list
1290  * are updated when the appropriate task has exclusivity.
1291  */
1292 isc_boolean_t
1293 ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1294                  isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1295                  dns_rdataclass_t rdclass, void *arg)
1296 {
1297         dns_view_t *view;
1298         dns_tsigkey_t *key = NULL;
1299         dns_name_t *tsig = NULL;
1300         isc_netaddr_t netsrc;
1301         isc_netaddr_t netdst;
1302
1303         UNUSED(arg);
1304
1305         /*
1306          * ns_g_server->interfacemgr is task exclusive locked.
1307          */
1308         if (ns_g_server->interfacemgr == NULL)
1309                 return (ISC_TRUE);
1310
1311         if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1312                 return (ISC_FALSE);
1313
1314         isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1315         isc_netaddr_fromsockaddr(&netdst, dstaddr);
1316
1317         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1318              view != NULL;
1319              view = ISC_LIST_NEXT(view, link)) {
1320
1321                 if (view->matchrecursiveonly)
1322                         continue;
1323
1324                 if (rdclass != view->rdclass)
1325                         continue;
1326
1327                 if (mykey != NULL) {
1328                         isc_boolean_t match;
1329                         isc_result_t result;
1330
1331                         result = dns_view_gettsig(view, &mykey->name, &key);
1332                         if (result != ISC_R_SUCCESS)
1333                                 continue;
1334                         match = dst_key_compare(mykey->key, key->key);
1335                         dns_tsigkey_detach(&key);
1336                         if (!match)
1337                                 continue;
1338                         tsig = dns_tsigkey_identity(mykey);
1339                 }
1340
1341                 if (allowed(&netsrc, tsig, view->matchclients) &&
1342                     allowed(&netdst, tsig, view->matchdestinations))
1343                         break;
1344         }
1345         return (ISC_TF(view == myview));
1346 }
1347
1348 /*
1349  * Handle an incoming request event from the socket (UDP case)
1350  * or tcpmsg (TCP case).
1351  */
1352 static void
1353 client_request(isc_task_t *task, isc_event_t *event) {
1354         ns_client_t *client;
1355         isc_socketevent_t *sevent;
1356         isc_result_t result;
1357         isc_result_t sigresult = ISC_R_SUCCESS;
1358         isc_buffer_t *buffer;
1359         isc_buffer_t tbuffer;
1360         dns_view_t *view;
1361         dns_rdataset_t *opt;
1362         dns_name_t *signame;
1363         isc_boolean_t ra;       /* Recursion available. */
1364         isc_netaddr_t netaddr;
1365         isc_netaddr_t destaddr;
1366         int match;
1367         dns_messageid_t id;
1368         unsigned int flags;
1369         isc_boolean_t notimp;
1370         dns_rdata_t rdata;
1371         isc_uint16_t optcode;
1372
1373         REQUIRE(event != NULL);
1374         client = event->ev_arg;
1375         REQUIRE(NS_CLIENT_VALID(client));
1376         REQUIRE(task == client->task);
1377
1378         INSIST(client->recursionquota == NULL);
1379
1380         INSIST(client->state ==
1381                TCP_CLIENT(client) ?
1382                NS_CLIENTSTATE_READING :
1383                NS_CLIENTSTATE_READY);
1384
1385         ns_client_requests++;
1386
1387         if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1388                 INSIST(!TCP_CLIENT(client));
1389                 sevent = (isc_socketevent_t *)event;
1390                 REQUIRE(sevent == client->recvevent);
1391                 isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1392                 isc_buffer_add(&tbuffer, sevent->n);
1393                 buffer = &tbuffer;
1394                 result = sevent->result;
1395                 if (result == ISC_R_SUCCESS) {
1396                         client->peeraddr = sevent->address;
1397                         client->peeraddr_valid = ISC_TRUE;
1398                 }
1399                 if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1400                         client->attributes |= NS_CLIENTATTR_PKTINFO;
1401                         client->pktinfo = sevent->pktinfo;
1402                 }
1403                 if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1404                         client->attributes |= NS_CLIENTATTR_MULTICAST;
1405                 client->nrecvs--;
1406         } else {
1407                 INSIST(TCP_CLIENT(client));
1408                 REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1409                 REQUIRE(event->ev_sender == &client->tcpmsg);
1410                 buffer = &client->tcpmsg.buffer;
1411                 result = client->tcpmsg.result;
1412                 INSIST(client->nreads == 1);
1413                 /*
1414                  * client->peeraddr was set when the connection was accepted.
1415                  */
1416                 client->nreads--;
1417         }
1418
1419         if (exit_check(client))
1420                 goto cleanup;
1421         client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1422
1423         isc_task_getcurrenttime(task, &client->requesttime);
1424         client->now = client->requesttime;
1425
1426         if (result != ISC_R_SUCCESS) {
1427                 if (TCP_CLIENT(client)) {
1428                         ns_client_next(client, result);
1429                 } else {
1430                         if  (result != ISC_R_CANCELED)
1431                                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1432                                               NS_LOGMODULE_CLIENT,
1433                                               ISC_LOG_ERROR,
1434                                               "UDP client handler shutting "
1435                                               "down due to fatal receive "
1436                                               "error: %s",
1437                                               isc_result_totext(result));
1438                         isc_task_shutdown(client->task);
1439                 }
1440                 goto cleanup;
1441         }
1442
1443         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1444
1445 #if NS_CLIENT_DROPPORT
1446         if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1447             DROPPORT_REQUEST) {
1448                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1449                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1450                               "dropped request: suspicious port");
1451                 ns_client_next(client, ISC_R_SUCCESS);
1452                 goto cleanup;
1453         }
1454 #endif
1455
1456         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1457                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1458                       "%s request",
1459                       TCP_CLIENT(client) ? "TCP" : "UDP");
1460
1461         /*
1462          * Check the blackhole ACL for UDP only, since TCP is done in
1463          * client_newconn.
1464          */
1465         if (!TCP_CLIENT(client)) {
1466
1467                 if (ns_g_server->blackholeacl != NULL &&
1468                     dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1469                                   &ns_g_server->aclenv,
1470                                   &match, NULL) == ISC_R_SUCCESS &&
1471                     match > 0)
1472                 {
1473                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1474                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1475                                       "blackholed UDP datagram");
1476                         ns_client_next(client, ISC_R_SUCCESS);
1477                         goto cleanup;
1478                 }
1479         }
1480
1481         /*
1482          * Silently drop multicast requests for the present.
1483          * XXXMPA look at when/if mDNS spec stabilizes.
1484          */
1485         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1486                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1487                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1488                               "dropping multicast request");
1489                 ns_client_next(client, DNS_R_REFUSED);
1490                 goto cleanup;
1491         }
1492
1493         result = dns_message_peekheader(buffer, &id, &flags);
1494         if (result != ISC_R_SUCCESS) {
1495                 /*
1496                  * There isn't enough header to determine whether
1497                  * this was a request or a response.  Drop it.
1498                  */
1499                 ns_client_next(client, result);
1500                 goto cleanup;
1501         }
1502
1503         /*
1504          * The client object handles requests, not responses.
1505          * If this is a UDP response, forward it to the dispatcher.
1506          * If it's a TCP response, discard it here.
1507          */
1508         if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1509                 if (TCP_CLIENT(client)) {
1510                         CTRACE("unexpected response");
1511                         ns_client_next(client, DNS_R_FORMERR);
1512                         goto cleanup;
1513                 } else {
1514                         dns_dispatch_importrecv(client->dispatch, event);
1515                         ns_client_next(client, ISC_R_SUCCESS);
1516                         goto cleanup;
1517                 }
1518         }
1519
1520         /*
1521          * Update some statistics counters.  Don't count responses.
1522          */
1523         if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1524                 isc_stats_increment(ns_g_server->nsstats,
1525                                     dns_nsstatscounter_requestv4);
1526         } else {
1527                 isc_stats_increment(ns_g_server->nsstats,
1528                                     dns_nsstatscounter_requestv6);
1529         }
1530         if (TCP_CLIENT(client))
1531                 isc_stats_increment(ns_g_server->nsstats,
1532                                     dns_nsstatscounter_tcp);
1533
1534         /*
1535          * It's a request.  Parse it.
1536          */
1537         result = dns_message_parse(client->message, buffer, 0);
1538         if (result != ISC_R_SUCCESS) {
1539                 /*
1540                  * Parsing the request failed.  Send a response
1541                  * (typically FORMERR or SERVFAIL).
1542                  */
1543                 ns_client_error(client, result);
1544                 goto cleanup;
1545         }
1546
1547         dns_opcodestats_increment(ns_g_server->opcodestats,
1548                                   client->message->opcode);
1549         switch (client->message->opcode) {
1550         case dns_opcode_query:
1551         case dns_opcode_update:
1552         case dns_opcode_notify:
1553                 notimp = ISC_FALSE;
1554                 break;
1555         case dns_opcode_iquery:
1556         default:
1557                 notimp = ISC_TRUE;
1558                 break;
1559         }
1560
1561         client->message->rcode = dns_rcode_noerror;
1562
1563         /* RFC1123 section 6.1.3.2 */
1564         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1565                 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1566
1567         /*
1568          * Deal with EDNS.
1569          */
1570         opt = dns_message_getopt(client->message);
1571         if (opt != NULL) {
1572                 /*
1573                  * Set the client's UDP buffer size.
1574                  */
1575                 client->udpsize = opt->rdclass;
1576
1577                 /*
1578                  * If the requested UDP buffer size is less than 512,
1579                  * ignore it and use 512.
1580                  */
1581                 if (client->udpsize < 512)
1582                         client->udpsize = 512;
1583
1584                 /*
1585                  * Get the flags out of the OPT record.
1586                  */
1587                 client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1588
1589                 /*
1590                  * Do we understand this version of EDNS?
1591                  *
1592                  * XXXRTH need library support for this!
1593                  */
1594                 client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1595                 if (client->ednsversion > 0) {
1596                         isc_stats_increment(ns_g_server->nsstats,
1597                                             dns_nsstatscounter_badednsver);
1598                         result = client_addopt(client);
1599                         if (result == ISC_R_SUCCESS)
1600                                 result = DNS_R_BADVERS;
1601                         ns_client_error(client, result);
1602                         goto cleanup;
1603                 }
1604
1605                 /* Check for NSID request */
1606                 result = dns_rdataset_first(opt);
1607                 if (result == ISC_R_SUCCESS) {
1608                         dns_rdata_init(&rdata);
1609                         dns_rdataset_current(opt, &rdata);
1610                         if (rdata.length >= 2) {
1611                                 isc_buffer_t nsidbuf;
1612                                 isc_buffer_init(&nsidbuf,
1613                                                 rdata.data, rdata.length);
1614                                 isc_buffer_add(&nsidbuf, rdata.length);
1615                                 optcode = isc_buffer_getuint16(&nsidbuf);
1616                                 if (optcode == DNS_OPT_NSID)
1617                                         client->attributes |=
1618                                                 NS_CLIENTATTR_WANTNSID;
1619                         }
1620                 }
1621
1622                 isc_stats_increment(ns_g_server->nsstats,
1623                                     dns_nsstatscounter_edns0in);
1624
1625                 /*
1626                  * Create an OPT for our reply.
1627                  */
1628                 result = client_addopt(client);
1629                 if (result != ISC_R_SUCCESS) {
1630                         ns_client_error(client, result);
1631                         goto cleanup;
1632                 }
1633         }
1634
1635         if (client->message->rdclass == 0) {
1636                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1637                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1638                               "message class could not be determined");
1639                 ns_client_dumpmessage(client,
1640                                       "message class could not be determined");
1641                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1642                 goto cleanup;
1643         }
1644
1645         /*
1646          * Determine the destination address.  If the receiving interface is
1647          * bound to a specific address, we simply use it regardless of the
1648          * address family.  All IPv4 queries should fall into this case.
1649          * Otherwise, if this is a TCP query, get the address from the
1650          * receiving socket (this needs a system call and can be heavy).
1651          * For IPv6 UDP queries, we get this from the pktinfo structure (if
1652          * supported).
1653          * If all the attempts fail (this can happen due to memory shortage,
1654          * etc), we regard this as an error for safety.
1655          */
1656         if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1657                 isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
1658         else {
1659                 result = ISC_R_FAILURE;
1660
1661                 if (TCP_CLIENT(client)) {
1662                         isc_sockaddr_t destsockaddr;
1663
1664                         result = isc_socket_getsockname(client->tcpsocket,
1665                                                         &destsockaddr);
1666                         if (result == ISC_R_SUCCESS)
1667                                 isc_netaddr_fromsockaddr(&destaddr,
1668                                                          &destsockaddr);
1669                 }
1670                 if (result != ISC_R_SUCCESS &&
1671                     client->interface->addr.type.sa.sa_family == AF_INET6 &&
1672                     (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1673                         isc_uint32_t zone = 0;
1674
1675                         /*
1676                          * XXXJT technically, we should convert the receiving
1677                          * interface ID to a proper scope zone ID.  However,
1678                          * due to the fact there is no standard API for this,
1679                          * we only handle link-local addresses and use the
1680                          * interface index as link ID.  Despite the assumption,
1681                          * it should cover most typical cases.
1682                          */
1683                         if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1684                                 zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex;
1685
1686                         isc_netaddr_fromin6(&destaddr,
1687                                             &client->pktinfo.ipi6_addr);
1688                         isc_netaddr_setzone(&destaddr, zone);
1689                         result = ISC_R_SUCCESS;
1690                 }
1691                 if (result != ISC_R_SUCCESS) {
1692                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1693                                          "failed to get request's "
1694                                          "destination: %s",
1695                                          isc_result_totext(result));
1696                         ns_client_next(client, ISC_R_SUCCESS);
1697                         goto cleanup;
1698                 }
1699         }
1700
1701         /*
1702          * Find a view that matches the client's source address.
1703          */
1704         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1705              view != NULL;
1706              view = ISC_LIST_NEXT(view, link)) {
1707                 if (client->message->rdclass == view->rdclass ||
1708                     client->message->rdclass == dns_rdataclass_any)
1709                 {
1710                         dns_name_t *tsig = NULL;
1711
1712                         sigresult = dns_message_rechecksig(client->message,
1713                                                            view);
1714                         if (sigresult == ISC_R_SUCCESS)
1715                                 tsig = dns_tsigkey_identity(client->message->tsigkey);
1716
1717                         if (allowed(&netaddr, tsig, view->matchclients) &&
1718                             allowed(&destaddr, tsig, view->matchdestinations) &&
1719                             !((client->message->flags & DNS_MESSAGEFLAG_RD)
1720                               == 0 && view->matchrecursiveonly))
1721                         {
1722                                 dns_view_attach(view, &client->view);
1723                                 break;
1724                         }
1725                 }
1726         }
1727
1728         if (view == NULL) {
1729                 char classname[DNS_RDATACLASS_FORMATSIZE];
1730
1731                 /*
1732                  * Do a dummy TSIG verification attempt so that the
1733                  * response will have a TSIG if the query did, as
1734                  * required by RFC2845.
1735                  */
1736                 isc_buffer_t b;
1737                 isc_region_t *r;
1738
1739                 dns_message_resetsig(client->message);
1740
1741                 r = dns_message_getrawmessage(client->message);
1742                 isc_buffer_init(&b, r->base, r->length);
1743                 isc_buffer_add(&b, r->length);
1744                 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
1745
1746                 dns_rdataclass_format(client->message->rdclass, classname,
1747                                       sizeof(classname));
1748                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1749                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1750                               "no matching view in class '%s'", classname);
1751                 ns_client_dumpmessage(client, "no matching view in class");
1752                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1753                 goto cleanup;
1754         }
1755
1756         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1757                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1758                       "using view '%s'", view->name);
1759
1760         /*
1761          * Check for a signature.  We log bad signatures regardless of
1762          * whether they ultimately cause the request to be rejected or
1763          * not.  We do not log the lack of a signature unless we are
1764          * debugging.
1765          */
1766         client->signer = NULL;
1767         dns_name_init(&client->signername, NULL);
1768         result = dns_message_signer(client->message, &client->signername);
1769         if (result != ISC_R_NOTFOUND) {
1770                 signame = NULL;
1771                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1772                         isc_stats_increment(ns_g_server->nsstats,
1773                                             dns_nsstatscounter_tsigin);
1774                 } else {
1775                         isc_stats_increment(ns_g_server->nsstats,
1776                                             dns_nsstatscounter_sig0in);
1777                 }
1778
1779         }
1780         if (result == ISC_R_SUCCESS) {
1781                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1782                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1783                               "request has valid signature");
1784                 client->signer = &client->signername;
1785         } else if (result == ISC_R_NOTFOUND) {
1786                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1787                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1788                               "request is not signed");
1789         } else if (result == DNS_R_NOIDENTITY) {
1790                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1791                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1792                               "request is signed by a nonauthoritative key");
1793         } else {
1794                 char tsigrcode[64];
1795                 isc_buffer_t b;
1796                 dns_rcode_t status;
1797                 isc_result_t tresult;
1798
1799                 /* There is a signature, but it is bad. */
1800                 isc_stats_increment(ns_g_server->nsstats,
1801                                     dns_nsstatscounter_invalidsig);
1802                 signame = NULL;
1803                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1804                         char namebuf[DNS_NAME_FORMATSIZE];
1805                         char cnamebuf[DNS_NAME_FORMATSIZE];
1806                         dns_name_format(signame, namebuf, sizeof(namebuf));
1807                         status = client->message->tsigstatus;
1808                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1809                         tresult = dns_tsigrcode_totext(status, &b);
1810                         INSIST(tresult == ISC_R_SUCCESS);
1811                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1812                         if (client->message->tsigkey->generated) {
1813                                 dns_name_format(client->message->tsigkey->creator,
1814                                                 cnamebuf, sizeof(cnamebuf));
1815                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1816                                               NS_LOGMODULE_CLIENT,
1817                                               ISC_LOG_ERROR,
1818                                               "request has invalid signature: "
1819                                               "TSIG %s (%s): %s (%s)", namebuf,
1820                                               cnamebuf,
1821                                               isc_result_totext(result),
1822                                               tsigrcode);
1823                         } else {
1824                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1825                                               NS_LOGMODULE_CLIENT,
1826                                               ISC_LOG_ERROR,
1827                                               "request has invalid signature: "
1828                                               "TSIG %s: %s (%s)", namebuf,
1829                                               isc_result_totext(result),
1830                                               tsigrcode);
1831                         }
1832                 } else {
1833                         status = client->message->sig0status;
1834                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1835                         tresult = dns_tsigrcode_totext(status, &b);
1836                         INSIST(tresult == ISC_R_SUCCESS);
1837                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1838                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1839                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1840                                       "request has invalid signature: %s (%s)",
1841                                       isc_result_totext(result), tsigrcode);
1842                 }
1843                 /*
1844                  * Accept update messages signed by unknown keys so that
1845                  * update forwarding works transparently through slaves
1846                  * that don't have all the same keys as the master.
1847                  */
1848                 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1849                       client->message->opcode == dns_opcode_update)) {
1850                         ns_client_error(client, sigresult);
1851                         goto cleanup;
1852                 }
1853         }
1854
1855         /*
1856          * Decide whether recursive service is available to this client.
1857          * We do this here rather than in the query code so that we can
1858          * set the RA bit correctly on all kinds of responses, not just
1859          * responses to ordinary queries.  Note if you can't query the
1860          * cache there is no point in setting RA.
1861          */
1862         ra = ISC_FALSE;
1863         if (client->view->resolver != NULL &&
1864             client->view->recursion == ISC_TRUE &&
1865             ns_client_checkaclsilent(client, NULL,
1866                                      client->view->recursionacl,
1867                                      ISC_TRUE) == ISC_R_SUCCESS &&
1868             ns_client_checkaclsilent(client, NULL,
1869                                      client->view->cacheacl,
1870                                      ISC_TRUE) == ISC_R_SUCCESS &&
1871             ns_client_checkaclsilent(client, &client->interface->addr,
1872                                      client->view->recursiononacl,
1873                                      ISC_TRUE) == ISC_R_SUCCESS &&
1874             ns_client_checkaclsilent(client, &client->interface->addr,
1875                                      client->view->cacheonacl,
1876                                      ISC_TRUE) == ISC_R_SUCCESS)
1877                 ra = ISC_TRUE;
1878
1879         if (ra == ISC_TRUE)
1880                 client->attributes |= NS_CLIENTATTR_RA;
1881
1882         ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1883                       ISC_LOG_DEBUG(3), ra ? "recursion available" :
1884                                              "recursion not available");
1885
1886         /*
1887          * Adjust maximum UDP response size for this client.
1888          */
1889         if (client->udpsize > 512) {
1890                 dns_peer_t *peer = NULL;
1891                 isc_uint16_t udpsize = view->maxudp;
1892                 (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1893                 if (peer != NULL)
1894                         dns_peer_getmaxudp(peer, &udpsize);
1895                 if (client->udpsize > udpsize)
1896                         client->udpsize = udpsize;
1897         }
1898
1899         /*
1900          * Dispatch the request.
1901          */
1902         switch (client->message->opcode) {
1903         case dns_opcode_query:
1904                 CTRACE("query");
1905                 ns_query_start(client);
1906                 break;
1907         case dns_opcode_update:
1908                 CTRACE("update");
1909                 ns_client_settimeout(client, 60);
1910                 ns_update_start(client, sigresult);
1911                 break;
1912         case dns_opcode_notify:
1913                 CTRACE("notify");
1914                 ns_client_settimeout(client, 60);
1915                 ns_notify_start(client);
1916                 break;
1917         case dns_opcode_iquery:
1918                 CTRACE("iquery");
1919                 ns_client_error(client, DNS_R_NOTIMP);
1920                 break;
1921         default:
1922                 CTRACE("unknown opcode");
1923                 ns_client_error(client, DNS_R_NOTIMP);
1924         }
1925
1926  cleanup:
1927         return;
1928 }
1929
1930 static void
1931 client_timeout(isc_task_t *task, isc_event_t *event) {
1932         ns_client_t *client;
1933
1934         REQUIRE(event != NULL);
1935         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1936                 event->ev_type == ISC_TIMEREVENT_IDLE);
1937         client = event->ev_arg;
1938         REQUIRE(NS_CLIENT_VALID(client));
1939         REQUIRE(task == client->task);
1940         REQUIRE(client->timer != NULL);
1941
1942         UNUSED(task);
1943
1944         CTRACE("timeout");
1945
1946         isc_event_free(&event);
1947
1948         if (client->shutdown != NULL) {
1949                 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1950                 client->shutdown = NULL;
1951                 client->shutdown_arg = NULL;
1952         }
1953
1954         if (client->newstate > NS_CLIENTSTATE_READY)
1955                 client->newstate = NS_CLIENTSTATE_READY;
1956         (void)exit_check(client);
1957 }
1958
1959 static isc_result_t
1960 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
1961         isc_mem_t *clientmctx;
1962         isc_result_t result;
1963
1964         /*
1965          * Caller must be holding the manager lock.
1966          */
1967         if (ns_g_clienttest) {
1968                 result = isc_mem_create(0, 0, mctxp);
1969                 if (result == ISC_R_SUCCESS)
1970                         isc_mem_setname(*mctxp, "client", NULL);
1971                 return (result);
1972         }
1973 #if NMCTXS > 0
1974         INSIST(manager->nextmctx < NMCTXS);
1975         clientmctx = manager->mctxpool[manager->nextmctx];
1976         if (clientmctx == NULL) {
1977                 result = isc_mem_create(0, 0, &clientmctx);
1978                 if (result != ISC_R_SUCCESS)
1979                         return (result);
1980                 isc_mem_setname(clientmctx, "client", NULL);
1981
1982                 manager->mctxpool[manager->nextmctx] = clientmctx;
1983         }
1984         manager->nextmctx++;
1985         if (manager->nextmctx == NMCTXS)
1986                 manager->nextmctx = 0;
1987 #else
1988         clientmctx = manager->mctx;
1989 #endif
1990
1991         isc_mem_attach(clientmctx, mctxp);
1992
1993         return (ISC_R_SUCCESS);
1994 }
1995
1996 static isc_result_t
1997 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
1998         ns_client_t *client;
1999         isc_result_t result;
2000         isc_mem_t *mctx = NULL;
2001
2002         /*
2003          * Caller must be holding the manager lock.
2004          *
2005          * Note: creating a client does not add the client to the
2006          * manager's client list or set the client's manager pointer.
2007          * The caller is responsible for that.
2008          */
2009
2010         REQUIRE(clientp != NULL && *clientp == NULL);
2011
2012         result = get_clientmctx(manager, &mctx);
2013         if (result != ISC_R_SUCCESS)
2014                 return (result);
2015
2016         client = isc_mem_get(mctx, sizeof(*client));
2017         if (client == NULL) {
2018                 isc_mem_detach(&mctx);
2019                 return (ISC_R_NOMEMORY);
2020         }
2021         client->mctx = mctx;
2022
2023         client->task = NULL;
2024         result = isc_task_create(manager->taskmgr, 0, &client->task);
2025         if (result != ISC_R_SUCCESS)
2026                 goto cleanup_client;
2027         isc_task_setname(client->task, "client", client);
2028
2029         client->timer = NULL;
2030         result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2031                                   NULL, NULL, client->task, client_timeout,
2032                                   client, &client->timer);
2033         if (result != ISC_R_SUCCESS)
2034                 goto cleanup_task;
2035         client->timerset = ISC_FALSE;
2036
2037         client->message = NULL;
2038         result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2039                                     &client->message);
2040         if (result != ISC_R_SUCCESS)
2041                 goto cleanup_timer;
2042
2043         /* XXXRTH  Hardwired constants */
2044
2045         client->sendevent = (isc_socketevent_t *)
2046                             isc_event_allocate(client->mctx, client,
2047                                                ISC_SOCKEVENT_SENDDONE,
2048                                                client_senddone, client,
2049                                                sizeof(isc_socketevent_t));
2050         if (client->sendevent == NULL) {
2051                 result = ISC_R_NOMEMORY;
2052                 goto cleanup_message;
2053         }
2054
2055         client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2056         if  (client->recvbuf == NULL) {
2057                 result = ISC_R_NOMEMORY;
2058                 goto cleanup_sendevent;
2059         }
2060
2061         client->recvevent = (isc_socketevent_t *)
2062                             isc_event_allocate(client->mctx, client,
2063                                                ISC_SOCKEVENT_RECVDONE,
2064                                                client_request, client,
2065                                                sizeof(isc_socketevent_t));
2066         if (client->recvevent == NULL) {
2067                 result = ISC_R_NOMEMORY;
2068                 goto cleanup_recvbuf;
2069         }
2070
2071         client->magic = NS_CLIENT_MAGIC;
2072         client->manager = NULL;
2073         client->state = NS_CLIENTSTATE_INACTIVE;
2074         client->newstate = NS_CLIENTSTATE_MAX;
2075         client->naccepts = 0;
2076         client->nreads = 0;
2077         client->nsends = 0;
2078         client->nrecvs = 0;
2079         client->nupdates = 0;
2080         client->nctls = 0;
2081         client->references = 0;
2082         client->attributes = 0;
2083         client->view = NULL;
2084         client->dispatch = NULL;
2085         client->udpsocket = NULL;
2086         client->tcplistener = NULL;
2087         client->tcpsocket = NULL;
2088         client->tcpmsg_valid = ISC_FALSE;
2089         client->tcpbuf = NULL;
2090         client->opt = NULL;
2091         client->udpsize = 512;
2092         client->extflags = 0;
2093         client->ednsversion = -1;
2094         client->next = NULL;
2095         client->shutdown = NULL;
2096         client->shutdown_arg = NULL;
2097         client->signer = NULL;
2098         dns_name_init(&client->signername, NULL);
2099         client->mortal = ISC_FALSE;
2100         client->tcpquota = NULL;
2101         client->recursionquota = NULL;
2102         client->interface = NULL;
2103         client->peeraddr_valid = ISC_FALSE;
2104         ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2105                        NS_EVENT_CLIENTCONTROL, client_start, client, client,
2106                        NULL, NULL);
2107         /*
2108          * Initialize FORMERR cache to sentinel value that will not match
2109          * any actual FORMERR response.
2110          */
2111         isc_sockaddr_any(&client->formerrcache.addr);
2112         client->formerrcache.time = 0;
2113         client->formerrcache.id = 0;
2114         ISC_LINK_INIT(client, link);
2115         client->list = NULL;
2116
2117         /*
2118          * We call the init routines for the various kinds of client here,
2119          * after we have created an otherwise valid client, because some
2120          * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2121          */
2122         result = ns_query_init(client);
2123         if (result != ISC_R_SUCCESS)
2124                 goto cleanup_recvevent;
2125
2126         result = isc_task_onshutdown(client->task, client_shutdown, client);
2127         if (result != ISC_R_SUCCESS)
2128                 goto cleanup_query;
2129
2130         client->needshutdown = ns_g_clienttest;
2131
2132         CTRACE("create");
2133
2134         *clientp = client;
2135
2136         return (ISC_R_SUCCESS);
2137
2138  cleanup_query:
2139         ns_query_free(client);
2140
2141  cleanup_recvevent:
2142         isc_event_free((isc_event_t **)&client->recvevent);
2143
2144  cleanup_recvbuf:
2145         isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2146
2147  cleanup_sendevent:
2148         isc_event_free((isc_event_t **)&client->sendevent);
2149
2150         client->magic = 0;
2151
2152  cleanup_message:
2153         dns_message_destroy(&client->message);
2154
2155  cleanup_timer:
2156         isc_timer_detach(&client->timer);
2157
2158  cleanup_task:
2159         isc_task_detach(&client->task);
2160
2161  cleanup_client:
2162         isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2163
2164         return (result);
2165 }
2166
2167 static void
2168 client_read(ns_client_t *client) {
2169         isc_result_t result;
2170
2171         CTRACE("read");
2172
2173         result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2174                                         client_request, client);
2175         if (result != ISC_R_SUCCESS)
2176                 goto fail;
2177
2178         /*
2179          * Set a timeout to limit the amount of time we will wait
2180          * for a request on this TCP connection.
2181          */
2182         ns_client_settimeout(client, 30);
2183
2184         client->state = client->newstate = NS_CLIENTSTATE_READING;
2185         INSIST(client->nreads == 0);
2186         INSIST(client->recursionquota == NULL);
2187         client->nreads++;
2188
2189         return;
2190  fail:
2191         ns_client_next(client, result);
2192 }
2193
2194 static void
2195 client_newconn(isc_task_t *task, isc_event_t *event) {
2196         ns_client_t *client = event->ev_arg;
2197         isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2198         isc_result_t result;
2199
2200         REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2201         REQUIRE(NS_CLIENT_VALID(client));
2202         REQUIRE(client->task == task);
2203
2204         UNUSED(task);
2205
2206         INSIST(client->state == NS_CLIENTSTATE_READY);
2207
2208         INSIST(client->naccepts == 1);
2209         client->naccepts--;
2210
2211         LOCK(&client->interface->lock);
2212         INSIST(client->interface->ntcpcurrent > 0);
2213         client->interface->ntcpcurrent--;
2214         UNLOCK(&client->interface->lock);
2215
2216         /*
2217          * We must take ownership of the new socket before the exit
2218          * check to make sure it gets destroyed if we decide to exit.
2219          */
2220         if (nevent->result == ISC_R_SUCCESS) {
2221                 client->tcpsocket = nevent->newsocket;
2222                 isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2223                 client->state = NS_CLIENTSTATE_READING;
2224                 INSIST(client->recursionquota == NULL);
2225
2226                 (void)isc_socket_getpeername(client->tcpsocket,
2227                                              &client->peeraddr);
2228                 client->peeraddr_valid = ISC_TRUE;
2229                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2230                            NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2231                            "new TCP connection");
2232         } else {
2233                 /*
2234                  * XXXRTH  What should we do?  We're trying to accept but
2235                  *         it didn't work.  If we just give up, then TCP
2236                  *         service may eventually stop.
2237                  *
2238                  *         For now, we just go idle.
2239                  *
2240                  *         Going idle is probably the right thing if the
2241                  *         I/O was canceled.
2242                  */
2243                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2244                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2245                               "accept failed: %s",
2246                               isc_result_totext(nevent->result));
2247         }
2248
2249         if (exit_check(client))
2250                 goto freeevent;
2251
2252         if (nevent->result == ISC_R_SUCCESS) {
2253                 int match;
2254                 isc_netaddr_t netaddr;
2255
2256                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2257
2258                 if (ns_g_server->blackholeacl != NULL &&
2259                     dns_acl_match(&netaddr, NULL,
2260                                   ns_g_server->blackholeacl,
2261                                   &ns_g_server->aclenv,
2262                                   &match, NULL) == ISC_R_SUCCESS &&
2263                     match > 0)
2264                 {
2265                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2266                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2267                                       "blackholed connection attempt");
2268                         client->newstate = NS_CLIENTSTATE_READY;
2269                         (void)exit_check(client);
2270                         goto freeevent;
2271                 }
2272
2273                 INSIST(client->tcpmsg_valid == ISC_FALSE);
2274                 dns_tcpmsg_init(client->mctx, client->tcpsocket,
2275                                 &client->tcpmsg);
2276                 client->tcpmsg_valid = ISC_TRUE;
2277
2278                 /*
2279                  * Let a new client take our place immediately, before
2280                  * we wait for a request packet.  If we don't,
2281                  * telnetting to port 53 (once per CPU) will
2282                  * deny service to legitimate TCP clients.
2283                  */
2284                 result = isc_quota_attach(&ns_g_server->tcpquota,
2285                                           &client->tcpquota);
2286                 if (result == ISC_R_SUCCESS)
2287                         result = ns_client_replace(client);
2288                 if (result != ISC_R_SUCCESS) {
2289                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2290                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2291                                       "no more TCP clients: %s",
2292                                       isc_result_totext(result));
2293                 }
2294
2295                 client_read(client);
2296         }
2297
2298  freeevent:
2299         isc_event_free(&event);
2300 }
2301
2302 static void
2303 client_accept(ns_client_t *client) {
2304         isc_result_t result;
2305
2306         CTRACE("accept");
2307
2308         result = isc_socket_accept(client->tcplistener, client->task,
2309                                    client_newconn, client);
2310         if (result != ISC_R_SUCCESS) {
2311                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2312                                  "isc_socket_accept() failed: %s",
2313                                  isc_result_totext(result));
2314                 /*
2315                  * XXXRTH  What should we do?  We're trying to accept but
2316                  *         it didn't work.  If we just give up, then TCP
2317                  *         service may eventually stop.
2318                  *
2319                  *         For now, we just go idle.
2320                  */
2321                 return;
2322         }
2323         INSIST(client->naccepts == 0);
2324         client->naccepts++;
2325         LOCK(&client->interface->lock);
2326         client->interface->ntcpcurrent++;
2327         UNLOCK(&client->interface->lock);
2328 }
2329
2330 static void
2331 client_udprecv(ns_client_t *client) {
2332         isc_result_t result;
2333         isc_region_t r;
2334
2335         CTRACE("udprecv");
2336
2337         r.base = client->recvbuf;
2338         r.length = RECV_BUFFER_SIZE;
2339         result = isc_socket_recv2(client->udpsocket, &r, 1,
2340                                   client->task, client->recvevent, 0);
2341         if (result != ISC_R_SUCCESS) {
2342                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2343                                  "isc_socket_recv2() failed: %s",
2344                                  isc_result_totext(result));
2345                 /*
2346                  * This cannot happen in the current implementation, since
2347                  * isc_socket_recv2() cannot fail if flags == 0.
2348                  *
2349                  * If this does fail, we just go idle.
2350                  */
2351                 return;
2352         }
2353         INSIST(client->nrecvs == 0);
2354         client->nrecvs++;
2355 }
2356
2357 void
2358 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2359         REQUIRE(NS_CLIENT_VALID(source));
2360         REQUIRE(targetp != NULL && *targetp == NULL);
2361
2362         source->references++;
2363         ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2364                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2365                       "ns_client_attach: ref = %d", source->references);
2366         *targetp = source;
2367 }
2368
2369 void
2370 ns_client_detach(ns_client_t **clientp) {
2371         ns_client_t *client = *clientp;
2372
2373         client->references--;
2374         INSIST(client->references >= 0);
2375         *clientp = NULL;
2376         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2377                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2378                       "ns_client_detach: ref = %d", client->references);
2379         (void)exit_check(client);
2380 }
2381
2382 isc_boolean_t
2383 ns_client_shuttingdown(ns_client_t *client) {
2384         return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2385 }
2386
2387 isc_result_t
2388 ns_client_replace(ns_client_t *client) {
2389         isc_result_t result;
2390
2391         CTRACE("replace");
2392
2393         result = ns_clientmgr_createclients(client->manager,
2394                                             1, client->interface,
2395                                             (TCP_CLIENT(client) ?
2396                                              ISC_TRUE : ISC_FALSE));
2397         if (result != ISC_R_SUCCESS)
2398                 return (result);
2399
2400         /*
2401          * The responsibility for listening for new requests is hereby
2402          * transferred to the new client.  Therefore, the old client
2403          * should refrain from listening for any more requests.
2404          */
2405         client->mortal = ISC_TRUE;
2406
2407         return (ISC_R_SUCCESS);
2408 }
2409
2410 /***
2411  *** Client Manager
2412  ***/
2413
2414 static void
2415 clientmgr_destroy(ns_clientmgr_t *manager) {
2416 #if NMCTXS > 0
2417         int i;
2418 #endif
2419
2420         REQUIRE(ISC_LIST_EMPTY(manager->active));
2421         REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2422         REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2423
2424         MTRACE("clientmgr_destroy");
2425
2426 #if NMCTXS > 0
2427         for (i = 0; i < NMCTXS; i++) {
2428                 if (manager->mctxpool[i] != NULL)
2429                         isc_mem_detach(&manager->mctxpool[i]);
2430         }
2431 #endif
2432
2433         DESTROYLOCK(&manager->lock);
2434         manager->magic = 0;
2435         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2436 }
2437
2438 isc_result_t
2439 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2440                     isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2441 {
2442         ns_clientmgr_t *manager;
2443         isc_result_t result;
2444 #if NMCTXS > 0
2445         int i;
2446 #endif
2447
2448         manager = isc_mem_get(mctx, sizeof(*manager));
2449         if (manager == NULL)
2450                 return (ISC_R_NOMEMORY);
2451
2452         result = isc_mutex_init(&manager->lock);
2453         if (result != ISC_R_SUCCESS)
2454                 goto cleanup_manager;
2455
2456         manager->mctx = mctx;
2457         manager->taskmgr = taskmgr;
2458         manager->timermgr = timermgr;
2459         manager->exiting = ISC_FALSE;
2460         ISC_LIST_INIT(manager->active);
2461         ISC_LIST_INIT(manager->inactive);
2462         ISC_LIST_INIT(manager->recursing);
2463 #if NMCTXS > 0
2464         manager->nextmctx = 0;
2465         for (i = 0; i < NMCTXS; i++)
2466                 manager->mctxpool[i] = NULL; /* will be created on-demand */
2467 #endif
2468         manager->magic = MANAGER_MAGIC;
2469
2470         MTRACE("create");
2471
2472         *managerp = manager;
2473
2474         return (ISC_R_SUCCESS);
2475
2476  cleanup_manager:
2477         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2478
2479         return (result);
2480 }
2481
2482 void
2483 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2484         ns_clientmgr_t *manager;
2485         ns_client_t *client;
2486         isc_boolean_t need_destroy = ISC_FALSE;
2487
2488         REQUIRE(managerp != NULL);
2489         manager = *managerp;
2490         REQUIRE(VALID_MANAGER(manager));
2491
2492         MTRACE("destroy");
2493
2494         LOCK(&manager->lock);
2495
2496         manager->exiting = ISC_TRUE;
2497
2498         for (client = ISC_LIST_HEAD(manager->recursing);
2499              client != NULL;
2500              client = ISC_LIST_NEXT(client, link))
2501                 isc_task_shutdown(client->task);
2502
2503         for (client = ISC_LIST_HEAD(manager->active);
2504              client != NULL;
2505              client = ISC_LIST_NEXT(client, link))
2506                 isc_task_shutdown(client->task);
2507
2508         for (client = ISC_LIST_HEAD(manager->inactive);
2509              client != NULL;
2510              client = ISC_LIST_NEXT(client, link))
2511                 isc_task_shutdown(client->task);
2512
2513         if (ISC_LIST_EMPTY(manager->active) &&
2514             ISC_LIST_EMPTY(manager->inactive) &&
2515             ISC_LIST_EMPTY(manager->recursing))
2516                 need_destroy = ISC_TRUE;
2517
2518         UNLOCK(&manager->lock);
2519
2520         if (need_destroy)
2521                 clientmgr_destroy(manager);
2522
2523         *managerp = NULL;
2524 }
2525
2526 isc_result_t
2527 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2528                            ns_interface_t *ifp, isc_boolean_t tcp)
2529 {
2530         isc_result_t result = ISC_R_SUCCESS;
2531         unsigned int i;
2532         ns_client_t *client;
2533
2534         REQUIRE(VALID_MANAGER(manager));
2535         REQUIRE(n > 0);
2536
2537         MTRACE("createclients");
2538
2539         /*
2540          * We MUST lock the manager lock for the entire client creation
2541          * process.  If we didn't do this, then a client could get a
2542          * shutdown event and disappear out from under us.
2543          */
2544
2545         LOCK(&manager->lock);
2546
2547         for (i = 0; i < n; i++) {
2548                 isc_event_t *ev;
2549                 /*
2550                  * Allocate a client.  First try to get a recycled one;
2551                  * if that fails, make a new one.
2552                  */
2553                 client = NULL;
2554                 if (!ns_g_clienttest)
2555                         client = ISC_LIST_HEAD(manager->inactive);
2556                 if (client != NULL) {
2557                         MTRACE("recycle");
2558                         ISC_LIST_UNLINK(manager->inactive, client, link);
2559                         client->list = NULL;
2560                 } else {
2561                         MTRACE("create new");
2562                         result = client_create(manager, &client);
2563                         if (result != ISC_R_SUCCESS)
2564                                 break;
2565                 }
2566
2567                 ns_interface_attach(ifp, &client->interface);
2568                 client->state = NS_CLIENTSTATE_READY;
2569                 INSIST(client->recursionquota == NULL);
2570
2571                 if (tcp) {
2572                         client->attributes |= NS_CLIENTATTR_TCP;
2573                         isc_socket_attach(ifp->tcpsocket,
2574                                           &client->tcplistener);
2575                 } else {
2576                         isc_socket_t *sock;
2577
2578                         dns_dispatch_attach(ifp->udpdispatch,
2579                                             &client->dispatch);
2580                         sock = dns_dispatch_getsocket(client->dispatch);
2581                         isc_socket_attach(sock, &client->udpsocket);
2582                 }
2583                 client->manager = manager;
2584                 ISC_LIST_APPEND(manager->active, client, link);
2585                 client->list = &manager->active;
2586
2587                 INSIST(client->nctls == 0);
2588                 client->nctls++;
2589                 ev = &client->ctlevent;
2590                 isc_task_send(client->task, &ev);
2591         }
2592         if (i != 0) {
2593                 /*
2594                  * We managed to create at least one client, so we
2595                  * declare victory.
2596                  */
2597                 result = ISC_R_SUCCESS;
2598         }
2599
2600         UNLOCK(&manager->lock);
2601
2602         return (result);
2603 }
2604
2605 isc_sockaddr_t *
2606 ns_client_getsockaddr(ns_client_t *client) {
2607         return (&client->peeraddr);
2608 }
2609
2610 isc_result_t
2611 ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr,
2612                          dns_acl_t *acl, isc_boolean_t default_allow)
2613 {
2614         isc_result_t result;
2615         int match;
2616         isc_netaddr_t netaddr;
2617
2618         if (acl == NULL) {
2619                 if (default_allow)
2620                         goto allow;
2621                 else
2622                         goto deny;
2623         }
2624
2625
2626         if (sockaddr == NULL)
2627                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2628         else
2629                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2630
2631         result = dns_acl_match(&netaddr, client->signer, acl,
2632                                &ns_g_server->aclenv,
2633                                &match, NULL);
2634
2635         if (result != ISC_R_SUCCESS)
2636                 goto deny; /* Internal error, already logged. */
2637         if (match > 0)
2638                 goto allow;
2639         goto deny; /* Negative match or no match. */
2640
2641  allow:
2642         return (ISC_R_SUCCESS);
2643
2644  deny:
2645         return (DNS_R_REFUSED);
2646 }
2647
2648 isc_result_t
2649 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2650                    const char *opname, dns_acl_t *acl,
2651                    isc_boolean_t default_allow, int log_level)
2652 {
2653         isc_result_t result =
2654                 ns_client_checkaclsilent(client, sockaddr, acl, default_allow);
2655
2656         if (result == ISC_R_SUCCESS)
2657                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2658                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2659                               "%s approved", opname);
2660         else
2661                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2662                               NS_LOGMODULE_CLIENT,
2663                               log_level, "%s denied", opname);
2664         return (result);
2665 }
2666
2667 static void
2668 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2669         if (client->peeraddr_valid)
2670                 isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2671         else
2672                 snprintf(peerbuf, len, "@%p", client);
2673 }
2674
2675 void
2676 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2677                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2678 {
2679         char msgbuf[2048];
2680         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2681         const char *name = "";
2682         const char *sep = "";
2683
2684         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2685         ns_client_name(client, peerbuf, sizeof(peerbuf));
2686         if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2687             strcmp(client->view->name, "_default") != 0) {
2688                 name = client->view->name;
2689                 sep = ": view ";
2690         }
2691
2692         isc_log_write(ns_g_lctx, category, module, level,
2693                       "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2694 }
2695
2696 void
2697 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2698            isc_logmodule_t *module, int level, const char *fmt, ...)
2699 {
2700         va_list ap;
2701
2702         if (! isc_log_wouldlog(ns_g_lctx, level))
2703                 return;
2704
2705         va_start(ap, fmt);
2706         ns_client_logv(client, category, module, level, fmt, ap);
2707         va_end(ap);
2708 }
2709
2710 void
2711 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2712                  dns_rdataclass_t rdclass, char *buf, size_t len)
2713 {
2714         char namebuf[DNS_NAME_FORMATSIZE];
2715         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2716         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2717
2718         dns_name_format(name, namebuf, sizeof(namebuf));
2719         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2720         dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2721         (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2722                        classbuf);
2723 }
2724
2725 static void
2726 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2727         isc_buffer_t buffer;
2728         char *buf = NULL;
2729         int len = 1024;
2730         isc_result_t result;
2731
2732         /*
2733          * Note that these are multiline debug messages.  We want a newline
2734          * to appear in the log after each message.
2735          */
2736
2737         do {
2738                 buf = isc_mem_get(client->mctx, len);
2739                 if (buf == NULL)
2740                         break;
2741                 isc_buffer_init(&buffer, buf, len);
2742                 result = dns_message_totext(client->message,
2743                                             &dns_master_style_debug,
2744                                             0, &buffer);
2745                 if (result == ISC_R_NOSPACE) {
2746                         isc_mem_put(client->mctx, buf, len);
2747                         len += 1024;
2748                 } else if (result == ISC_R_SUCCESS)
2749                         ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2750                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2751                                       "%s\n%.*s", reason,
2752                                        (int)isc_buffer_usedlength(&buffer),
2753                                        buf);
2754         } while (result == ISC_R_NOSPACE);
2755
2756         if (buf != NULL)
2757                 isc_mem_put(client->mctx, buf, len);
2758 }
2759
2760 void
2761 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2762         ns_client_t *client;
2763         char namebuf[DNS_NAME_FORMATSIZE];
2764         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2765         const char *name;
2766         const char *sep;
2767
2768         REQUIRE(VALID_MANAGER(manager));
2769
2770         LOCK(&manager->lock);
2771         client = ISC_LIST_HEAD(manager->recursing);
2772         while (client != NULL) {
2773                 ns_client_name(client, peerbuf, sizeof(peerbuf));
2774                 if (client->view != NULL &&
2775                     strcmp(client->view->name, "_bind") != 0 &&
2776                     strcmp(client->view->name, "_default") != 0) {
2777                         name = client->view->name;
2778                         sep = ": view ";
2779                 } else {
2780                         name = "";
2781                         sep = "";
2782                 }
2783                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2784                 fprintf(f, "; client %s%s%s: '%s' requesttime %d\n",
2785                         peerbuf, sep, name, namebuf, client->requesttime);
2786                 client = ISC_LIST_NEXT(client, link);
2787         }
2788         UNLOCK(&manager->lock);
2789 }
2790
2791 void
2792 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2793
2794         if (client->manager != NULL)
2795                 LOCK(&client->manager->lock);
2796         if (client->query.restarts > 0) {
2797                 /*
2798                  * client->query.qname was dynamically allocated.
2799                  */
2800                 dns_message_puttempname(client->message,
2801                                         &client->query.qname);
2802         }
2803         client->query.qname = name;
2804         if (client->manager != NULL)
2805                 UNLOCK(&client->manager->lock);
2806 }