]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/bin/named/client.c
MFC r254651:
[FreeBSD/stable/9.git] / contrib / bind9 / bin / named / client.c
1 /*
2  * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id$ */
19
20 #include <config.h>
21
22 #include <isc/formatcheck.h>
23 #include <isc/mutex.h>
24 #include <isc/once.h>
25 #include <isc/platform.h>
26 #include <isc/print.h>
27 #include <isc/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         cleanup_cctx = ISC_TRUE;
977
978         result = dns_message_renderbegin(client->message, &cctx, &buffer);
979         if (result != ISC_R_SUCCESS)
980                 goto done;
981
982         if (client->opt != NULL) {
983                 result = dns_message_setopt(client->message, client->opt);
984                 opt_included = ISC_TRUE;
985                 client->opt = NULL;
986                 if (result != ISC_R_SUCCESS)
987                         goto done;
988         }
989         result = dns_message_rendersection(client->message,
990                                            DNS_SECTION_QUESTION, 0);
991         if (result == ISC_R_NOSPACE) {
992                 client->message->flags |= DNS_MESSAGEFLAG_TC;
993                 goto renderend;
994         }
995         if (result != ISC_R_SUCCESS)
996                 goto done;
997         result = dns_message_rendersection(client->message,
998                                            DNS_SECTION_ANSWER,
999                                            DNS_MESSAGERENDER_PARTIAL |
1000                                            render_opts);
1001         if (result == ISC_R_NOSPACE) {
1002                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1003                 goto renderend;
1004         }
1005         if (result != ISC_R_SUCCESS)
1006                 goto done;
1007         result = dns_message_rendersection(client->message,
1008                                            DNS_SECTION_AUTHORITY,
1009                                            DNS_MESSAGERENDER_PARTIAL |
1010                                            render_opts);
1011         if (result == ISC_R_NOSPACE) {
1012                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1013                 goto renderend;
1014         }
1015         if (result != ISC_R_SUCCESS)
1016                 goto done;
1017         result = dns_message_rendersection(client->message,
1018                                            DNS_SECTION_ADDITIONAL,
1019                                            preferred_glue | render_opts);
1020         if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1021                 goto done;
1022  renderend:
1023         result = dns_message_renderend(client->message);
1024
1025         if (result != ISC_R_SUCCESS)
1026                 goto done;
1027
1028         if (cleanup_cctx) {
1029                 dns_compress_invalidate(&cctx);
1030                 cleanup_cctx = ISC_FALSE;
1031         }
1032
1033         if (TCP_CLIENT(client)) {
1034                 isc_buffer_usedregion(&buffer, &r);
1035                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1036                 isc_buffer_add(&tcpbuffer, r.length);
1037                 result = client_sendpkg(client, &tcpbuffer);
1038         } else
1039                 result = client_sendpkg(client, &buffer);
1040
1041         /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1042         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1043         if (opt_included) {
1044                 isc_stats_increment(ns_g_server->nsstats,
1045                                     dns_nsstatscounter_edns0out);
1046         }
1047         if (client->message->tsigkey != NULL) {
1048                 isc_stats_increment(ns_g_server->nsstats,
1049                                     dns_nsstatscounter_tsigout);
1050         }
1051         if (client->message->sig0key != NULL) {
1052                 isc_stats_increment(ns_g_server->nsstats,
1053                                     dns_nsstatscounter_sig0out);
1054         }
1055         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1056                 isc_stats_increment(ns_g_server->nsstats,
1057                                     dns_nsstatscounter_truncatedresp);
1058
1059         if (result == ISC_R_SUCCESS)
1060                 return;
1061
1062  done:
1063         if (client->tcpbuf != NULL) {
1064                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1065                 client->tcpbuf = NULL;
1066         }
1067
1068         if (cleanup_cctx)
1069                 dns_compress_invalidate(&cctx);
1070
1071         ns_client_next(client, result);
1072 }
1073
1074 #if NS_CLIENT_DROPPORT
1075 #define DROPPORT_NO             0
1076 #define DROPPORT_REQUEST        1
1077 #define DROPPORT_RESPONSE       2
1078 /*%
1079  * ns_client_dropport determines if certain requests / responses
1080  * should be dropped based on the port number.
1081  *
1082  * Returns:
1083  * \li  0:      Don't drop.
1084  * \li  1:      Drop request.
1085  * \li  2:      Drop (error) response.
1086  */
1087 static int
1088 ns_client_dropport(in_port_t port) {
1089         switch (port) {
1090         case 7: /* echo */
1091         case 13: /* daytime */
1092         case 19: /* chargen */
1093         case 37: /* time */
1094                 return (DROPPORT_REQUEST);
1095         case 464: /* kpasswd */
1096                 return (DROPPORT_RESPONSE);
1097         }
1098         return (DROPPORT_NO);
1099 }
1100 #endif
1101
1102 void
1103 ns_client_error(ns_client_t *client, isc_result_t result) {
1104         dns_rcode_t rcode;
1105         dns_message_t *message;
1106
1107         REQUIRE(NS_CLIENT_VALID(client));
1108
1109         CTRACE("error");
1110
1111         message = client->message;
1112         rcode = dns_result_torcode(result);
1113
1114 #if NS_CLIENT_DROPPORT
1115         /*
1116          * Don't send FORMERR to ports on the drop port list.
1117          */
1118         if (rcode == dns_rcode_formerr &&
1119             ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1120             DROPPORT_NO) {
1121                 char buf[64];
1122                 isc_buffer_t b;
1123
1124                 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1125                 if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1126                         isc_buffer_putstr(&b, "UNKNOWN RCODE");
1127                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1128                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1129                               "dropped error (%.*s) response: suspicious port",
1130                               (int)isc_buffer_usedlength(&b), buf);
1131                 ns_client_next(client, ISC_R_SUCCESS);
1132                 return;
1133         }
1134 #endif
1135
1136         /*
1137          * Message may be an in-progress reply that we had trouble
1138          * with, in which case QR will be set.  We need to clear QR before
1139          * calling dns_message_reply() to avoid triggering an assertion.
1140          */
1141         message->flags &= ~DNS_MESSAGEFLAG_QR;
1142         /*
1143          * AA and AD shouldn't be set.
1144          */
1145         message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1146         result = dns_message_reply(message, ISC_TRUE);
1147         if (result != ISC_R_SUCCESS) {
1148                 /*
1149                  * It could be that we've got a query with a good header,
1150                  * but a bad question section, so we try again with
1151                  * want_question_section set to ISC_FALSE.
1152                  */
1153                 result = dns_message_reply(message, ISC_FALSE);
1154                 if (result != ISC_R_SUCCESS) {
1155                         ns_client_next(client, result);
1156                         return;
1157                 }
1158         }
1159         message->rcode = rcode;
1160
1161         /*
1162          * FORMERR loop avoidance:  If we sent a FORMERR message
1163          * with the same ID to the same client less than two
1164          * seconds ago, assume that we are in an infinite error
1165          * packet dialog with a server for some protocol whose
1166          * error responses look enough like DNS queries to
1167          * elicit a FORMERR response.  Drop a packet to break
1168          * the loop.
1169          */
1170         if (rcode == dns_rcode_formerr) {
1171                 if (isc_sockaddr_equal(&client->peeraddr,
1172                                        &client->formerrcache.addr) &&
1173                     message->id == client->formerrcache.id &&
1174                     client->requesttime - client->formerrcache.time < 2) {
1175                         /* Drop packet. */
1176                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1177                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1178                                       "possible error packet loop, "
1179                                       "FORMERR dropped");
1180                         ns_client_next(client, result);
1181                         return;
1182                 }
1183                 client->formerrcache.addr = client->peeraddr;
1184                 client->formerrcache.time = client->requesttime;
1185                 client->formerrcache.id = message->id;
1186         }
1187         ns_client_send(client);
1188 }
1189
1190 static inline isc_result_t
1191 client_addopt(ns_client_t *client) {
1192         dns_rdataset_t *rdataset;
1193         dns_rdatalist_t *rdatalist;
1194         dns_rdata_t *rdata;
1195         isc_result_t result;
1196         dns_view_t *view;
1197         dns_resolver_t *resolver;
1198         isc_uint16_t udpsize;
1199
1200         REQUIRE(client->opt == NULL);   /* XXXRTH free old. */
1201
1202         rdatalist = NULL;
1203         result = dns_message_gettemprdatalist(client->message, &rdatalist);
1204         if (result != ISC_R_SUCCESS)
1205                 return (result);
1206         rdata = NULL;
1207         result = dns_message_gettemprdata(client->message, &rdata);
1208         if (result != ISC_R_SUCCESS)
1209                 return (result);
1210         rdataset = NULL;
1211         result = dns_message_gettemprdataset(client->message, &rdataset);
1212         if (result != ISC_R_SUCCESS)
1213                 return (result);
1214         dns_rdataset_init(rdataset);
1215
1216         rdatalist->type = dns_rdatatype_opt;
1217         rdatalist->covers = 0;
1218
1219         /*
1220          * Set the maximum UDP buffer size.
1221          */
1222         view = client->view;
1223         resolver = (view != NULL) ? view->resolver : NULL;
1224         if (resolver != NULL)
1225                 udpsize = dns_resolver_getudpsize(resolver);
1226         else
1227                 udpsize = ns_g_udpsize;
1228         rdatalist->rdclass = udpsize;
1229
1230         /*
1231          * Set EXTENDED-RCODE, VERSION and Z to 0.
1232          */
1233         rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1234
1235         /* Set EDNS options if applicable */
1236         if (client->attributes & NS_CLIENTATTR_WANTNSID &&
1237             (ns_g_server->server_id != NULL ||
1238              ns_g_server->server_usehostname)) {
1239                 /*
1240                  * Space required for NSID data:
1241                  *   2 bytes for opt code
1242                  * + 2 bytes for NSID length
1243                  * + NSID itself
1244                  */
1245                 char nsid[BUFSIZ], *nsidp;
1246                 isc_buffer_t *buffer = NULL;
1247
1248                 if (ns_g_server->server_usehostname) {
1249                         isc_result_t result;
1250                         result = ns_os_gethostname(nsid, sizeof(nsid));
1251                         if (result != ISC_R_SUCCESS) {
1252                                 goto no_nsid;
1253                         }
1254                         nsidp = nsid;
1255                 } else
1256                         nsidp = ns_g_server->server_id;
1257
1258                 rdata->length = strlen(nsidp) + 4;
1259                 result = isc_buffer_allocate(client->mctx, &buffer,
1260                                              rdata->length);
1261                 if (result != ISC_R_SUCCESS)
1262                         goto no_nsid;
1263
1264                 isc_buffer_putuint16(buffer, DNS_OPT_NSID);
1265                 isc_buffer_putuint16(buffer, strlen(nsidp));
1266                 isc_buffer_putstr(buffer, nsidp);
1267                 rdata->data = buffer->base;
1268                 dns_message_takebuffer(client->message, &buffer);
1269         } else {
1270 no_nsid:
1271                 rdata->data = NULL;
1272                 rdata->length = 0;
1273         }
1274
1275         rdata->rdclass = rdatalist->rdclass;
1276         rdata->type = rdatalist->type;
1277         rdata->flags = 0;
1278
1279         ISC_LIST_INIT(rdatalist->rdata);
1280         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1281         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1282                       == ISC_R_SUCCESS);
1283
1284         client->opt = rdataset;
1285
1286         return (ISC_R_SUCCESS);
1287 }
1288
1289 static inline isc_boolean_t
1290 allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1291         int match;
1292         isc_result_t result;
1293
1294         if (acl == NULL)
1295                 return (ISC_TRUE);
1296         result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1297                                &match, NULL);
1298         if (result == ISC_R_SUCCESS && match > 0)
1299                 return (ISC_TRUE);
1300         return (ISC_FALSE);
1301 }
1302
1303 /*
1304  * Callback to see if a non-recursive query coming from 'srcaddr' to
1305  * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1306  * delivered to 'myview'.
1307  *
1308  * We run this unlocked as both the view list and the interface list
1309  * are updated when the appropriate task has exclusivity.
1310  */
1311 isc_boolean_t
1312 ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1313                  isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1314                  dns_rdataclass_t rdclass, void *arg)
1315 {
1316         dns_view_t *view;
1317         dns_tsigkey_t *key = NULL;
1318         dns_name_t *tsig = NULL;
1319         isc_netaddr_t netsrc;
1320         isc_netaddr_t netdst;
1321
1322         UNUSED(arg);
1323
1324         /*
1325          * ns_g_server->interfacemgr is task exclusive locked.
1326          */
1327         if (ns_g_server->interfacemgr == NULL)
1328                 return (ISC_TRUE);
1329
1330         if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1331                 return (ISC_FALSE);
1332
1333         isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1334         isc_netaddr_fromsockaddr(&netdst, dstaddr);
1335
1336         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1337              view != NULL;
1338              view = ISC_LIST_NEXT(view, link)) {
1339
1340                 if (view->matchrecursiveonly)
1341                         continue;
1342
1343                 if (rdclass != view->rdclass)
1344                         continue;
1345
1346                 if (mykey != NULL) {
1347                         isc_boolean_t match;
1348                         isc_result_t result;
1349
1350                         result = dns_view_gettsig(view, &mykey->name, &key);
1351                         if (result != ISC_R_SUCCESS)
1352                                 continue;
1353                         match = dst_key_compare(mykey->key, key->key);
1354                         dns_tsigkey_detach(&key);
1355                         if (!match)
1356                                 continue;
1357                         tsig = dns_tsigkey_identity(mykey);
1358                 }
1359
1360                 if (allowed(&netsrc, tsig, view->matchclients) &&
1361                     allowed(&netdst, tsig, view->matchdestinations))
1362                         break;
1363         }
1364         return (ISC_TF(view == myview));
1365 }
1366
1367 /*
1368  * Handle an incoming request event from the socket (UDP case)
1369  * or tcpmsg (TCP case).
1370  */
1371 static void
1372 client_request(isc_task_t *task, isc_event_t *event) {
1373         ns_client_t *client;
1374         isc_socketevent_t *sevent;
1375         isc_result_t result;
1376         isc_result_t sigresult = ISC_R_SUCCESS;
1377         isc_buffer_t *buffer;
1378         isc_buffer_t tbuffer;
1379         dns_view_t *view;
1380         dns_rdataset_t *opt;
1381         dns_name_t *signame;
1382         isc_boolean_t ra;       /* Recursion available. */
1383         isc_netaddr_t netaddr;
1384         int match;
1385         dns_messageid_t id;
1386         unsigned int flags;
1387         isc_boolean_t notimp;
1388         dns_rdata_t rdata;
1389         isc_uint16_t optcode;
1390
1391         REQUIRE(event != NULL);
1392         client = event->ev_arg;
1393         REQUIRE(NS_CLIENT_VALID(client));
1394         REQUIRE(task == client->task);
1395
1396         INSIST(client->recursionquota == NULL);
1397
1398         INSIST(client->state == (TCP_CLIENT(client) ?
1399                                        NS_CLIENTSTATE_READING :
1400                                        NS_CLIENTSTATE_READY));
1401
1402         ns_client_requests++;
1403
1404         if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1405                 INSIST(!TCP_CLIENT(client));
1406                 sevent = (isc_socketevent_t *)event;
1407                 REQUIRE(sevent == client->recvevent);
1408                 isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1409                 isc_buffer_add(&tbuffer, sevent->n);
1410                 buffer = &tbuffer;
1411                 result = sevent->result;
1412                 if (result == ISC_R_SUCCESS) {
1413                         client->peeraddr = sevent->address;
1414                         client->peeraddr_valid = ISC_TRUE;
1415                 }
1416                 if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1417                         client->attributes |= NS_CLIENTATTR_PKTINFO;
1418                         client->pktinfo = sevent->pktinfo;
1419                 }
1420                 if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1421                         client->attributes |= NS_CLIENTATTR_MULTICAST;
1422                 client->nrecvs--;
1423         } else {
1424                 INSIST(TCP_CLIENT(client));
1425                 REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1426                 REQUIRE(event->ev_sender == &client->tcpmsg);
1427                 buffer = &client->tcpmsg.buffer;
1428                 result = client->tcpmsg.result;
1429                 INSIST(client->nreads == 1);
1430                 /*
1431                  * client->peeraddr was set when the connection was accepted.
1432                  */
1433                 client->nreads--;
1434         }
1435
1436         if (exit_check(client))
1437                 goto cleanup;
1438         client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1439
1440         isc_task_getcurrenttime(task, &client->requesttime);
1441         client->now = client->requesttime;
1442
1443         if (result != ISC_R_SUCCESS) {
1444                 if (TCP_CLIENT(client)) {
1445                         ns_client_next(client, result);
1446                 } else {
1447                         if  (result != ISC_R_CANCELED)
1448                                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1449                                               NS_LOGMODULE_CLIENT,
1450                                               ISC_LOG_ERROR,
1451                                               "UDP client handler shutting "
1452                                               "down due to fatal receive "
1453                                               "error: %s",
1454                                               isc_result_totext(result));
1455                         isc_task_shutdown(client->task);
1456                 }
1457                 goto cleanup;
1458         }
1459
1460         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1461
1462 #if NS_CLIENT_DROPPORT
1463         if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1464             DROPPORT_REQUEST) {
1465                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1466                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1467                               "dropped request: suspicious port");
1468                 ns_client_next(client, ISC_R_SUCCESS);
1469                 goto cleanup;
1470         }
1471 #endif
1472
1473         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1474                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1475                       "%s request",
1476                       TCP_CLIENT(client) ? "TCP" : "UDP");
1477
1478         /*
1479          * Check the blackhole ACL for UDP only, since TCP is done in
1480          * client_newconn.
1481          */
1482         if (!TCP_CLIENT(client)) {
1483
1484                 if (ns_g_server->blackholeacl != NULL &&
1485                     dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1486                                   &ns_g_server->aclenv,
1487                                   &match, NULL) == ISC_R_SUCCESS &&
1488                     match > 0)
1489                 {
1490                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1491                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1492                                       "blackholed UDP datagram");
1493                         ns_client_next(client, ISC_R_SUCCESS);
1494                         goto cleanup;
1495                 }
1496         }
1497
1498         /*
1499          * Silently drop multicast requests for the present.
1500          * XXXMPA revisit this as mDNS spec was published.
1501          */
1502         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1503                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1504                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1505                               "dropping multicast request");
1506                 ns_client_next(client, DNS_R_REFUSED);
1507                 goto cleanup;
1508         }
1509
1510         result = dns_message_peekheader(buffer, &id, &flags);
1511         if (result != ISC_R_SUCCESS) {
1512                 /*
1513                  * There isn't enough header to determine whether
1514                  * this was a request or a response.  Drop it.
1515                  */
1516                 ns_client_next(client, result);
1517                 goto cleanup;
1518         }
1519
1520         /*
1521          * The client object handles requests, not responses.
1522          * If this is a UDP response, forward it to the dispatcher.
1523          * If it's a TCP response, discard it here.
1524          */
1525         if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1526                 if (TCP_CLIENT(client)) {
1527                         CTRACE("unexpected response");
1528                         ns_client_next(client, DNS_R_FORMERR);
1529                         goto cleanup;
1530                 } else {
1531                         dns_dispatch_importrecv(client->dispatch, event);
1532                         ns_client_next(client, ISC_R_SUCCESS);
1533                         goto cleanup;
1534                 }
1535         }
1536
1537         /*
1538          * Update some statistics counters.  Don't count responses.
1539          */
1540         if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1541                 isc_stats_increment(ns_g_server->nsstats,
1542                                     dns_nsstatscounter_requestv4);
1543         } else {
1544                 isc_stats_increment(ns_g_server->nsstats,
1545                                     dns_nsstatscounter_requestv6);
1546         }
1547         if (TCP_CLIENT(client))
1548                 isc_stats_increment(ns_g_server->nsstats,
1549                                     dns_nsstatscounter_tcp);
1550
1551         /*
1552          * It's a request.  Parse it.
1553          */
1554         result = dns_message_parse(client->message, buffer, 0);
1555         if (result != ISC_R_SUCCESS) {
1556                 /*
1557                  * Parsing the request failed.  Send a response
1558                  * (typically FORMERR or SERVFAIL).
1559                  */
1560                 ns_client_error(client, result);
1561                 goto cleanup;
1562         }
1563
1564         dns_opcodestats_increment(ns_g_server->opcodestats,
1565                                   client->message->opcode);
1566         switch (client->message->opcode) {
1567         case dns_opcode_query:
1568         case dns_opcode_update:
1569         case dns_opcode_notify:
1570                 notimp = ISC_FALSE;
1571                 break;
1572         case dns_opcode_iquery:
1573         default:
1574                 notimp = ISC_TRUE;
1575                 break;
1576         }
1577
1578         client->message->rcode = dns_rcode_noerror;
1579
1580         /* RFC1123 section 6.1.3.2 */
1581         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1582                 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1583
1584         /*
1585          * Deal with EDNS.
1586          */
1587         opt = dns_message_getopt(client->message);
1588         if (opt != NULL) {
1589                 /*
1590                  * Set the client's UDP buffer size.
1591                  */
1592                 client->udpsize = opt->rdclass;
1593
1594                 /*
1595                  * If the requested UDP buffer size is less than 512,
1596                  * ignore it and use 512.
1597                  */
1598                 if (client->udpsize < 512)
1599                         client->udpsize = 512;
1600
1601                 /*
1602                  * Get the flags out of the OPT record.
1603                  */
1604                 client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1605
1606                 /*
1607                  * Do we understand this version of EDNS?
1608                  *
1609                  * XXXRTH need library support for this!
1610                  */
1611                 client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1612                 if (client->ednsversion > 0) {
1613                         isc_stats_increment(ns_g_server->nsstats,
1614                                             dns_nsstatscounter_badednsver);
1615                         result = client_addopt(client);
1616                         if (result == ISC_R_SUCCESS)
1617                                 result = DNS_R_BADVERS;
1618                         ns_client_error(client, result);
1619                         goto cleanup;
1620                 }
1621
1622                 /* Check for NSID request */
1623                 result = dns_rdataset_first(opt);
1624                 if (result == ISC_R_SUCCESS) {
1625                         dns_rdata_init(&rdata);
1626                         dns_rdataset_current(opt, &rdata);
1627                         if (rdata.length >= 2) {
1628                                 isc_buffer_t nsidbuf;
1629                                 isc_buffer_init(&nsidbuf,
1630                                                 rdata.data, rdata.length);
1631                                 isc_buffer_add(&nsidbuf, rdata.length);
1632                                 optcode = isc_buffer_getuint16(&nsidbuf);
1633                                 if (optcode == DNS_OPT_NSID)
1634                                         client->attributes |=
1635                                                 NS_CLIENTATTR_WANTNSID;
1636                         }
1637                 }
1638
1639                 isc_stats_increment(ns_g_server->nsstats,
1640                                     dns_nsstatscounter_edns0in);
1641
1642                 /*
1643                  * Create an OPT for our reply.
1644                  */
1645                 result = client_addopt(client);
1646                 if (result != ISC_R_SUCCESS) {
1647                         ns_client_error(client, result);
1648                         goto cleanup;
1649                 }
1650         }
1651
1652         if (client->message->rdclass == 0) {
1653                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1654                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1655                               "message class could not be determined");
1656                 ns_client_dumpmessage(client,
1657                                       "message class could not be determined");
1658                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1659                 goto cleanup;
1660         }
1661
1662         /*
1663          * Determine the destination address.  If the receiving interface is
1664          * bound to a specific address, we simply use it regardless of the
1665          * address family.  All IPv4 queries should fall into this case.
1666          * Otherwise, if this is a TCP query, get the address from the
1667          * receiving socket (this needs a system call and can be heavy).
1668          * For IPv6 UDP queries, we get this from the pktinfo structure (if
1669          * supported).
1670          * If all the attempts fail (this can happen due to memory shortage,
1671          * etc), we regard this as an error for safety.
1672          */
1673         if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1674                 isc_netaddr_fromsockaddr(&client->destaddr,
1675                                          &client->interface->addr);
1676         else {
1677                 isc_sockaddr_t sockaddr;
1678                 result = ISC_R_FAILURE;
1679
1680                 if (TCP_CLIENT(client))
1681                         result = isc_socket_getsockname(client->tcpsocket,
1682                                                         &sockaddr);
1683                 if (result == ISC_R_SUCCESS)
1684                         isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1685                 if (result != ISC_R_SUCCESS &&
1686                     client->interface->addr.type.sa.sa_family == AF_INET6 &&
1687                     (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1688                         /*
1689                          * XXXJT technically, we should convert the receiving
1690                          * interface ID to a proper scope zone ID.  However,
1691                          * due to the fact there is no standard API for this,
1692                          * we only handle link-local addresses and use the
1693                          * interface index as link ID.  Despite the assumption,
1694                          * it should cover most typical cases.
1695                          */
1696                         isc_netaddr_fromin6(&client->destaddr,
1697                                             &client->pktinfo.ipi6_addr);
1698                         if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1699                                 isc_netaddr_setzone(&client->destaddr,
1700                                                 client->pktinfo.ipi6_ifindex);
1701                         result = ISC_R_SUCCESS;
1702                 }
1703                 if (result != ISC_R_SUCCESS) {
1704                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1705                                          "failed to get request's "
1706                                          "destination: %s",
1707                                          isc_result_totext(result));
1708                         ns_client_next(client, ISC_R_SUCCESS);
1709                         goto cleanup;
1710                 }
1711         }
1712
1713         /*
1714          * Find a view that matches the client's source address.
1715          */
1716         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1717              view != NULL;
1718              view = ISC_LIST_NEXT(view, link)) {
1719                 if (client->message->rdclass == view->rdclass ||
1720                     client->message->rdclass == dns_rdataclass_any)
1721                 {
1722                         dns_name_t *tsig = NULL;
1723
1724                         sigresult = dns_message_rechecksig(client->message,
1725                                                            view);
1726                         if (sigresult == ISC_R_SUCCESS)
1727                                 tsig = dns_tsigkey_identity(client->message->tsigkey);
1728
1729                         if (allowed(&netaddr, tsig, view->matchclients) &&
1730                             allowed(&client->destaddr, tsig,
1731                                     view->matchdestinations) &&
1732                             !((client->message->flags & DNS_MESSAGEFLAG_RD)
1733                               == 0 && view->matchrecursiveonly))
1734                         {
1735                                 dns_view_attach(view, &client->view);
1736                                 break;
1737                         }
1738                 }
1739         }
1740
1741         if (view == NULL) {
1742                 char classname[DNS_RDATACLASS_FORMATSIZE];
1743
1744                 /*
1745                  * Do a dummy TSIG verification attempt so that the
1746                  * response will have a TSIG if the query did, as
1747                  * required by RFC2845.
1748                  */
1749                 isc_buffer_t b;
1750                 isc_region_t *r;
1751
1752                 dns_message_resetsig(client->message);
1753
1754                 r = dns_message_getrawmessage(client->message);
1755                 isc_buffer_init(&b, r->base, r->length);
1756                 isc_buffer_add(&b, r->length);
1757                 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
1758
1759                 dns_rdataclass_format(client->message->rdclass, classname,
1760                                       sizeof(classname));
1761                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1762                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1763                               "no matching view in class '%s'", classname);
1764                 ns_client_dumpmessage(client, "no matching view in class");
1765                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1766                 goto cleanup;
1767         }
1768
1769         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1770                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1771                       "using view '%s'", view->name);
1772
1773         /*
1774          * Check for a signature.  We log bad signatures regardless of
1775          * whether they ultimately cause the request to be rejected or
1776          * not.  We do not log the lack of a signature unless we are
1777          * debugging.
1778          */
1779         client->signer = NULL;
1780         dns_name_init(&client->signername, NULL);
1781         result = dns_message_signer(client->message, &client->signername);
1782         if (result != ISC_R_NOTFOUND) {
1783                 signame = NULL;
1784                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1785                         isc_stats_increment(ns_g_server->nsstats,
1786                                             dns_nsstatscounter_tsigin);
1787                 } else {
1788                         isc_stats_increment(ns_g_server->nsstats,
1789                                             dns_nsstatscounter_sig0in);
1790                 }
1791
1792         }
1793         if (result == ISC_R_SUCCESS) {
1794                 char namebuf[DNS_NAME_FORMATSIZE];
1795                 dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1796                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1797                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1798                               "request has valid signature: %s", namebuf);
1799                 client->signer = &client->signername;
1800         } else if (result == ISC_R_NOTFOUND) {
1801                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1802                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1803                               "request is not signed");
1804         } else if (result == DNS_R_NOIDENTITY) {
1805                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1806                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1807                               "request is signed by a nonauthoritative key");
1808         } else {
1809                 char tsigrcode[64];
1810                 isc_buffer_t b;
1811                 dns_rcode_t status;
1812                 isc_result_t tresult;
1813
1814                 /* There is a signature, but it is bad. */
1815                 isc_stats_increment(ns_g_server->nsstats,
1816                                     dns_nsstatscounter_invalidsig);
1817                 signame = NULL;
1818                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1819                         char namebuf[DNS_NAME_FORMATSIZE];
1820                         char cnamebuf[DNS_NAME_FORMATSIZE];
1821                         dns_name_format(signame, namebuf, sizeof(namebuf));
1822                         status = client->message->tsigstatus;
1823                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1824                         tresult = dns_tsigrcode_totext(status, &b);
1825                         INSIST(tresult == ISC_R_SUCCESS);
1826                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1827                         if (client->message->tsigkey->generated) {
1828                                 dns_name_format(client->message->tsigkey->creator,
1829                                                 cnamebuf, sizeof(cnamebuf));
1830                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1831                                               NS_LOGMODULE_CLIENT,
1832                                               ISC_LOG_ERROR,
1833                                               "request has invalid signature: "
1834                                               "TSIG %s (%s): %s (%s)", namebuf,
1835                                               cnamebuf,
1836                                               isc_result_totext(result),
1837                                               tsigrcode);
1838                         } else {
1839                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1840                                               NS_LOGMODULE_CLIENT,
1841                                               ISC_LOG_ERROR,
1842                                               "request has invalid signature: "
1843                                               "TSIG %s: %s (%s)", namebuf,
1844                                               isc_result_totext(result),
1845                                               tsigrcode);
1846                         }
1847                 } else {
1848                         status = client->message->sig0status;
1849                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1850                         tresult = dns_tsigrcode_totext(status, &b);
1851                         INSIST(tresult == ISC_R_SUCCESS);
1852                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1853                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1854                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1855                                       "request has invalid signature: %s (%s)",
1856                                       isc_result_totext(result), tsigrcode);
1857                 }
1858                 /*
1859                  * Accept update messages signed by unknown keys so that
1860                  * update forwarding works transparently through slaves
1861                  * that don't have all the same keys as the master.
1862                  */
1863                 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1864                       client->message->opcode == dns_opcode_update)) {
1865                         ns_client_error(client, sigresult);
1866                         goto cleanup;
1867                 }
1868         }
1869
1870         /*
1871          * Decide whether recursive service is available to this client.
1872          * We do this here rather than in the query code so that we can
1873          * set the RA bit correctly on all kinds of responses, not just
1874          * responses to ordinary queries.  Note if you can't query the
1875          * cache there is no point in setting RA.
1876          */
1877         ra = ISC_FALSE;
1878         if (client->view->resolver != NULL &&
1879             client->view->recursion == ISC_TRUE &&
1880             ns_client_checkaclsilent(client, NULL,
1881                                      client->view->recursionacl,
1882                                      ISC_TRUE) == ISC_R_SUCCESS &&
1883             ns_client_checkaclsilent(client, NULL,
1884                                      client->view->cacheacl,
1885                                      ISC_TRUE) == ISC_R_SUCCESS &&
1886             ns_client_checkaclsilent(client, &client->destaddr,
1887                                      client->view->recursiononacl,
1888                                      ISC_TRUE) == ISC_R_SUCCESS &&
1889             ns_client_checkaclsilent(client, &client->destaddr,
1890                                      client->view->cacheonacl,
1891                                      ISC_TRUE) == ISC_R_SUCCESS)
1892                 ra = ISC_TRUE;
1893
1894         if (ra == ISC_TRUE)
1895                 client->attributes |= NS_CLIENTATTR_RA;
1896
1897         ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1898                       ISC_LOG_DEBUG(3), ra ? "recursion available" :
1899                                              "recursion not available");
1900
1901         /*
1902          * Adjust maximum UDP response size for this client.
1903          */
1904         if (client->udpsize > 512) {
1905                 dns_peer_t *peer = NULL;
1906                 isc_uint16_t udpsize = view->maxudp;
1907                 (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1908                 if (peer != NULL)
1909                         dns_peer_getmaxudp(peer, &udpsize);
1910                 if (client->udpsize > udpsize)
1911                         client->udpsize = udpsize;
1912         }
1913
1914         /*
1915          * Dispatch the request.
1916          */
1917         switch (client->message->opcode) {
1918         case dns_opcode_query:
1919                 CTRACE("query");
1920                 ns_query_start(client);
1921                 break;
1922         case dns_opcode_update:
1923                 CTRACE("update");
1924                 ns_client_settimeout(client, 60);
1925                 ns_update_start(client, sigresult);
1926                 break;
1927         case dns_opcode_notify:
1928                 CTRACE("notify");
1929                 ns_client_settimeout(client, 60);
1930                 ns_notify_start(client);
1931                 break;
1932         case dns_opcode_iquery:
1933                 CTRACE("iquery");
1934                 ns_client_error(client, DNS_R_NOTIMP);
1935                 break;
1936         default:
1937                 CTRACE("unknown opcode");
1938                 ns_client_error(client, DNS_R_NOTIMP);
1939         }
1940
1941  cleanup:
1942         return;
1943 }
1944
1945 static void
1946 client_timeout(isc_task_t *task, isc_event_t *event) {
1947         ns_client_t *client;
1948
1949         REQUIRE(event != NULL);
1950         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1951                 event->ev_type == ISC_TIMEREVENT_IDLE);
1952         client = event->ev_arg;
1953         REQUIRE(NS_CLIENT_VALID(client));
1954         REQUIRE(task == client->task);
1955         REQUIRE(client->timer != NULL);
1956
1957         UNUSED(task);
1958
1959         CTRACE("timeout");
1960
1961         isc_event_free(&event);
1962
1963         if (client->shutdown != NULL) {
1964                 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1965                 client->shutdown = NULL;
1966                 client->shutdown_arg = NULL;
1967         }
1968
1969         if (client->newstate > NS_CLIENTSTATE_READY)
1970                 client->newstate = NS_CLIENTSTATE_READY;
1971         (void)exit_check(client);
1972 }
1973
1974 static isc_result_t
1975 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
1976         isc_mem_t *clientmctx;
1977         isc_result_t result;
1978 #if NMCTXS > 0
1979         unsigned int nextmctx;
1980 #endif
1981
1982         MTRACE("clientmctx");
1983
1984         /*
1985          * Caller must be holding the manager lock.
1986          */
1987         if (ns_g_clienttest) {
1988                 result = isc_mem_create(0, 0, mctxp);
1989                 if (result == ISC_R_SUCCESS)
1990                         isc_mem_setname(*mctxp, "client", NULL);
1991                 return (result);
1992         }
1993 #if NMCTXS > 0
1994         nextmctx = manager->nextmctx++;
1995         if (manager->nextmctx == NMCTXS)
1996                 manager->nextmctx = 0;
1997
1998         INSIST(nextmctx < NMCTXS);
1999
2000         clientmctx = manager->mctxpool[nextmctx];
2001         if (clientmctx == NULL) {
2002                 result = isc_mem_create(0, 0, &clientmctx);
2003                 if (result != ISC_R_SUCCESS)
2004                         return (result);
2005                 isc_mem_setname(clientmctx, "client", NULL);
2006
2007                 manager->mctxpool[nextmctx] = clientmctx;
2008         }
2009 #else
2010         clientmctx = manager->mctx;
2011 #endif
2012
2013         isc_mem_attach(clientmctx, mctxp);
2014
2015         return (ISC_R_SUCCESS);
2016 }
2017
2018 static isc_result_t
2019 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
2020         ns_client_t *client;
2021         isc_result_t result;
2022         isc_mem_t *mctx = NULL;
2023
2024         /*
2025          * Caller must be holding the manager lock.
2026          *
2027          * Note: creating a client does not add the client to the
2028          * manager's client list or set the client's manager pointer.
2029          * The caller is responsible for that.
2030          */
2031
2032         REQUIRE(clientp != NULL && *clientp == NULL);
2033
2034         result = get_clientmctx(manager, &mctx);
2035         if (result != ISC_R_SUCCESS)
2036                 return (result);
2037
2038         client = isc_mem_get(mctx, sizeof(*client));
2039         if (client == NULL) {
2040                 isc_mem_detach(&mctx);
2041                 return (ISC_R_NOMEMORY);
2042         }
2043         client->mctx = mctx;
2044
2045         client->task = NULL;
2046         result = isc_task_create(manager->taskmgr, 0, &client->task);
2047         if (result != ISC_R_SUCCESS)
2048                 goto cleanup_client;
2049         isc_task_setname(client->task, "client", client);
2050
2051         client->timer = NULL;
2052         result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2053                                   NULL, NULL, client->task, client_timeout,
2054                                   client, &client->timer);
2055         if (result != ISC_R_SUCCESS)
2056                 goto cleanup_task;
2057         client->timerset = ISC_FALSE;
2058
2059         client->message = NULL;
2060         result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2061                                     &client->message);
2062         if (result != ISC_R_SUCCESS)
2063                 goto cleanup_timer;
2064
2065         /* XXXRTH  Hardwired constants */
2066
2067         client->sendevent = (isc_socketevent_t *)
2068                             isc_event_allocate(client->mctx, client,
2069                                                ISC_SOCKEVENT_SENDDONE,
2070                                                client_senddone, client,
2071                                                sizeof(isc_socketevent_t));
2072         if (client->sendevent == NULL) {
2073                 result = ISC_R_NOMEMORY;
2074                 goto cleanup_message;
2075         }
2076
2077         client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2078         if  (client->recvbuf == NULL) {
2079                 result = ISC_R_NOMEMORY;
2080                 goto cleanup_sendevent;
2081         }
2082
2083         client->recvevent = (isc_socketevent_t *)
2084                             isc_event_allocate(client->mctx, client,
2085                                                ISC_SOCKEVENT_RECVDONE,
2086                                                client_request, client,
2087                                                sizeof(isc_socketevent_t));
2088         if (client->recvevent == NULL) {
2089                 result = ISC_R_NOMEMORY;
2090                 goto cleanup_recvbuf;
2091         }
2092
2093         client->magic = NS_CLIENT_MAGIC;
2094         client->manager = NULL;
2095         client->state = NS_CLIENTSTATE_INACTIVE;
2096         client->newstate = NS_CLIENTSTATE_MAX;
2097         client->naccepts = 0;
2098         client->nreads = 0;
2099         client->nsends = 0;
2100         client->nrecvs = 0;
2101         client->nupdates = 0;
2102         client->nctls = 0;
2103         client->references = 0;
2104         client->attributes = 0;
2105         client->view = NULL;
2106         client->dispatch = NULL;
2107         client->udpsocket = NULL;
2108         client->tcplistener = NULL;
2109         client->tcpsocket = NULL;
2110         client->tcpmsg_valid = ISC_FALSE;
2111         client->tcpbuf = NULL;
2112         client->opt = NULL;
2113         client->udpsize = 512;
2114         client->extflags = 0;
2115         client->ednsversion = -1;
2116         client->next = NULL;
2117         client->shutdown = NULL;
2118         client->shutdown_arg = NULL;
2119         client->signer = NULL;
2120         dns_name_init(&client->signername, NULL);
2121         client->mortal = ISC_FALSE;
2122         client->tcpquota = NULL;
2123         client->recursionquota = NULL;
2124         client->interface = NULL;
2125         client->peeraddr_valid = ISC_FALSE;
2126 #ifdef ALLOW_FILTER_AAAA_ON_V4
2127         client->filter_aaaa = dns_v4_aaaa_ok;
2128 #endif
2129         client->needshutdown = ns_g_clienttest;
2130
2131         ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2132                        NS_EVENT_CLIENTCONTROL, client_start, client, client,
2133                        NULL, NULL);
2134         /*
2135          * Initialize FORMERR cache to sentinel value that will not match
2136          * any actual FORMERR response.
2137          */
2138         isc_sockaddr_any(&client->formerrcache.addr);
2139         client->formerrcache.time = 0;
2140         client->formerrcache.id = 0;
2141         ISC_LINK_INIT(client, link);
2142         ISC_LINK_INIT(client, rlink);
2143         ISC_QLINK_INIT(client, ilink);
2144
2145         /*
2146          * We call the init routines for the various kinds of client here,
2147          * after we have created an otherwise valid client, because some
2148          * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2149          */
2150         result = ns_query_init(client);
2151         if (result != ISC_R_SUCCESS)
2152                 goto cleanup_recvevent;
2153
2154         result = isc_task_onshutdown(client->task, client_shutdown, client);
2155         if (result != ISC_R_SUCCESS)
2156                 goto cleanup_query;
2157
2158         CTRACE("create");
2159
2160         *clientp = client;
2161
2162         return (ISC_R_SUCCESS);
2163
2164  cleanup_query:
2165         ns_query_free(client);
2166
2167  cleanup_recvevent:
2168         isc_event_free((isc_event_t **)&client->recvevent);
2169
2170  cleanup_recvbuf:
2171         isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2172
2173  cleanup_sendevent:
2174         isc_event_free((isc_event_t **)&client->sendevent);
2175
2176         client->magic = 0;
2177
2178  cleanup_message:
2179         dns_message_destroy(&client->message);
2180
2181  cleanup_timer:
2182         isc_timer_detach(&client->timer);
2183
2184  cleanup_task:
2185         isc_task_detach(&client->task);
2186
2187  cleanup_client:
2188         isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2189
2190         return (result);
2191 }
2192
2193 static void
2194 client_read(ns_client_t *client) {
2195         isc_result_t result;
2196
2197         CTRACE("read");
2198
2199         result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2200                                         client_request, client);
2201         if (result != ISC_R_SUCCESS)
2202                 goto fail;
2203
2204         /*
2205          * Set a timeout to limit the amount of time we will wait
2206          * for a request on this TCP connection.
2207          */
2208         ns_client_settimeout(client, 30);
2209
2210         client->state = client->newstate = NS_CLIENTSTATE_READING;
2211         INSIST(client->nreads == 0);
2212         INSIST(client->recursionquota == NULL);
2213         client->nreads++;
2214
2215         return;
2216  fail:
2217         ns_client_next(client, result);
2218 }
2219
2220 static void
2221 client_newconn(isc_task_t *task, isc_event_t *event) {
2222         ns_client_t *client = event->ev_arg;
2223         isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2224         isc_result_t result;
2225
2226         REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2227         REQUIRE(NS_CLIENT_VALID(client));
2228         REQUIRE(client->task == task);
2229
2230         UNUSED(task);
2231
2232         INSIST(client->state == NS_CLIENTSTATE_READY);
2233
2234         INSIST(client->naccepts == 1);
2235         client->naccepts--;
2236
2237         LOCK(&client->interface->lock);
2238         INSIST(client->interface->ntcpcurrent > 0);
2239         client->interface->ntcpcurrent--;
2240         UNLOCK(&client->interface->lock);
2241
2242         /*
2243          * We must take ownership of the new socket before the exit
2244          * check to make sure it gets destroyed if we decide to exit.
2245          */
2246         if (nevent->result == ISC_R_SUCCESS) {
2247                 client->tcpsocket = nevent->newsocket;
2248                 isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2249                 client->state = NS_CLIENTSTATE_READING;
2250                 INSIST(client->recursionquota == NULL);
2251
2252                 (void)isc_socket_getpeername(client->tcpsocket,
2253                                              &client->peeraddr);
2254                 client->peeraddr_valid = ISC_TRUE;
2255                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2256                            NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2257                            "new TCP connection");
2258         } else {
2259                 /*
2260                  * XXXRTH  What should we do?  We're trying to accept but
2261                  *         it didn't work.  If we just give up, then TCP
2262                  *         service may eventually stop.
2263                  *
2264                  *         For now, we just go idle.
2265                  *
2266                  *         Going idle is probably the right thing if the
2267                  *         I/O was canceled.
2268                  */
2269                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2270                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2271                               "accept failed: %s",
2272                               isc_result_totext(nevent->result));
2273         }
2274
2275         if (exit_check(client))
2276                 goto freeevent;
2277
2278         if (nevent->result == ISC_R_SUCCESS) {
2279                 int match;
2280                 isc_netaddr_t netaddr;
2281
2282                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2283
2284                 if (ns_g_server->blackholeacl != NULL &&
2285                     dns_acl_match(&netaddr, NULL,
2286                                   ns_g_server->blackholeacl,
2287                                   &ns_g_server->aclenv,
2288                                   &match, NULL) == ISC_R_SUCCESS &&
2289                     match > 0)
2290                 {
2291                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2292                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2293                                       "blackholed connection attempt");
2294                         client->newstate = NS_CLIENTSTATE_READY;
2295                         (void)exit_check(client);
2296                         goto freeevent;
2297                 }
2298
2299                 INSIST(client->tcpmsg_valid == ISC_FALSE);
2300                 dns_tcpmsg_init(client->mctx, client->tcpsocket,
2301                                 &client->tcpmsg);
2302                 client->tcpmsg_valid = ISC_TRUE;
2303
2304                 /*
2305                  * Let a new client take our place immediately, before
2306                  * we wait for a request packet.  If we don't,
2307                  * telnetting to port 53 (once per CPU) will
2308                  * deny service to legitimate TCP clients.
2309                  */
2310                 result = isc_quota_attach(&ns_g_server->tcpquota,
2311                                           &client->tcpquota);
2312                 if (result == ISC_R_SUCCESS)
2313                         result = ns_client_replace(client);
2314                 if (result != ISC_R_SUCCESS) {
2315                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2316                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2317                                       "no more TCP clients: %s",
2318                                       isc_result_totext(result));
2319                 }
2320
2321                 client_read(client);
2322         }
2323
2324  freeevent:
2325         isc_event_free(&event);
2326 }
2327
2328 static void
2329 client_accept(ns_client_t *client) {
2330         isc_result_t result;
2331
2332         CTRACE("accept");
2333
2334         result = isc_socket_accept(client->tcplistener, client->task,
2335                                    client_newconn, client);
2336         if (result != ISC_R_SUCCESS) {
2337                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2338                                  "isc_socket_accept() failed: %s",
2339                                  isc_result_totext(result));
2340                 /*
2341                  * XXXRTH  What should we do?  We're trying to accept but
2342                  *         it didn't work.  If we just give up, then TCP
2343                  *         service may eventually stop.
2344                  *
2345                  *         For now, we just go idle.
2346                  */
2347                 return;
2348         }
2349         INSIST(client->naccepts == 0);
2350         client->naccepts++;
2351         LOCK(&client->interface->lock);
2352         client->interface->ntcpcurrent++;
2353         UNLOCK(&client->interface->lock);
2354 }
2355
2356 static void
2357 client_udprecv(ns_client_t *client) {
2358         isc_result_t result;
2359         isc_region_t r;
2360
2361         CTRACE("udprecv");
2362
2363         r.base = client->recvbuf;
2364         r.length = RECV_BUFFER_SIZE;
2365         result = isc_socket_recv2(client->udpsocket, &r, 1,
2366                                   client->task, client->recvevent, 0);
2367         if (result != ISC_R_SUCCESS) {
2368                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2369                                  "isc_socket_recv2() failed: %s",
2370                                  isc_result_totext(result));
2371                 /*
2372                  * This cannot happen in the current implementation, since
2373                  * isc_socket_recv2() cannot fail if flags == 0.
2374                  *
2375                  * If this does fail, we just go idle.
2376                  */
2377                 return;
2378         }
2379         INSIST(client->nrecvs == 0);
2380         client->nrecvs++;
2381 }
2382
2383 void
2384 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2385         REQUIRE(NS_CLIENT_VALID(source));
2386         REQUIRE(targetp != NULL && *targetp == NULL);
2387
2388         source->references++;
2389         ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2390                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2391                       "ns_client_attach: ref = %d", source->references);
2392         *targetp = source;
2393 }
2394
2395 void
2396 ns_client_detach(ns_client_t **clientp) {
2397         ns_client_t *client = *clientp;
2398
2399         client->references--;
2400         INSIST(client->references >= 0);
2401         *clientp = NULL;
2402         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2403                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2404                       "ns_client_detach: ref = %d", client->references);
2405         (void)exit_check(client);
2406 }
2407
2408 isc_boolean_t
2409 ns_client_shuttingdown(ns_client_t *client) {
2410         return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2411 }
2412
2413 isc_result_t
2414 ns_client_replace(ns_client_t *client) {
2415         isc_result_t result;
2416
2417         CTRACE("replace");
2418
2419         REQUIRE(client != NULL);
2420         REQUIRE(client->manager != NULL);
2421
2422         result = get_client(client->manager, client->interface,
2423                             client->dispatch, TCP_CLIENT(client));
2424         if (result != ISC_R_SUCCESS)
2425                 return (result);
2426
2427         /*
2428          * The responsibility for listening for new requests is hereby
2429          * transferred to the new client.  Therefore, the old client
2430          * should refrain from listening for any more requests.
2431          */
2432         client->mortal = ISC_TRUE;
2433
2434         return (ISC_R_SUCCESS);
2435 }
2436
2437 /***
2438  *** Client Manager
2439  ***/
2440
2441 static void
2442 clientmgr_destroy(ns_clientmgr_t *manager) {
2443 #if NMCTXS > 0
2444         int i;
2445 #endif
2446
2447         REQUIRE(ISC_LIST_EMPTY(manager->clients));
2448
2449         MTRACE("clientmgr_destroy");
2450
2451 #if NMCTXS > 0
2452         for (i = 0; i < NMCTXS; i++) {
2453                 if (manager->mctxpool[i] != NULL)
2454                         isc_mem_detach(&manager->mctxpool[i]);
2455         }
2456 #endif
2457
2458         ISC_QUEUE_DESTROY(manager->inactive);
2459         DESTROYLOCK(&manager->lock);
2460         DESTROYLOCK(&manager->listlock);
2461         DESTROYLOCK(&manager->reclock);
2462         manager->magic = 0;
2463         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2464 }
2465
2466 isc_result_t
2467 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2468                     isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2469 {
2470         ns_clientmgr_t *manager;
2471         isc_result_t result;
2472 #if NMCTXS > 0
2473         int i;
2474 #endif
2475
2476         manager = isc_mem_get(mctx, sizeof(*manager));
2477         if (manager == NULL)
2478                 return (ISC_R_NOMEMORY);
2479
2480         result = isc_mutex_init(&manager->lock);
2481         if (result != ISC_R_SUCCESS)
2482                 goto cleanup_manager;
2483
2484         result = isc_mutex_init(&manager->listlock);
2485         if (result != ISC_R_SUCCESS)
2486                 goto cleanup_lock;
2487
2488         result = isc_mutex_init(&manager->reclock);
2489         if (result != ISC_R_SUCCESS)
2490                 goto cleanup_listlock;
2491
2492         manager->mctx = mctx;
2493         manager->taskmgr = taskmgr;
2494         manager->timermgr = timermgr;
2495         manager->exiting = ISC_FALSE;
2496         ISC_LIST_INIT(manager->clients);
2497         ISC_LIST_INIT(manager->recursing);
2498         ISC_QUEUE_INIT(manager->inactive, ilink);
2499 #if NMCTXS > 0
2500         manager->nextmctx = 0;
2501         for (i = 0; i < NMCTXS; i++)
2502                 manager->mctxpool[i] = NULL; /* will be created on-demand */
2503 #endif
2504         manager->magic = MANAGER_MAGIC;
2505
2506         MTRACE("create");
2507
2508         *managerp = manager;
2509
2510         return (ISC_R_SUCCESS);
2511
2512  cleanup_listlock:
2513         (void) isc_mutex_destroy(&manager->listlock);
2514
2515  cleanup_lock:
2516         (void) isc_mutex_destroy(&manager->lock);
2517
2518  cleanup_manager:
2519         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2520
2521         return (result);
2522 }
2523
2524 void
2525 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2526         isc_result_t result;
2527         ns_clientmgr_t *manager;
2528         ns_client_t *client;
2529         isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE;
2530
2531         REQUIRE(managerp != NULL);
2532         manager = *managerp;
2533         REQUIRE(VALID_MANAGER(manager));
2534
2535         MTRACE("destroy");
2536
2537         /*
2538          * Check for success because we may already be task-exclusive
2539          * at this point.  Only if we succeed at obtaining an exclusive
2540          * lock now will we need to relinquish it later.
2541          */
2542         result = isc_task_beginexclusive(ns_g_server->task);
2543         if (result == ISC_R_SUCCESS)
2544                 unlock = ISC_TRUE;
2545
2546         manager->exiting = ISC_TRUE;
2547
2548         for (client = ISC_LIST_HEAD(manager->clients);
2549              client != NULL;
2550              client = ISC_LIST_NEXT(client, link))
2551                 isc_task_shutdown(client->task);
2552
2553         if (ISC_LIST_EMPTY(manager->clients))
2554                 need_destroy = ISC_TRUE;
2555
2556         if (unlock)
2557                 isc_task_endexclusive(ns_g_server->task);
2558
2559         if (need_destroy)
2560                 clientmgr_destroy(manager);
2561
2562         *managerp = NULL;
2563 }
2564
2565 static isc_result_t
2566 get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
2567            dns_dispatch_t *disp, isc_boolean_t tcp)
2568 {
2569         isc_result_t result = ISC_R_SUCCESS;
2570         isc_event_t *ev;
2571         ns_client_t *client;
2572         MTRACE("get client");
2573
2574         REQUIRE(manager != NULL);
2575
2576         if (manager->exiting)
2577                 return (ISC_R_SHUTTINGDOWN);
2578
2579         /*
2580          * Allocate a client.  First try to get a recycled one;
2581          * if that fails, make a new one.
2582          */
2583         client = NULL;
2584         if (!ns_g_clienttest)
2585                 ISC_QUEUE_POP(manager->inactive, ilink, client);
2586
2587         if (client != NULL)
2588                 MTRACE("recycle");
2589         else {
2590                 MTRACE("create new");
2591
2592                 LOCK(&manager->lock);
2593                 result = client_create(manager, &client);
2594                 UNLOCK(&manager->lock);
2595                 if (result != ISC_R_SUCCESS)
2596                         return (result);
2597
2598                 LOCK(&manager->listlock);
2599                 ISC_LIST_APPEND(manager->clients, client, link);
2600                 UNLOCK(&manager->listlock);
2601         }
2602
2603         client->manager = manager;
2604         ns_interface_attach(ifp, &client->interface);
2605         client->state = NS_CLIENTSTATE_READY;
2606         INSIST(client->recursionquota == NULL);
2607
2608         if (tcp) {
2609                 client->attributes |= NS_CLIENTATTR_TCP;
2610                 isc_socket_attach(ifp->tcpsocket,
2611                                   &client->tcplistener);
2612         } else {
2613                 isc_socket_t *sock;
2614
2615                 dns_dispatch_attach(disp, &client->dispatch);
2616                 sock = dns_dispatch_getsocket(client->dispatch);
2617                 isc_socket_attach(sock, &client->udpsocket);
2618         }
2619
2620         INSIST(client->nctls == 0);
2621         client->nctls++;
2622         ev = &client->ctlevent;
2623         isc_task_send(client->task, &ev);
2624
2625         return (ISC_R_SUCCESS);
2626 }
2627
2628 isc_result_t
2629 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2630                            ns_interface_t *ifp, isc_boolean_t tcp)
2631 {
2632         isc_result_t result = ISC_R_SUCCESS;
2633         unsigned int disp;
2634
2635         REQUIRE(VALID_MANAGER(manager));
2636         REQUIRE(n > 0);
2637
2638         MTRACE("createclients");
2639
2640         for (disp = 0; disp < n; disp++) {
2641                 result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);
2642                 if (result != ISC_R_SUCCESS)
2643                         break;
2644         }
2645
2646         return (result);
2647 }
2648
2649 isc_sockaddr_t *
2650 ns_client_getsockaddr(ns_client_t *client) {
2651         return (&client->peeraddr);
2652 }
2653
2654 isc_result_t
2655 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2656                          dns_acl_t *acl, isc_boolean_t default_allow)
2657 {
2658         isc_result_t result;
2659         isc_netaddr_t tmpnetaddr;
2660         int match;
2661
2662         if (acl == NULL) {
2663                 if (default_allow)
2664                         goto allow;
2665                 else
2666                         goto deny;
2667         }
2668
2669         if (netaddr == NULL) {
2670                 isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2671                 netaddr = &tmpnetaddr;
2672         }
2673
2674         result = dns_acl_match(netaddr, client->signer, acl,
2675                                &ns_g_server->aclenv, &match, NULL);
2676
2677         if (result != ISC_R_SUCCESS)
2678                 goto deny; /* Internal error, already logged. */
2679         if (match > 0)
2680                 goto allow;
2681         goto deny; /* Negative match or no match. */
2682
2683  allow:
2684         return (ISC_R_SUCCESS);
2685
2686  deny:
2687         return (DNS_R_REFUSED);
2688 }
2689
2690 isc_result_t
2691 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2692                    const char *opname, dns_acl_t *acl,
2693                    isc_boolean_t default_allow, int log_level)
2694 {
2695         isc_result_t result;
2696         isc_netaddr_t netaddr;
2697
2698         if (sockaddr != NULL)
2699                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2700
2701         result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2702                                           acl, default_allow);
2703
2704         if (result == ISC_R_SUCCESS)
2705                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2706                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2707                               "%s approved", opname);
2708         else
2709                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2710                               NS_LOGMODULE_CLIENT,
2711                               log_level, "%s denied", opname);
2712         return (result);
2713 }
2714
2715 static void
2716 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2717         if (client->peeraddr_valid)
2718                 isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2719         else
2720                 snprintf(peerbuf, len, "@%p", client);
2721 }
2722
2723 void
2724 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2725                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2726 {
2727         char msgbuf[2048];
2728         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2729         char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
2730         const char *viewname = "";
2731         const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
2732         const char *signer = "", *qname = "";
2733         dns_name_t *q = NULL;
2734
2735         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2736
2737         ns_client_name(client, peerbuf, sizeof(peerbuf));
2738
2739         if (client->signer != NULL) {
2740                 dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
2741                 sep1 = "/key ";
2742                 signer = signerbuf;
2743         }
2744
2745         q = client->query.origqname != NULL
2746                 ? client->query.origqname : client->query.qname;
2747         if (q != NULL) {
2748                 dns_name_format(q, qnamebuf, sizeof(qnamebuf));
2749                 sep2 = " (";
2750                 sep3 = ")";
2751                 qname = qnamebuf;
2752         }
2753
2754         if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2755             strcmp(client->view->name, "_default") != 0) {
2756                 sep4 = ": view ";
2757                 viewname = client->view->name;
2758         }
2759
2760         isc_log_write(ns_g_lctx, category, module, level,
2761                       "client %s%s%s%s%s%s%s%s: %s",
2762                       peerbuf, sep1, signer, sep2, qname, sep3,
2763                       sep4, viewname, msgbuf);
2764 }
2765
2766 void
2767 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2768            isc_logmodule_t *module, int level, const char *fmt, ...)
2769 {
2770         va_list ap;
2771
2772         if (! isc_log_wouldlog(ns_g_lctx, level))
2773                 return;
2774
2775         va_start(ap, fmt);
2776         ns_client_logv(client, category, module, level, fmt, ap);
2777         va_end(ap);
2778 }
2779
2780 void
2781 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2782                  dns_rdataclass_t rdclass, char *buf, size_t len)
2783 {
2784         char namebuf[DNS_NAME_FORMATSIZE];
2785         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2786         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2787
2788         dns_name_format(name, namebuf, sizeof(namebuf));
2789         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2790         dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2791         (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2792                        classbuf);
2793 }
2794
2795 static void
2796 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2797         isc_buffer_t buffer;
2798         char *buf = NULL;
2799         int len = 1024;
2800         isc_result_t result;
2801
2802         /*
2803          * Note that these are multiline debug messages.  We want a newline
2804          * to appear in the log after each message.
2805          */
2806
2807         do {
2808                 buf = isc_mem_get(client->mctx, len);
2809                 if (buf == NULL)
2810                         break;
2811                 isc_buffer_init(&buffer, buf, len);
2812                 result = dns_message_totext(client->message,
2813                                             &dns_master_style_debug,
2814                                             0, &buffer);
2815                 if (result == ISC_R_NOSPACE) {
2816                         isc_mem_put(client->mctx, buf, len);
2817                         len += 1024;
2818                 } else if (result == ISC_R_SUCCESS)
2819                         ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2820                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2821                                       "%s\n%.*s", reason,
2822                                        (int)isc_buffer_usedlength(&buffer),
2823                                        buf);
2824         } while (result == ISC_R_NOSPACE);
2825
2826         if (buf != NULL)
2827                 isc_mem_put(client->mctx, buf, len);
2828 }
2829
2830 void
2831 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2832         ns_client_t *client;
2833         char namebuf[DNS_NAME_FORMATSIZE];
2834         char original[DNS_NAME_FORMATSIZE];
2835         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2836         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2837         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2838         const char *name;
2839         const char *sep;
2840         const char *origfor;
2841         dns_rdataset_t *rdataset;
2842
2843         REQUIRE(VALID_MANAGER(manager));
2844
2845         LOCK(&manager->reclock);
2846         client = ISC_LIST_HEAD(manager->recursing);
2847         while (client != NULL) {
2848                 INSIST(client->state == NS_CLIENTSTATE_RECURSING);
2849
2850                 ns_client_name(client, peerbuf, sizeof(peerbuf));
2851                 if (client->view != NULL &&
2852                     strcmp(client->view->name, "_bind") != 0 &&
2853                     strcmp(client->view->name, "_default") != 0) {
2854                         name = client->view->name;
2855                         sep = ": view ";
2856                 } else {
2857                         name = "";
2858                         sep = "";
2859                 }
2860
2861                 LOCK(&client->query.fetchlock);
2862                 INSIST(client->query.qname != NULL);
2863                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2864                 if (client->query.qname != client->query.origqname &&
2865                     client->query.origqname != NULL) {
2866                         origfor = " for ";
2867                         dns_name_format(client->query.origqname, original,
2868                                         sizeof(original));
2869                 } else {
2870                         origfor = "";
2871                         original[0] = '\0';
2872                 }
2873                 rdataset = ISC_LIST_HEAD(client->query.qname->list);
2874                 if (rdataset == NULL && client->query.origqname != NULL)
2875                         rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2876                 if (rdataset != NULL) {
2877                         dns_rdatatype_format(rdataset->type, typebuf,
2878                                              sizeof(typebuf));
2879                         dns_rdataclass_format(rdataset->rdclass, classbuf,
2880                                               sizeof(classbuf));
2881                 } else {
2882                         strcpy(typebuf, "-");
2883                         strcpy(classbuf, "-");
2884                 }
2885                 UNLOCK(&client->query.fetchlock);
2886                 fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2887                         "requesttime %d\n", peerbuf, sep, name,
2888                         client->message->id, namebuf, typebuf, classbuf,
2889                         origfor, original, client->requesttime);
2890                 client = ISC_LIST_NEXT(client, rlink);
2891         }
2892         UNLOCK(&manager->reclock);
2893 }
2894
2895 void
2896 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2897         LOCK(&client->query.fetchlock);
2898         if (client->query.restarts > 0) {
2899                 /*
2900                  * client->query.qname was dynamically allocated.
2901                  */
2902                 dns_message_puttempname(client->message,
2903                                         &client->query.qname);
2904         }
2905         client->query.qname = name;
2906         UNLOCK(&client->query.fetchlock);
2907 }
2908
2909 isc_result_t
2910 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
2911         ns_client_t *client = (ns_client_t *) ci->data;
2912
2913         REQUIRE(NS_CLIENT_VALID(client));
2914         REQUIRE(addrp != NULL);
2915
2916         *addrp = &client->peeraddr;
2917         return (ISC_R_SUCCESS);
2918 }