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