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