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