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