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