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