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