1 /* $NetBSD: client.c,v 1.13 2015/07/08 17:28:55 christos Exp $ */
4 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: client.c,v 1.286 2012/01/31 23:47:30 tbox Exp */
24 #include <isc/formatcheck.h>
25 #include <isc/mutex.h>
27 #include <isc/platform.h>
28 #include <isc/print.h>
29 #include <isc/queue.h>
30 #include <isc/random.h>
31 #include <isc/serial.h>
32 #include <isc/stats.h>
33 #include <isc/stdio.h>
34 #include <isc/string.h>
36 #include <isc/timer.h>
42 #include <isc/hmacsha.h>
46 #include <dns/dispatch.h>
47 #include <dns/events.h>
48 #include <dns/message.h>
50 #include <dns/rcode.h>
51 #include <dns/rdata.h>
52 #include <dns/rdataclass.h>
53 #include <dns/rdatalist.h>
54 #include <dns/rdataset.h>
55 #include <dns/resolver.h>
56 #include <dns/stats.h>
61 #include <named/interfacemgr.h>
62 #include <named/log.h>
63 #include <named/notify.h>
65 #include <named/server.h>
66 #include <named/update.h>
79 * All client state changes, other than that from idle to listening, occur
80 * as a result of events. This guarantees serialization and avoids the
83 * If a routine is ever created that allows someone other than the client's
84 * task to change the client, then the client will have to be locked.
87 #define NS_CLIENT_TRACE
88 #ifdef NS_CLIENT_TRACE
89 #define CTRACE(m) ns_client_log(client, \
90 NS_LOGCATEGORY_CLIENT, \
91 NS_LOGMODULE_CLIENT, \
94 #define MTRACE(m) isc_log_write(ns_g_lctx, \
95 NS_LOGCATEGORY_GENERAL, \
96 NS_LOGMODULE_CLIENT, \
98 "clientmgr @%p: %s", manager, (m))
100 #define CTRACE(m) ((void)(m))
101 #define MTRACE(m) ((void)(m))
104 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
106 #define TCP_BUFFER_SIZE (65535 + 2)
107 #define SEND_BUFFER_SIZE 4096
108 #define RECV_BUFFER_SIZE 4096
110 #ifdef ISC_PLATFORM_USETHREADS
113 * Number of 'mctx pools' for clients. (Should this be configurable?)
114 * When enabling threads, we use a pool of memory contexts shared by
115 * client objects, since concurrent access to a shared context would cause
116 * heavy contentions. The above constant is expected to be enough for
117 * completely avoiding contentions among threads for an authoritative-only
123 * If named with built without thread, simply share manager's context. Using
124 * a separate context in this case would simply waste memory.
128 #define SIT_SIZE 24U /* 8 + 4 + 4 + 8 */
130 /*% nameserver client manager structure */
131 struct ns_clientmgr
{
135 /* The queue object has its own locks */
136 client_queue_t inactive
; /*%< To be recycled */
139 isc_taskmgr_t
* taskmgr
;
140 isc_timermgr_t
* timermgr
;
142 /* Lock covers manager state. */
144 isc_boolean_t exiting
;
146 /* Lock covers the clients list */
147 isc_mutex_t listlock
;
148 client_list_t clients
; /*%< All active clients */
150 /* Lock covers the recursing list */
152 client_list_t recursing
; /*%< Recursing clients */
155 /*%< mctx pool for clients. */
156 unsigned int nextmctx
;
157 isc_mem_t
* mctxpool
[NMCTXS
];
161 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
162 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
165 * Client object states. Ordering is significant: higher-numbered
166 * states are generally "more active", meaning that the client can
167 * have more dynamically allocated data, outstanding events, etc.
168 * In the list below, any such properties listed for state N
169 * also apply to any state > N.
171 * To force the client into a less active state, set client->newstate
172 * to that state and call exit_check(). This will cause any
173 * activities defined for higher-numbered states to be aborted.
176 #define NS_CLIENTSTATE_FREED 0
178 * The client object no longer exists.
181 #define NS_CLIENTSTATE_INACTIVE 1
183 * The client object exists and has a task and timer.
184 * Its "query" struct and sendbuf are initialized.
185 * It is on the client manager's list of inactive clients.
186 * It has a message and OPT, both in the reset state.
189 #define NS_CLIENTSTATE_READY 2
191 * The client object is either a TCP or a UDP one, and
192 * it is associated with a network interface. It is on the
193 * client manager's list of active clients.
195 * If it is a TCP client object, it has a TCP listener socket
196 * and an outstanding TCP listen request.
198 * If it is a UDP client object, it has a UDP listener socket
199 * and an outstanding UDP receive request.
202 #define NS_CLIENTSTATE_READING 3
204 * The client object is a TCP client object that has received
205 * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
206 * outstanding TCP read request. This state is not used for
207 * UDP client objects.
210 #define NS_CLIENTSTATE_WORKING 4
212 * The client object has received a request and is working
213 * on it. It has a view, and it may have any of a non-reset OPT,
214 * recursion quota, and an outstanding write request.
217 #define NS_CLIENTSTATE_RECURSING 5
219 * The client object is recursing. It will be on the 'recursing'
223 #define NS_CLIENTSTATE_MAX 9
225 * Sentinel value used to indicate "no state". When client->newstate
226 * has this value, we are not attempting to exit the current state.
227 * Must be greater than any valid state.
231 * Enable ns_client_dropport() by default.
233 #ifndef NS_CLIENT_DROPPORT
234 #define NS_CLIENT_DROPPORT 1
237 unsigned int ns_client_requests
;
239 static void client_read(ns_client_t
*client
);
240 static void client_accept(ns_client_t
*client
);
241 static void client_udprecv(ns_client_t
*client
);
242 static void clientmgr_destroy(ns_clientmgr_t
*manager
);
243 static isc_boolean_t
exit_check(ns_client_t
*client
);
244 static void ns_client_endrequest(ns_client_t
*client
);
245 static void client_start(isc_task_t
*task
, isc_event_t
*event
);
246 static void client_request(isc_task_t
*task
, isc_event_t
*event
);
247 static void ns_client_dumpmessage(ns_client_t
*client
, const char *reason
);
248 static isc_result_t
get_client(ns_clientmgr_t
*manager
, ns_interface_t
*ifp
,
249 dns_dispatch_t
*disp
, isc_boolean_t tcp
);
250 static inline isc_boolean_t
251 allowed(isc_netaddr_t
*addr
, dns_name_t
*signer
, dns_acl_t
*acl
);
252 #ifdef ISC_PLATFORM_USESIT
253 static void compute_sit(ns_client_t
*client
, isc_uint32_t when
,
254 isc_uint32_t nonce
, isc_buffer_t
*buf
);
258 ns_client_recursing(ns_client_t
*client
) {
259 REQUIRE(NS_CLIENT_VALID(client
));
260 REQUIRE(client
->state
== NS_CLIENTSTATE_WORKING
);
262 LOCK(&client
->manager
->reclock
);
263 client
->newstate
= client
->state
= NS_CLIENTSTATE_RECURSING
;
264 ISC_LIST_APPEND(client
->manager
->recursing
, client
, rlink
);
265 UNLOCK(&client
->manager
->reclock
);
269 ns_client_killoldestquery(ns_client_t
*client
) {
271 REQUIRE(NS_CLIENT_VALID(client
));
273 LOCK(&client
->manager
->reclock
);
274 oldest
= ISC_LIST_HEAD(client
->manager
->recursing
);
275 if (oldest
!= NULL
) {
276 ISC_LIST_UNLINK(client
->manager
->recursing
, oldest
, rlink
);
277 UNLOCK(&client
->manager
->reclock
);
278 ns_query_cancel(oldest
);
280 UNLOCK(&client
->manager
->reclock
);
284 ns_client_settimeout(ns_client_t
*client
, unsigned int seconds
) {
286 isc_interval_t interval
;
288 isc_interval_set(&interval
, seconds
, 0);
289 result
= isc_timer_reset(client
->timer
, isc_timertype_once
, NULL
,
290 &interval
, ISC_FALSE
);
291 client
->timerset
= ISC_TRUE
;
292 if (result
!= ISC_R_SUCCESS
) {
293 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
294 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
295 "setting timeout: %s",
296 isc_result_totext(result
));
297 /* Continue anyway. */
302 * Check for a deactivation or shutdown request and take appropriate
303 * action. Returns ISC_TRUE if either is in progress; in this case
304 * the caller must no longer use the client object as it may have been
308 exit_check(ns_client_t
*client
) {
309 isc_boolean_t destroy_manager
= ISC_FALSE
;
310 ns_clientmgr_t
*manager
= NULL
;
312 REQUIRE(NS_CLIENT_VALID(client
));
313 manager
= client
->manager
;
315 if (client
->state
<= client
->newstate
)
316 return (ISC_FALSE
); /* Business as usual. */
318 INSIST(client
->newstate
< NS_CLIENTSTATE_RECURSING
);
321 * We need to detach from the view early when shutting down
322 * the server to break the following vicious circle:
324 * - The resolver will not shut down until the view refcount is zero
325 * - The view refcount does not go to zero until all clients detach
326 * - The client does not detach from the view until references is zero
327 * - references does not go to zero until the resolver has shut down
329 * Keep the view attached until any outstanding updates complete.
331 if (client
->nupdates
== 0 &&
332 client
->newstate
== NS_CLIENTSTATE_FREED
&& client
->view
!= NULL
)
333 dns_view_detach(&client
->view
);
335 if (client
->state
== NS_CLIENTSTATE_WORKING
||
336 client
->state
== NS_CLIENTSTATE_RECURSING
)
338 INSIST(client
->newstate
<= NS_CLIENTSTATE_READING
);
340 * Let the update processing complete.
342 if (client
->nupdates
> 0)
346 * We are trying to abort request processing.
348 if (client
->nsends
> 0) {
349 isc_socket_t
*socket
;
350 if (TCP_CLIENT(client
))
351 socket
= client
->tcpsocket
;
353 socket
= client
->udpsocket
;
354 isc_socket_cancel(socket
, client
->task
,
355 ISC_SOCKCANCEL_SEND
);
358 if (! (client
->nsends
== 0 && client
->nrecvs
== 0 &&
359 client
->references
== 0))
362 * Still waiting for I/O cancel completion.
363 * or lingering references.
369 * I/O cancel is complete. Burn down all state
370 * related to the current request. Ensure that
371 * the client is no longer on the recursing list.
373 * We need to check whether the client is still linked,
374 * because it may already have been removed from the
375 * recursing list by ns_client_killoldestquery()
377 if (client
->state
== NS_CLIENTSTATE_RECURSING
) {
378 LOCK(&manager
->reclock
);
379 if (ISC_LINK_LINKED(client
, rlink
))
380 ISC_LIST_UNLINK(manager
->recursing
,
382 UNLOCK(&manager
->reclock
);
384 ns_client_endrequest(client
);
386 client
->state
= NS_CLIENTSTATE_READING
;
387 INSIST(client
->recursionquota
== NULL
);
389 if (NS_CLIENTSTATE_READING
== client
->newstate
) {
391 client
->newstate
= NS_CLIENTSTATE_MAX
;
392 return (ISC_TRUE
); /* We're done. */
396 if (client
->state
== NS_CLIENTSTATE_READING
) {
398 * We are trying to abort the current TCP connection,
401 INSIST(client
->recursionquota
== NULL
);
402 INSIST(client
->newstate
<= NS_CLIENTSTATE_READY
);
403 if (client
->nreads
> 0)
404 dns_tcpmsg_cancelread(&client
->tcpmsg
);
405 if (! client
->nreads
== 0) {
406 /* Still waiting for read cancel completion. */
410 if (client
->tcpmsg_valid
) {
411 dns_tcpmsg_invalidate(&client
->tcpmsg
);
412 client
->tcpmsg_valid
= ISC_FALSE
;
414 if (client
->tcpsocket
!= NULL
) {
416 isc_socket_detach(&client
->tcpsocket
);
419 if (client
->tcpquota
!= NULL
)
420 isc_quota_detach(&client
->tcpquota
);
422 if (client
->timerset
) {
423 (void)isc_timer_reset(client
->timer
,
424 isc_timertype_inactive
,
425 NULL
, NULL
, ISC_TRUE
);
426 client
->timerset
= ISC_FALSE
;
429 client
->peeraddr_valid
= ISC_FALSE
;
431 client
->state
= NS_CLIENTSTATE_READY
;
432 INSIST(client
->recursionquota
== NULL
);
435 * Now the client is ready to accept a new TCP connection
436 * or UDP request, but we may have enough clients doing
437 * that already. Check whether this client needs to remain
438 * active and force it to go inactive if not.
440 * UDP clients go inactive at this point, but TCP clients
441 * may remain active if we have fewer active TCP client
442 * objects than desired due to an earlier quota exhaustion.
444 if (client
->mortal
&& TCP_CLIENT(client
) && !ns_g_clienttest
) {
445 LOCK(&client
->interface
->lock
);
446 if (client
->interface
->ntcpcurrent
<
447 client
->interface
->ntcptarget
)
448 client
->mortal
= ISC_FALSE
;
449 UNLOCK(&client
->interface
->lock
);
453 * We don't need the client; send it to the inactive
454 * queue for recycling.
456 if (client
->mortal
) {
457 if (client
->newstate
> NS_CLIENTSTATE_INACTIVE
)
458 client
->newstate
= NS_CLIENTSTATE_INACTIVE
;
461 if (NS_CLIENTSTATE_READY
== client
->newstate
) {
462 if (TCP_CLIENT(client
)) {
463 client_accept(client
);
465 client_udprecv(client
);
466 client
->newstate
= NS_CLIENTSTATE_MAX
;
471 if (client
->state
== NS_CLIENTSTATE_READY
) {
472 INSIST(client
->newstate
<= NS_CLIENTSTATE_INACTIVE
);
475 * We are trying to enter the inactive state.
477 if (client
->naccepts
> 0)
478 isc_socket_cancel(client
->tcplistener
, client
->task
,
479 ISC_SOCKCANCEL_ACCEPT
);
481 /* Still waiting for accept cancel completion. */
482 if (! (client
->naccepts
== 0))
485 /* Accept cancel is complete. */
486 if (client
->nrecvs
> 0)
487 isc_socket_cancel(client
->udpsocket
, client
->task
,
488 ISC_SOCKCANCEL_RECV
);
490 /* Still waiting for recv cancel completion. */
491 if (! (client
->nrecvs
== 0))
494 /* Still waiting for control event to be delivered */
495 if (client
->nctls
> 0)
498 /* Deactivate the client. */
499 if (client
->interface
)
500 ns_interface_detach(&client
->interface
);
502 INSIST(client
->naccepts
== 0);
503 INSIST(client
->recursionquota
== NULL
);
504 if (client
->tcplistener
!= NULL
)
505 isc_socket_detach(&client
->tcplistener
);
507 if (client
->udpsocket
!= NULL
)
508 isc_socket_detach(&client
->udpsocket
);
510 if (client
->dispatch
!= NULL
)
511 dns_dispatch_detach(&client
->dispatch
);
513 client
->attributes
= 0;
514 client
->mortal
= ISC_FALSE
;
517 * Put the client on the inactive list. If we are aiming for
518 * the "freed" state, it will be removed from the inactive
519 * list shortly, and we need to keep the manager locked until
520 * that has been done, lest the manager decide to reactivate
521 * the dying client inbetween.
523 client
->state
= NS_CLIENTSTATE_INACTIVE
;
524 INSIST(client
->recursionquota
== NULL
);
526 if (client
->state
== client
->newstate
) {
527 client
->newstate
= NS_CLIENTSTATE_MAX
;
528 if (!ns_g_clienttest
&& manager
!= NULL
&&
530 ISC_QUEUE_PUSH(manager
->inactive
, client
,
532 if (client
->needshutdown
)
533 isc_task_shutdown(client
->task
);
538 if (client
->state
== NS_CLIENTSTATE_INACTIVE
) {
539 INSIST(client
->newstate
== NS_CLIENTSTATE_FREED
);
541 * We are trying to free the client.
543 * When "shuttingdown" is true, either the task has received
544 * its shutdown event or no shutdown event has ever been
545 * set up. Thus, we have no outstanding shutdown
546 * event at this point.
548 REQUIRE(client
->state
== NS_CLIENTSTATE_INACTIVE
);
550 INSIST(client
->recursionquota
== NULL
);
551 INSIST(!ISC_QLINK_LINKED(client
, ilink
));
553 if (manager
!= NULL
) {
554 LOCK(&manager
->listlock
);
555 ISC_LIST_UNLINK(manager
->clients
, client
, link
);
556 LOCK(&manager
->lock
);
557 if (manager
->exiting
&&
558 ISC_LIST_EMPTY(manager
->clients
))
559 destroy_manager
= ISC_TRUE
;
560 UNLOCK(&manager
->lock
);
561 UNLOCK(&manager
->listlock
);
564 ns_query_free(client
);
565 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
566 isc_event_free((isc_event_t
**)&client
->sendevent
);
567 isc_event_free((isc_event_t
**)&client
->recvevent
);
568 isc_timer_detach(&client
->timer
);
569 if (client
->delaytimer
!= NULL
)
570 isc_timer_detach(&client
->delaytimer
);
572 if (client
->tcpbuf
!= NULL
)
573 isc_mem_put(client
->mctx
, client
->tcpbuf
,
575 if (client
->opt
!= NULL
) {
576 INSIST(dns_rdataset_isassociated(client
->opt
));
577 dns_rdataset_disassociate(client
->opt
);
578 dns_message_puttemprdataset(client
->message
,
582 dns_message_destroy(&client
->message
);
585 * Detaching the task must be done after unlinking from
586 * the manager's lists because the manager accesses
589 if (client
->task
!= NULL
)
590 isc_task_detach(&client
->task
);
596 * Check that there are no other external references to
597 * the memory context.
599 if (ns_g_clienttest
&& isc_mem_references(client
->mctx
) != 1) {
600 isc_mem_stats(client
->mctx
, stderr
);
605 * Destroy the fetchlock mutex that was created in
608 DESTROYLOCK(&client
->query
.fetchlock
);
610 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
613 if (destroy_manager
&& manager
!= NULL
)
614 clientmgr_destroy(manager
);
620 * The client's task has received the client's control event
621 * as part of the startup process.
624 client_start(isc_task_t
*task
, isc_event_t
*event
) {
625 ns_client_t
*client
= (ns_client_t
*) event
->ev_arg
;
627 INSIST(task
== client
->task
);
631 INSIST(client
->nctls
== 1);
634 if (exit_check(client
))
637 if (TCP_CLIENT(client
)) {
638 client_accept(client
);
640 client_udprecv(client
);
646 * The client's task has received a shutdown event.
649 client_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
652 REQUIRE(event
!= NULL
);
653 REQUIRE(event
->ev_type
== ISC_TASKEVENT_SHUTDOWN
);
654 client
= event
->ev_arg
;
655 REQUIRE(NS_CLIENT_VALID(client
));
656 REQUIRE(task
== client
->task
);
662 isc_event_free(&event
);
664 if (client
->shutdown
!= NULL
) {
665 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_SHUTTINGDOWN
);
666 client
->shutdown
= NULL
;
667 client
->shutdown_arg
= NULL
;
670 if (ISC_QLINK_LINKED(client
, ilink
))
671 ISC_QUEUE_UNLINK(client
->manager
->inactive
, client
, ilink
);
673 client
->newstate
= NS_CLIENTSTATE_FREED
;
674 client
->needshutdown
= ISC_FALSE
;
675 (void)exit_check(client
);
679 ns_client_endrequest(ns_client_t
*client
) {
680 INSIST(client
->naccepts
== 0);
681 INSIST(client
->nreads
== 0);
682 INSIST(client
->nsends
== 0);
683 INSIST(client
->nrecvs
== 0);
684 INSIST(client
->nupdates
== 0);
685 INSIST(client
->state
== NS_CLIENTSTATE_WORKING
||
686 client
->state
== NS_CLIENTSTATE_RECURSING
);
688 CTRACE("endrequest");
690 if (client
->next
!= NULL
) {
691 (client
->next
)(client
);
695 if (client
->view
!= NULL
)
696 dns_view_detach(&client
->view
);
697 if (client
->opt
!= NULL
) {
698 INSIST(dns_rdataset_isassociated(client
->opt
));
699 dns_rdataset_disassociate(client
->opt
);
700 dns_message_puttemprdataset(client
->message
, &client
->opt
);
703 client
->signer
= NULL
;
704 client
->udpsize
= 512;
705 client
->extflags
= 0;
706 client
->ednsversion
= -1;
707 dns_message_reset(client
->message
, DNS_MESSAGE_INTENTPARSE
);
709 if (client
->recursionquota
!= NULL
) {
710 isc_quota_detach(&client
->recursionquota
);
711 isc_stats_decrement(ns_g_server
->nsstats
,
712 dns_nsstatscounter_recursclients
);
716 * Clear all client attributes that are specific to
717 * the request; that's all except the TCP flag.
719 client
->attributes
&= NS_CLIENTATTR_TCP
;
723 ns_client_next(ns_client_t
*client
, isc_result_t result
) {
726 REQUIRE(NS_CLIENT_VALID(client
));
727 REQUIRE(client
->state
== NS_CLIENTSTATE_WORKING
||
728 client
->state
== NS_CLIENTSTATE_RECURSING
||
729 client
->state
== NS_CLIENTSTATE_READING
);
733 if (result
!= ISC_R_SUCCESS
)
734 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
735 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
736 "request failed: %s", isc_result_totext(result
));
739 * An error processing a TCP request may have left
740 * the connection out of sync. To be safe, we always
741 * sever the connection when result != ISC_R_SUCCESS.
743 if (result
== ISC_R_SUCCESS
&& TCP_CLIENT(client
))
744 newstate
= NS_CLIENTSTATE_READING
;
746 newstate
= NS_CLIENTSTATE_READY
;
748 if (client
->newstate
> newstate
)
749 client
->newstate
= newstate
;
750 (void)exit_check(client
);
755 client_senddone(isc_task_t
*task
, isc_event_t
*event
) {
757 isc_socketevent_t
*sevent
= (isc_socketevent_t
*) event
;
759 REQUIRE(sevent
!= NULL
);
760 REQUIRE(sevent
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
761 client
= sevent
->ev_arg
;
762 REQUIRE(NS_CLIENT_VALID(client
));
763 REQUIRE(task
== client
->task
);
764 REQUIRE(sevent
== client
->sendevent
);
770 if (sevent
->result
!= ISC_R_SUCCESS
)
771 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
772 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
773 "error sending response: %s",
774 isc_result_totext(sevent
->result
));
776 INSIST(client
->nsends
> 0);
779 if (client
->tcpbuf
!= NULL
) {
780 INSIST(TCP_CLIENT(client
));
781 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
782 client
->tcpbuf
= NULL
;
785 ns_client_next(client
, ISC_R_SUCCESS
);
789 * We only want to fail with ISC_R_NOSPACE when called from
790 * ns_client_sendraw() and not when called from ns_client_send(),
791 * tcpbuffer is NULL when called from ns_client_sendraw() and
792 * length != 0. tcpbuffer != NULL when called from ns_client_send()
797 client_allocsendbuf(ns_client_t
*client
, isc_buffer_t
*buffer
,
798 isc_buffer_t
*tcpbuffer
, isc_uint32_t length
,
799 unsigned char *sendbuf
, unsigned char **datap
)
802 isc_uint32_t bufsize
;
805 INSIST(datap
!= NULL
);
806 INSIST((tcpbuffer
== NULL
&& length
!= 0) ||
807 (tcpbuffer
!= NULL
&& length
== 0));
809 if (TCP_CLIENT(client
)) {
810 INSIST(client
->tcpbuf
== NULL
);
811 if (length
+ 2 > TCP_BUFFER_SIZE
) {
812 result
= ISC_R_NOSPACE
;
815 client
->tcpbuf
= isc_mem_get(client
->mctx
, TCP_BUFFER_SIZE
);
816 if (client
->tcpbuf
== NULL
) {
817 result
= ISC_R_NOMEMORY
;
820 data
= client
->tcpbuf
;
821 if (tcpbuffer
!= NULL
) {
822 isc_buffer_init(tcpbuffer
, data
, TCP_BUFFER_SIZE
);
823 isc_buffer_init(buffer
, data
+ 2, TCP_BUFFER_SIZE
- 2);
825 isc_buffer_init(buffer
, data
, TCP_BUFFER_SIZE
);
826 INSIST(length
<= 0xffff);
827 isc_buffer_putuint16(buffer
, (isc_uint16_t
)length
);
831 #ifdef ISC_PLATFORM_USESIT
832 if ((client
->attributes
& NS_CLIENTATTR_HAVESIT
) == 0) {
833 if (client
->view
!= NULL
)
834 bufsize
= client
->view
->situdp
;
838 bufsize
= client
->udpsize
;
839 if (bufsize
> client
->udpsize
)
840 bufsize
= client
->udpsize
;
841 if (bufsize
> SEND_BUFFER_SIZE
)
842 bufsize
= SEND_BUFFER_SIZE
;
844 if (client
->udpsize
< SEND_BUFFER_SIZE
)
845 bufsize
= client
->udpsize
;
847 bufsize
= SEND_BUFFER_SIZE
;
849 if (length
> bufsize
) {
850 result
= ISC_R_NOSPACE
;
853 isc_buffer_init(buffer
, data
, bufsize
);
856 result
= ISC_R_SUCCESS
;
863 client_sendpkg(ns_client_t
*client
, isc_buffer_t
*buffer
) {
864 struct in6_pktinfo
*pktinfo
;
867 isc_sockaddr_t
*address
;
868 isc_socket_t
*socket
;
869 isc_netaddr_t netaddr
;
871 unsigned int sockflags
= ISC_SOCKFLAG_IMMEDIATE
;
872 isc_dscp_t dispdscp
= -1;
874 if (TCP_CLIENT(client
)) {
875 socket
= client
->tcpsocket
;
878 socket
= client
->udpsocket
;
879 address
= &client
->peeraddr
;
881 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
882 if (ns_g_server
->blackholeacl
!= NULL
&&
883 dns_acl_match(&netaddr
, NULL
,
884 ns_g_server
->blackholeacl
,
885 &ns_g_server
->aclenv
,
886 &match
, NULL
) == ISC_R_SUCCESS
&&
888 return (DNS_R_BLACKHOLED
);
889 sockflags
|= ISC_SOCKFLAG_NORETRY
;
892 if ((client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0 &&
893 (client
->attributes
& NS_CLIENTATTR_MULTICAST
) == 0)
894 pktinfo
= &client
->pktinfo
;
898 if (client
->dispatch
!= NULL
) {
899 dispdscp
= dns_dispatch_getdscp(client
->dispatch
);
901 client
->dscp
= dispdscp
;
904 if (client
->dscp
== -1) {
905 client
->sendevent
->attributes
&= ~ISC_SOCKEVENTATTR_DSCP
;
906 client
->sendevent
->dscp
= 0;
908 client
->sendevent
->attributes
|= ISC_SOCKEVENTATTR_DSCP
;
909 client
->sendevent
->dscp
= client
->dscp
;
912 isc_buffer_usedregion(buffer
, &r
);
916 result
= isc_socket_sendto2(socket
, &r
, client
->task
,
918 client
->sendevent
, sockflags
);
919 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_INPROGRESS
) {
921 if (result
== ISC_R_SUCCESS
)
922 client_senddone(client
->task
,
923 (isc_event_t
*)client
->sendevent
);
924 result
= ISC_R_SUCCESS
;
930 ns_client_sendraw(ns_client_t
*client
, dns_message_t
*message
) {
936 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
938 REQUIRE(NS_CLIENT_VALID(client
));
942 mr
= dns_message_getrawmessage(message
);
944 result
= ISC_R_UNEXPECTEDEND
;
948 result
= client_allocsendbuf(client
, &buffer
, NULL
, mr
->length
,
950 if (result
!= ISC_R_SUCCESS
)
954 * Copy message to buffer and fixup id.
956 isc_buffer_availableregion(&buffer
, &r
);
957 result
= isc_buffer_copyregion(&buffer
, mr
);
958 if (result
!= ISC_R_SUCCESS
)
960 r
.base
[0] = (client
->message
->id
>> 8) & 0xff;
961 r
.base
[1] = client
->message
->id
& 0xff;
963 result
= client_sendpkg(client
, &buffer
);
964 if (result
== ISC_R_SUCCESS
)
968 if (client
->tcpbuf
!= NULL
) {
969 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
970 client
->tcpbuf
= NULL
;
972 ns_client_next(client
, result
);
976 client_send(ns_client_t
*client
) {
980 isc_buffer_t tcpbuffer
;
983 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
984 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
985 unsigned int render_opts
;
986 unsigned int preferred_glue
;
987 isc_boolean_t opt_included
= ISC_FALSE
;
989 REQUIRE(NS_CLIENT_VALID(client
));
993 if ((client
->attributes
& NS_CLIENTATTR_RA
) != 0)
994 client
->message
->flags
|= DNS_MESSAGEFLAG_RA
;
996 if ((client
->attributes
& NS_CLIENTATTR_WANTDNSSEC
) != 0)
999 render_opts
= DNS_MESSAGERENDER_OMITDNSSEC
;
1002 if (client
->view
!= NULL
) {
1003 if (client
->view
->preferred_glue
== dns_rdatatype_a
)
1004 preferred_glue
= DNS_MESSAGERENDER_PREFER_A
;
1005 else if (client
->view
->preferred_glue
== dns_rdatatype_aaaa
)
1006 preferred_glue
= DNS_MESSAGERENDER_PREFER_AAAA
;
1009 #ifdef ALLOW_FILTER_AAAA
1011 * filter-aaaa-on-v4 yes or break-dnssec option to suppress
1014 * We already know that request came via IPv4,
1015 * that we have both AAAA and A records,
1016 * and that we either have no signatures that the client wants
1017 * or we are supposed to break DNSSEC.
1019 * Override preferred glue if necessary.
1021 if ((client
->attributes
& NS_CLIENTATTR_FILTER_AAAA
) != 0) {
1022 render_opts
|= DNS_MESSAGERENDER_FILTER_AAAA
;
1023 if (preferred_glue
== DNS_MESSAGERENDER_PREFER_AAAA
)
1024 preferred_glue
= DNS_MESSAGERENDER_PREFER_A
;
1029 * Create an OPT for our reply.
1031 if ((client
->attributes
& NS_CLIENTATTR_WANTOPT
) != 0) {
1032 result
= ns_client_addopt(client
, client
->message
,
1034 if (result
!= ISC_R_SUCCESS
)
1039 * XXXRTH The following doesn't deal with TCP buffer resizing.
1041 result
= client_allocsendbuf(client
, &buffer
, &tcpbuffer
, 0,
1043 if (result
!= ISC_R_SUCCESS
)
1046 result
= dns_compress_init(&cctx
, -1, client
->mctx
);
1047 if (result
!= ISC_R_SUCCESS
)
1049 if (client
->peeraddr_valid
&& client
->view
!= NULL
) {
1050 isc_netaddr_t netaddr
;
1051 dns_name_t
*name
= NULL
;
1053 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1054 if (client
->message
->tsigkey
!= NULL
)
1055 name
= &client
->message
->tsigkey
->name
;
1056 if (client
->view
->nocasecompress
== NULL
||
1057 !allowed(&netaddr
, name
, client
->view
->nocasecompress
))
1059 dns_compress_setsensitive(&cctx
, ISC_TRUE
);
1062 cleanup_cctx
= ISC_TRUE
;
1064 result
= dns_message_renderbegin(client
->message
, &cctx
, &buffer
);
1065 if (result
!= ISC_R_SUCCESS
)
1068 if (client
->opt
!= NULL
) {
1069 result
= dns_message_setopt(client
->message
, client
->opt
);
1070 opt_included
= ISC_TRUE
;
1072 if (result
!= ISC_R_SUCCESS
)
1075 result
= dns_message_rendersection(client
->message
,
1076 DNS_SECTION_QUESTION
, 0);
1077 if (result
== ISC_R_NOSPACE
) {
1078 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
1081 if (result
!= ISC_R_SUCCESS
)
1084 * Stop after the question if TC was set for rate limiting.
1086 if ((client
->message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
1088 result
= dns_message_rendersection(client
->message
,
1090 DNS_MESSAGERENDER_PARTIAL
|
1092 if (result
== ISC_R_NOSPACE
) {
1093 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
1096 if (result
!= ISC_R_SUCCESS
)
1098 result
= dns_message_rendersection(client
->message
,
1099 DNS_SECTION_AUTHORITY
,
1100 DNS_MESSAGERENDER_PARTIAL
|
1102 if (result
== ISC_R_NOSPACE
) {
1103 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
1106 if (result
!= ISC_R_SUCCESS
)
1108 result
= dns_message_rendersection(client
->message
,
1109 DNS_SECTION_ADDITIONAL
,
1110 preferred_glue
| render_opts
);
1111 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
1114 result
= dns_message_renderend(client
->message
);
1116 if (result
!= ISC_R_SUCCESS
)
1120 dns_compress_invalidate(&cctx
);
1121 cleanup_cctx
= ISC_FALSE
;
1124 if (TCP_CLIENT(client
)) {
1125 isc_buffer_usedregion(&buffer
, &r
);
1126 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
) r
.length
);
1127 isc_buffer_add(&tcpbuffer
, r
.length
);
1128 result
= client_sendpkg(client
, &tcpbuffer
);
1130 result
= client_sendpkg(client
, &buffer
);
1132 /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1133 isc_stats_increment(ns_g_server
->nsstats
, dns_nsstatscounter_response
);
1135 isc_stats_increment(ns_g_server
->nsstats
,
1136 dns_nsstatscounter_edns0out
);
1138 if (client
->message
->tsigkey
!= NULL
) {
1139 isc_stats_increment(ns_g_server
->nsstats
,
1140 dns_nsstatscounter_tsigout
);
1142 if (client
->message
->sig0key
!= NULL
) {
1143 isc_stats_increment(ns_g_server
->nsstats
,
1144 dns_nsstatscounter_sig0out
);
1146 if ((client
->message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
1147 isc_stats_increment(ns_g_server
->nsstats
,
1148 dns_nsstatscounter_truncatedresp
);
1150 if (result
== ISC_R_SUCCESS
)
1154 if (client
->tcpbuf
!= NULL
) {
1155 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
1156 client
->tcpbuf
= NULL
;
1160 dns_compress_invalidate(&cctx
);
1162 ns_client_next(client
, result
);
1166 * Completes the sending of a delayed client response.
1169 client_delay(isc_task_t
*task
, isc_event_t
*event
) {
1170 ns_client_t
*client
;
1172 REQUIRE(event
!= NULL
);
1173 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_LIFE
||
1174 event
->ev_type
== ISC_TIMEREVENT_IDLE
);
1175 client
= event
->ev_arg
;
1176 REQUIRE(NS_CLIENT_VALID(client
));
1177 REQUIRE(task
== client
->task
);
1178 REQUIRE(client
->delaytimer
!= NULL
);
1182 CTRACE("client_delay");
1184 isc_event_free(&event
);
1185 isc_timer_detach(&client
->delaytimer
);
1187 client_send(client
);
1188 ns_client_detach(&client
);
1192 ns_client_send(ns_client_t
*client
) {
1195 * Delay the response by ns_g_delay ms.
1197 if (ns_g_delay
!= 0) {
1198 ns_client_t
*dummy
= NULL
;
1199 isc_result_t result
;
1200 isc_interval_t interval
;
1203 * Replace ourselves if we have not already been replaced.
1205 if (!client
->mortal
) {
1206 result
= ns_client_replace(client
);
1207 if (result
!= ISC_R_SUCCESS
)
1211 ns_client_attach(client
, &dummy
);
1212 if (ns_g_delay
>= 1000)
1213 isc_interval_set(&interval
, ns_g_delay
/ 1000,
1214 (ns_g_delay
% 1000) * 1000000);
1216 isc_interval_set(&interval
, 0, ns_g_delay
* 1000000);
1217 result
= isc_timer_create(client
->manager
->timermgr
,
1218 isc_timertype_once
, NULL
, &interval
,
1219 client
->task
, client_delay
,
1220 client
, &client
->delaytimer
);
1221 if (result
== ISC_R_SUCCESS
)
1224 ns_client_detach(&dummy
);
1228 client_send(client
);
1231 #if NS_CLIENT_DROPPORT
1232 #define DROPPORT_NO 0
1233 #define DROPPORT_REQUEST 1
1234 #define DROPPORT_RESPONSE 2
1236 * ns_client_dropport determines if certain requests / responses
1237 * should be dropped based on the port number.
1240 * \li 0: Don't drop.
1241 * \li 1: Drop request.
1242 * \li 2: Drop (error) response.
1245 ns_client_dropport(in_port_t port
) {
1248 case 13: /* daytime */
1249 case 19: /* chargen */
1251 return (DROPPORT_REQUEST
);
1252 case 464: /* kpasswd */
1253 return (DROPPORT_RESPONSE
);
1255 return (DROPPORT_NO
);
1260 ns_client_error(ns_client_t
*client
, isc_result_t result
) {
1262 dns_message_t
*message
;
1264 REQUIRE(NS_CLIENT_VALID(client
));
1268 message
= client
->message
;
1269 rcode
= dns_result_torcode(result
);
1271 #if NS_CLIENT_DROPPORT
1273 * Don't send FORMERR to ports on the drop port list.
1275 if (rcode
== dns_rcode_formerr
&&
1276 ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) !=
1281 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
1282 if (dns_rcode_totext(rcode
, &b
) != ISC_R_SUCCESS
)
1283 isc_buffer_putstr(&b
, "UNKNOWN RCODE");
1284 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1285 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1286 "dropped error (%.*s) response: suspicious port",
1287 (int)isc_buffer_usedlength(&b
), buf
);
1288 ns_client_next(client
, ISC_R_SUCCESS
);
1294 * Try to rate limit error responses.
1296 if (client
->view
!= NULL
&& client
->view
->rrl
!= NULL
) {
1297 isc_boolean_t wouldlog
;
1298 char log_buf
[DNS_RRL_LOG_BUF_LEN
];
1299 dns_rrl_result_t rrl_result
;
1301 INSIST(rcode
!= dns_rcode_noerror
&&
1302 rcode
!= dns_rcode_nxdomain
);
1303 wouldlog
= isc_log_wouldlog(ns_g_lctx
, DNS_RRL_LOG_DROP
);
1304 rrl_result
= dns_rrl(client
->view
, &client
->peeraddr
,
1306 dns_rdataclass_in
, dns_rdatatype_none
,
1307 NULL
, result
, client
->now
,
1308 wouldlog
, log_buf
, sizeof(log_buf
));
1309 if (rrl_result
!= DNS_RRL_RESULT_OK
) {
1311 * Log dropped errors in the query category
1312 * so that they are not lost in silence.
1313 * Starts of rate-limited bursts are logged in
1314 * NS_LOGCATEGORY_RRL.
1317 ns_client_log(client
,
1318 NS_LOGCATEGORY_QUERY_EERRORS
,
1319 NS_LOGMODULE_CLIENT
,
1324 * Some error responses cannot be 'slipped',
1325 * so don't try to slip any error responses.
1327 if (!client
->view
->rrl
->log_only
) {
1328 isc_stats_increment(ns_g_server
->nsstats
,
1329 dns_nsstatscounter_ratedropped
);
1330 isc_stats_increment(ns_g_server
->nsstats
,
1331 dns_nsstatscounter_dropped
);
1332 ns_client_next(client
, DNS_R_DROP
);
1339 * Message may be an in-progress reply that we had trouble
1340 * with, in which case QR will be set. We need to clear QR before
1341 * calling dns_message_reply() to avoid triggering an assertion.
1343 message
->flags
&= ~DNS_MESSAGEFLAG_QR
;
1345 * AA and AD shouldn't be set.
1347 message
->flags
&= ~(DNS_MESSAGEFLAG_AA
| DNS_MESSAGEFLAG_AD
);
1348 result
= dns_message_reply(message
, ISC_TRUE
);
1349 if (result
!= ISC_R_SUCCESS
) {
1351 * It could be that we've got a query with a good header,
1352 * but a bad question section, so we try again with
1353 * want_question_section set to ISC_FALSE.
1355 result
= dns_message_reply(message
, ISC_FALSE
);
1356 if (result
!= ISC_R_SUCCESS
) {
1357 ns_client_next(client
, result
);
1361 message
->rcode
= rcode
;
1364 * FORMERR loop avoidance: If we sent a FORMERR message
1365 * with the same ID to the same client less than two
1366 * seconds ago, assume that we are in an infinite error
1367 * packet dialog with a server for some protocol whose
1368 * error responses look enough like DNS queries to
1369 * elicit a FORMERR response. Drop a packet to break
1372 if (rcode
== dns_rcode_formerr
) {
1373 if (isc_sockaddr_equal(&client
->peeraddr
,
1374 &client
->formerrcache
.addr
) &&
1375 message
->id
== client
->formerrcache
.id
&&
1376 client
->requesttime
- client
->formerrcache
.time
< 2) {
1378 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1379 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1380 "possible error packet loop, "
1382 ns_client_next(client
, result
);
1385 client
->formerrcache
.addr
= client
->peeraddr
;
1386 client
->formerrcache
.time
= client
->requesttime
;
1387 client
->formerrcache
.id
= message
->id
;
1389 ns_client_send(client
);
1393 ns_client_addopt(ns_client_t
*client
, dns_message_t
*message
,
1394 dns_rdataset_t
**opt
)
1396 char nsid
[BUFSIZ
], *nsidp
;
1397 #ifdef ISC_PLATFORM_USESIT
1398 unsigned char sit
[SIT_SIZE
];
1400 isc_result_t result
;
1402 dns_resolver_t
*resolver
;
1403 isc_uint16_t udpsize
;
1404 dns_ednsopt_t ednsopts
[DNS_EDNSOPTIONS
];
1407 unsigned char expire
[4];
1409 REQUIRE(NS_CLIENT_VALID(client
));
1410 REQUIRE(opt
!= NULL
&& *opt
== NULL
);
1411 REQUIRE(message
!= NULL
);
1413 view
= client
->view
;
1414 resolver
= (view
!= NULL
) ? view
->resolver
: NULL
;
1415 if (resolver
!= NULL
)
1416 udpsize
= dns_resolver_getudpsize(resolver
);
1418 udpsize
= ns_g_udpsize
;
1420 flags
= client
->extflags
& DNS_MESSAGEEXTFLAG_REPLYPRESERVE
;
1422 /* Set EDNS options if applicable */
1423 if ((client
->attributes
& NS_CLIENTATTR_WANTNSID
) != 0 &&
1424 (ns_g_server
->server_id
!= NULL
||
1425 ns_g_server
->server_usehostname
)) {
1426 if (ns_g_server
->server_usehostname
) {
1427 result
= ns_os_gethostname(nsid
, sizeof(nsid
));
1428 if (result
!= ISC_R_SUCCESS
) {
1433 nsidp
= ns_g_server
->server_id
;
1435 INSIST(count
< DNS_EDNSOPTIONS
);
1436 ednsopts
[count
].code
= DNS_OPT_NSID
;
1437 ednsopts
[count
].length
= strlen(nsidp
);
1438 ednsopts
[count
].value
= (unsigned char *)nsidp
;
1442 #ifdef ISC_PLATFORM_USESIT
1443 if ((client
->attributes
& NS_CLIENTATTR_WANTSIT
) != 0) {
1448 isc_buffer_init(&buf
, sit
, sizeof(sit
));
1449 isc_stdtime_get(&now
);
1450 isc_random_get(&nonce
);
1452 compute_sit(client
, now
, nonce
, &buf
);
1454 INSIST(count
< DNS_EDNSOPTIONS
);
1455 ednsopts
[count
].code
= DNS_OPT_SIT
;
1456 ednsopts
[count
].length
= SIT_SIZE
;
1457 ednsopts
[count
].value
= sit
;
1461 if ((client
->attributes
& NS_CLIENTATTR_HAVEEXPIRE
) != 0) {
1464 INSIST(count
< DNS_EDNSOPTIONS
);
1466 isc_buffer_init(&buf
, expire
, sizeof(expire
));
1467 isc_buffer_putuint32(&buf
, client
->expire
);
1468 ednsopts
[count
].code
= DNS_OPT_EXPIRE
;
1469 ednsopts
[count
].length
= 4;
1470 ednsopts
[count
].value
= expire
;
1474 result
= dns_message_buildopt(message
, opt
, 0, udpsize
, flags
,
1479 static inline isc_boolean_t
1480 allowed(isc_netaddr_t
*addr
, dns_name_t
*signer
, dns_acl_t
*acl
) {
1482 isc_result_t result
;
1486 result
= dns_acl_match(addr
, signer
, acl
, &ns_g_server
->aclenv
,
1488 if (result
== ISC_R_SUCCESS
&& match
> 0)
1494 * Callback to see if a non-recursive query coming from 'srcaddr' to
1495 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1496 * delivered to 'myview'.
1498 * We run this unlocked as both the view list and the interface list
1499 * are updated when the appropriate task has exclusivity.
1502 ns_client_isself(dns_view_t
*myview
, dns_tsigkey_t
*mykey
,
1503 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*dstaddr
,
1504 dns_rdataclass_t rdclass
, void *arg
)
1507 dns_tsigkey_t
*key
= NULL
;
1508 dns_name_t
*tsig
= NULL
;
1509 isc_netaddr_t netsrc
;
1510 isc_netaddr_t netdst
;
1515 * ns_g_server->interfacemgr is task exclusive locked.
1517 if (ns_g_server
->interfacemgr
== NULL
)
1520 if (!ns_interfacemgr_listeningon(ns_g_server
->interfacemgr
, dstaddr
))
1523 isc_netaddr_fromsockaddr(&netsrc
, srcaddr
);
1524 isc_netaddr_fromsockaddr(&netdst
, dstaddr
);
1526 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1528 view
= ISC_LIST_NEXT(view
, link
)) {
1530 if (view
->matchrecursiveonly
)
1533 if (rdclass
!= view
->rdclass
)
1536 if (mykey
!= NULL
) {
1537 isc_boolean_t match
;
1538 isc_result_t result
;
1540 result
= dns_view_gettsig(view
, &mykey
->name
, &key
);
1541 if (result
!= ISC_R_SUCCESS
)
1543 match
= dst_key_compare(mykey
->key
, key
->key
);
1544 dns_tsigkey_detach(&key
);
1547 tsig
= dns_tsigkey_identity(mykey
);
1550 if (allowed(&netsrc
, tsig
, view
->matchclients
) &&
1551 allowed(&netdst
, tsig
, view
->matchdestinations
))
1554 return (ISC_TF(view
== myview
));
1557 #ifdef ISC_PLATFORM_USESIT
1559 compute_sit(ns_client_t
*client
, isc_uint32_t when
, isc_uint32_t nonce
,
1563 unsigned char digest
[ISC_AES_BLOCK_LENGTH
];
1564 unsigned char input
[4 + 4 + 16];
1565 isc_netaddr_t netaddr
;
1569 memset(input
, 0, sizeof(input
));
1570 cp
= isc_buffer_used(buf
);
1571 isc_buffer_putmem(buf
, client
->cookie
, 8);
1572 isc_buffer_putuint32(buf
, nonce
);
1573 isc_buffer_putuint32(buf
, when
);
1574 memmove(input
, cp
, 16);
1575 isc_aes128_crypt(ns_g_server
->secret
, input
, digest
);
1576 for (i
= 0; i
< 8; i
++)
1577 input
[i
] = digest
[i
] ^ digest
[i
+ 8];
1578 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1579 switch (netaddr
.family
) {
1581 memmove(input
+ 8, (unsigned char *)&netaddr
.type
.in
, 4);
1582 memset(input
+ 12, 0, 4);
1583 isc_aes128_crypt(ns_g_server
->secret
, input
, digest
);
1586 memmove(input
+ 8, (unsigned char *)&netaddr
.type
.in6
, 16);
1587 isc_aes128_crypt(ns_g_server
->secret
, input
, digest
);
1588 for (i
= 0; i
< 8; i
++)
1589 input
[i
+ 8] = digest
[i
] ^ digest
[i
+ 8];
1590 isc_aes128_crypt(ns_g_server
->secret
, input
+ 8, digest
);
1593 for (i
= 0; i
< 8; i
++)
1594 digest
[i
] ^= digest
[i
+ 8];
1595 isc_buffer_putmem(buf
, digest
, 8);
1597 #ifdef HMAC_SHA1_SIT
1598 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
1599 isc_netaddr_t netaddr
;
1601 isc_hmacsha1_t hmacsha1
;
1603 cp
= isc_buffer_used(buf
);
1604 isc_buffer_putmem(buf
, client
->cookie
, 8);
1605 isc_buffer_putuint32(buf
, nonce
);
1606 isc_buffer_putuint32(buf
, when
);
1608 isc_hmacsha1_init(&hmacsha1
,
1609 ns_g_server
->secret
,
1610 ISC_SHA1_DIGESTLENGTH
);
1611 isc_hmacsha1_update(&hmacsha1
, cp
, 16);
1612 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1613 switch (netaddr
.family
) {
1615 isc_hmacsha1_update(&hmacsha1
,
1616 (unsigned char *)&netaddr
.type
.in
, 4);
1619 isc_hmacsha1_update(&hmacsha1
,
1620 (unsigned char *)&netaddr
.type
.in6
, 16);
1623 isc_hmacsha1_update(&hmacsha1
, client
->cookie
, sizeof(client
->cookie
));
1624 isc_hmacsha1_sign(&hmacsha1
, digest
, sizeof(digest
));
1625 isc_buffer_putmem(buf
, digest
, 8);
1626 isc_hmacsha1_invalidate(&hmacsha1
);
1628 #ifdef HMAC_SHA256_SIT
1629 unsigned char digest
[ISC_SHA256_DIGESTLENGTH
];
1630 isc_netaddr_t netaddr
;
1632 isc_hmacsha256_t hmacsha256
;
1634 cp
= isc_buffer_used(buf
);
1635 isc_buffer_putmem(buf
, client
->cookie
, 8);
1636 isc_buffer_putuint32(buf
, nonce
);
1637 isc_buffer_putuint32(buf
, when
);
1639 isc_hmacsha256_init(&hmacsha256
,
1640 ns_g_server
->secret
,
1641 ISC_SHA256_DIGESTLENGTH
);
1642 isc_hmacsha256_update(&hmacsha256
, cp
, 16);
1643 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1644 switch (netaddr
.family
) {
1646 isc_hmacsha256_update(&hmacsha256
,
1647 (unsigned char *)&netaddr
.type
.in
, 4);
1650 isc_hmacsha256_update(&hmacsha256
,
1651 (unsigned char *)&netaddr
.type
.in6
, 16);
1654 isc_hmacsha256_update(&hmacsha256
, client
->cookie
,
1655 sizeof(client
->cookie
));
1656 isc_hmacsha256_sign(&hmacsha256
, digest
, sizeof(digest
));
1657 isc_buffer_putmem(buf
, digest
, 8);
1658 isc_hmacsha256_invalidate(&hmacsha256
);
1663 process_sit(ns_client_t
*client
, isc_buffer_t
*buf
, size_t optlen
) {
1664 unsigned char dbuf
[SIT_SIZE
];
1671 client
->attributes
|= NS_CLIENTATTR_WANTSIT
;
1673 isc_stats_increment(ns_g_server
->nsstats
,
1674 dns_nsstatscounter_sitopt
);
1676 if (optlen
!= SIT_SIZE
) {
1681 memmove(client
->cookie
, isc_buffer_current(buf
), 8);
1683 memset(client
->cookie
, 0, 8);
1684 isc_buffer_forward(buf
, (unsigned int)optlen
);
1687 isc_stats_increment(ns_g_server
->nsstats
,
1688 dns_nsstatscounter_sitnew
);
1690 isc_stats_increment(ns_g_server
->nsstats
,
1691 dns_nsstatscounter_sitbadsize
);
1696 * Process all of the incoming buffer.
1698 old
= isc_buffer_current(buf
);
1699 memmove(client
->cookie
, old
, 8);
1700 isc_buffer_forward(buf
, 8);
1701 nonce
= isc_buffer_getuint32(buf
);
1702 when
= isc_buffer_getuint32(buf
);
1703 isc_buffer_forward(buf
, 8);
1706 * Allow for a 5 minute clock skew between servers sharing a secret.
1707 * Only accept SIT if we have talked to the client in the last hour.
1709 isc_stdtime_get(&now
);
1710 if (isc_serial_gt(when
, (now
+ 300)) || /* In the future. */
1711 isc_serial_lt(when
, (now
- 3600))) { /* In the past. */
1712 isc_stats_increment(ns_g_server
->nsstats
,
1713 dns_nsstatscounter_sitbadtime
);
1717 isc_buffer_init(&db
, dbuf
, sizeof(dbuf
));
1718 compute_sit(client
, when
, nonce
, &db
);
1720 if (memcmp(old
, dbuf
, SIT_SIZE
) != 0) {
1721 isc_stats_increment(ns_g_server
->nsstats
,
1722 dns_nsstatscounter_sitnomatch
);
1725 isc_stats_increment(ns_g_server
->nsstats
,
1726 dns_nsstatscounter_sitmatch
);
1728 client
->attributes
|= NS_CLIENTATTR_HAVESIT
;
1733 process_opt(ns_client_t
*client
, dns_rdataset_t
*opt
) {
1735 isc_buffer_t optbuf
;
1736 isc_result_t result
;
1737 isc_uint16_t optcode
;
1738 isc_uint16_t optlen
;
1741 * Set the client's UDP buffer size.
1743 client
->udpsize
= opt
->rdclass
;
1746 * If the requested UDP buffer size is less than 512,
1747 * ignore it and use 512.
1749 if (client
->udpsize
< 512)
1750 client
->udpsize
= 512;
1753 * Get the flags out of the OPT record.
1755 client
->extflags
= (isc_uint16_t
)(opt
->ttl
& 0xFFFF);
1758 * Do we understand this version of EDNS?
1760 * XXXRTH need library support for this!
1762 client
->ednsversion
= (opt
->ttl
& 0x00FF0000) >> 16;
1763 if (client
->ednsversion
> 0) {
1764 isc_stats_increment(ns_g_server
->nsstats
,
1765 dns_nsstatscounter_badednsver
);
1766 result
= ns_client_addopt(client
, client
->message
,
1768 if (result
== ISC_R_SUCCESS
)
1769 result
= DNS_R_BADVERS
;
1770 ns_client_error(client
, result
);
1774 /* Check for NSID request */
1775 result
= dns_rdataset_first(opt
);
1776 if (result
== ISC_R_SUCCESS
) {
1777 dns_rdata_init(&rdata
);
1778 dns_rdataset_current(opt
, &rdata
);
1779 isc_buffer_init(&optbuf
, rdata
.data
, rdata
.length
);
1780 isc_buffer_add(&optbuf
, rdata
.length
);
1781 while (isc_buffer_remaininglength(&optbuf
) >= 4) {
1782 optcode
= isc_buffer_getuint16(&optbuf
);
1783 optlen
= isc_buffer_getuint16(&optbuf
);
1786 isc_stats_increment(ns_g_server
->nsstats
,
1787 dns_nsstatscounter_nsidopt
);
1788 client
->attributes
|= NS_CLIENTATTR_WANTNSID
;
1789 isc_buffer_forward(&optbuf
, optlen
);
1791 #ifdef ISC_PLATFORM_USESIT
1793 process_sit(client
, &optbuf
, optlen
);
1796 case DNS_OPT_EXPIRE
:
1797 isc_stats_increment(ns_g_server
->nsstats
,
1798 dns_nsstatscounter_expireopt
);
1799 client
->attributes
|= NS_CLIENTATTR_WANTEXPIRE
;
1800 isc_buffer_forward(&optbuf
, optlen
);
1803 isc_stats_increment(ns_g_server
->nsstats
,
1804 dns_nsstatscounter_otheropt
);
1805 isc_buffer_forward(&optbuf
, optlen
);
1811 isc_stats_increment(ns_g_server
->nsstats
, dns_nsstatscounter_edns0in
);
1812 client
->attributes
|= NS_CLIENTATTR_WANTOPT
;
1819 * Handle an incoming request event from the socket (UDP case)
1820 * or tcpmsg (TCP case).
1823 client_request(isc_task_t
*task
, isc_event_t
*event
) {
1824 ns_client_t
*client
;
1825 isc_socketevent_t
*sevent
;
1826 isc_result_t result
;
1827 isc_result_t sigresult
= ISC_R_SUCCESS
;
1828 isc_buffer_t
*buffer
;
1829 isc_buffer_t tbuffer
;
1831 dns_rdataset_t
*opt
;
1832 dns_name_t
*signame
;
1833 isc_boolean_t ra
; /* Recursion available. */
1834 isc_netaddr_t netaddr
;
1838 isc_boolean_t notimp
;
1840 REQUIRE(event
!= NULL
);
1841 client
= event
->ev_arg
;
1842 REQUIRE(NS_CLIENT_VALID(client
));
1843 REQUIRE(task
== client
->task
);
1845 INSIST(client
->recursionquota
== NULL
);
1847 INSIST(client
->state
== (TCP_CLIENT(client
) ?
1848 NS_CLIENTSTATE_READING
:
1849 NS_CLIENTSTATE_READY
));
1851 ns_client_requests
++;
1853 if (event
->ev_type
== ISC_SOCKEVENT_RECVDONE
) {
1854 INSIST(!TCP_CLIENT(client
));
1855 sevent
= (isc_socketevent_t
*)event
;
1856 REQUIRE(sevent
== client
->recvevent
);
1857 isc_buffer_init(&tbuffer
, sevent
->region
.base
, sevent
->n
);
1858 isc_buffer_add(&tbuffer
, sevent
->n
);
1860 result
= sevent
->result
;
1861 if (result
== ISC_R_SUCCESS
) {
1862 client
->peeraddr
= sevent
->address
;
1863 client
->peeraddr_valid
= ISC_TRUE
;
1865 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_DSCP
) != 0) {
1866 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1867 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(90),
1868 "received DSCP %d", sevent
->dscp
);
1869 if (client
->dscp
== -1)
1870 client
->dscp
= sevent
->dscp
;
1872 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_PKTINFO
) != 0) {
1873 client
->attributes
|= NS_CLIENTATTR_PKTINFO
;
1874 client
->pktinfo
= sevent
->pktinfo
;
1876 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_MULTICAST
) != 0)
1877 client
->attributes
|= NS_CLIENTATTR_MULTICAST
;
1880 INSIST(TCP_CLIENT(client
));
1881 REQUIRE(event
->ev_type
== DNS_EVENT_TCPMSG
);
1882 REQUIRE(event
->ev_sender
== &client
->tcpmsg
);
1883 buffer
= &client
->tcpmsg
.buffer
;
1884 result
= client
->tcpmsg
.result
;
1885 INSIST(client
->nreads
== 1);
1887 * client->peeraddr was set when the connection was accepted.
1892 if (exit_check(client
))
1894 client
->state
= client
->newstate
= NS_CLIENTSTATE_WORKING
;
1896 isc_task_getcurrenttime(task
, &client
->requesttime
);
1897 client
->now
= client
->requesttime
;
1899 if (result
!= ISC_R_SUCCESS
) {
1900 if (TCP_CLIENT(client
)) {
1901 ns_client_next(client
, result
);
1903 if (result
!= ISC_R_CANCELED
)
1904 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_CLIENT
,
1905 NS_LOGMODULE_CLIENT
,
1907 "UDP client handler shutting "
1908 "down due to fatal receive "
1910 isc_result_totext(result
));
1911 isc_task_shutdown(client
->task
);
1916 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1918 #if NS_CLIENT_DROPPORT
1919 if (ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) ==
1921 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1922 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1923 "dropped request: suspicious port");
1924 ns_client_next(client
, ISC_R_SUCCESS
);
1929 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1930 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1932 TCP_CLIENT(client
) ? "TCP" : "UDP");
1935 * Check the blackhole ACL for UDP only, since TCP is done in
1938 if (!TCP_CLIENT(client
)) {
1940 if (ns_g_server
->blackholeacl
!= NULL
&&
1941 dns_acl_match(&netaddr
, NULL
, ns_g_server
->blackholeacl
,
1942 &ns_g_server
->aclenv
,
1943 &match
, NULL
) == ISC_R_SUCCESS
&&
1946 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1947 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1948 "blackholed UDP datagram");
1949 ns_client_next(client
, ISC_R_SUCCESS
);
1955 * Silently drop multicast requests for the present.
1956 * XXXMPA revisit this as mDNS spec was published.
1958 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0) {
1959 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1960 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(2),
1961 "dropping multicast request");
1962 ns_client_next(client
, DNS_R_REFUSED
);
1966 result
= dns_message_peekheader(buffer
, &id
, &flags
);
1967 if (result
!= ISC_R_SUCCESS
) {
1969 * There isn't enough header to determine whether
1970 * this was a request or a response. Drop it.
1972 ns_client_next(client
, result
);
1977 * The client object handles requests, not responses.
1978 * If this is a UDP response, forward it to the dispatcher.
1979 * If it's a TCP response, discard it here.
1981 if ((flags
& DNS_MESSAGEFLAG_QR
) != 0) {
1982 if (TCP_CLIENT(client
)) {
1983 CTRACE("unexpected response");
1984 ns_client_next(client
, DNS_R_FORMERR
);
1987 dns_dispatch_importrecv(client
->dispatch
, event
);
1988 ns_client_next(client
, ISC_R_SUCCESS
);
1994 * Update some statistics counters. Don't count responses.
1996 if (isc_sockaddr_pf(&client
->peeraddr
) == PF_INET
) {
1997 isc_stats_increment(ns_g_server
->nsstats
,
1998 dns_nsstatscounter_requestv4
);
2000 isc_stats_increment(ns_g_server
->nsstats
,
2001 dns_nsstatscounter_requestv6
);
2003 if (TCP_CLIENT(client
))
2004 isc_stats_increment(ns_g_server
->nsstats
,
2005 dns_nsstatscounter_requesttcp
);
2008 * It's a request. Parse it.
2010 result
= dns_message_parse(client
->message
, buffer
, 0);
2011 if (result
!= ISC_R_SUCCESS
) {
2013 * Parsing the request failed. Send a response
2014 * (typically FORMERR or SERVFAIL).
2016 ns_client_error(client
, result
);
2020 dns_opcodestats_increment(ns_g_server
->opcodestats
,
2021 client
->message
->opcode
);
2022 switch (client
->message
->opcode
) {
2023 case dns_opcode_query
:
2024 case dns_opcode_update
:
2025 case dns_opcode_notify
:
2028 case dns_opcode_iquery
:
2034 client
->message
->rcode
= dns_rcode_noerror
;
2036 /* RFC1123 section 6.1.3.2 */
2037 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0)
2038 client
->message
->flags
&= ~DNS_MESSAGEFLAG_RD
;
2046 opt
= dns_message_getopt(client
->message
);
2049 * Are we dropping all EDNS queries?
2051 if (ns_g_dropedns
) {
2052 ns_client_next(client
, ISC_R_SUCCESS
);
2055 result
= process_opt(client
, opt
);
2056 if (result
!= ISC_R_SUCCESS
)
2060 if (client
->message
->rdclass
== 0) {
2061 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2062 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
2063 "message class could not be determined");
2064 ns_client_dumpmessage(client
,
2065 "message class could not be determined");
2066 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_FORMERR
);
2071 * Determine the destination address. If the receiving interface is
2072 * bound to a specific address, we simply use it regardless of the
2073 * address family. All IPv4 queries should fall into this case.
2074 * Otherwise, if this is a TCP query, get the address from the
2075 * receiving socket (this needs a system call and can be heavy).
2076 * For IPv6 UDP queries, we get this from the pktinfo structure (if
2078 * If all the attempts fail (this can happen due to memory shortage,
2079 * etc), we regard this as an error for safety.
2081 if ((client
->interface
->flags
& NS_INTERFACEFLAG_ANYADDR
) == 0)
2082 isc_netaddr_fromsockaddr(&client
->destaddr
,
2083 &client
->interface
->addr
);
2085 isc_sockaddr_t sockaddr
;
2086 result
= ISC_R_FAILURE
;
2088 if (TCP_CLIENT(client
))
2089 result
= isc_socket_getsockname(client
->tcpsocket
,
2091 if (result
== ISC_R_SUCCESS
)
2092 isc_netaddr_fromsockaddr(&client
->destaddr
, &sockaddr
);
2093 if (result
!= ISC_R_SUCCESS
&&
2094 client
->interface
->addr
.type
.sa
.sa_family
== AF_INET6
&&
2095 (client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0) {
2097 * XXXJT technically, we should convert the receiving
2098 * interface ID to a proper scope zone ID. However,
2099 * due to the fact there is no standard API for this,
2100 * we only handle link-local addresses and use the
2101 * interface index as link ID. Despite the assumption,
2102 * it should cover most typical cases.
2104 isc_netaddr_fromin6(&client
->destaddr
,
2105 &client
->pktinfo
.ipi6_addr
);
2106 if (IN6_IS_ADDR_LINKLOCAL(&client
->pktinfo
.ipi6_addr
))
2107 isc_netaddr_setzone(&client
->destaddr
,
2108 client
->pktinfo
.ipi6_ifindex
);
2109 result
= ISC_R_SUCCESS
;
2111 if (result
!= ISC_R_SUCCESS
) {
2112 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2113 "failed to get request's "
2115 isc_result_totext(result
));
2116 ns_client_next(client
, ISC_R_SUCCESS
);
2122 * Find a view that matches the client's source address.
2124 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
2126 view
= ISC_LIST_NEXT(view
, link
)) {
2127 if (client
->message
->rdclass
== view
->rdclass
||
2128 client
->message
->rdclass
== dns_rdataclass_any
)
2130 dns_name_t
*tsig
= NULL
;
2132 sigresult
= dns_message_rechecksig(client
->message
,
2134 if (sigresult
== ISC_R_SUCCESS
)
2135 tsig
= dns_tsigkey_identity(client
->message
->tsigkey
);
2137 if (allowed(&netaddr
, tsig
, view
->matchclients
) &&
2138 allowed(&client
->destaddr
, tsig
,
2139 view
->matchdestinations
) &&
2140 !((client
->message
->flags
& DNS_MESSAGEFLAG_RD
)
2141 == 0 && view
->matchrecursiveonly
))
2143 dns_view_attach(view
, &client
->view
);
2150 char classname
[DNS_RDATACLASS_FORMATSIZE
];
2153 * Do a dummy TSIG verification attempt so that the
2154 * response will have a TSIG if the query did, as
2155 * required by RFC2845.
2160 dns_message_resetsig(client
->message
);
2162 r
= dns_message_getrawmessage(client
->message
);
2163 isc_buffer_init(&b
, r
->base
, r
->length
);
2164 isc_buffer_add(&b
, r
->length
);
2165 (void)dns_tsig_verify(&b
, client
->message
, NULL
, NULL
);
2167 dns_rdataclass_format(client
->message
->rdclass
, classname
,
2169 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2170 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
2171 "no matching view in class '%s'", classname
);
2172 ns_client_dumpmessage(client
, "no matching view in class");
2173 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_REFUSED
);
2177 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2178 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(5),
2179 "using view '%s'", view
->name
);
2182 * Check for a signature. We log bad signatures regardless of
2183 * whether they ultimately cause the request to be rejected or
2184 * not. We do not log the lack of a signature unless we are
2187 client
->signer
= NULL
;
2188 dns_name_init(&client
->signername
, NULL
);
2189 result
= dns_message_signer(client
->message
, &client
->signername
);
2190 if (result
!= ISC_R_NOTFOUND
) {
2192 if (dns_message_gettsig(client
->message
, &signame
) != NULL
) {
2193 isc_stats_increment(ns_g_server
->nsstats
,
2194 dns_nsstatscounter_tsigin
);
2196 isc_stats_increment(ns_g_server
->nsstats
,
2197 dns_nsstatscounter_sig0in
);
2201 if (result
== ISC_R_SUCCESS
) {
2202 char namebuf
[DNS_NAME_FORMATSIZE
];
2203 dns_name_format(&client
->signername
, namebuf
, sizeof(namebuf
));
2204 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2205 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2206 "request has valid signature: %s", namebuf
);
2207 client
->signer
= &client
->signername
;
2208 } else if (result
== ISC_R_NOTFOUND
) {
2209 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2210 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2211 "request is not signed");
2212 } else if (result
== DNS_R_NOIDENTITY
) {
2213 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2214 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2215 "request is signed by a nonauthoritative key");
2220 isc_result_t tresult
;
2222 /* There is a signature, but it is bad. */
2223 isc_stats_increment(ns_g_server
->nsstats
,
2224 dns_nsstatscounter_invalidsig
);
2226 if (dns_message_gettsig(client
->message
, &signame
) != NULL
) {
2227 char namebuf
[DNS_NAME_FORMATSIZE
];
2228 char cnamebuf
[DNS_NAME_FORMATSIZE
];
2229 dns_name_format(signame
, namebuf
, sizeof(namebuf
));
2230 status
= client
->message
->tsigstatus
;
2231 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
2232 tresult
= dns_tsigrcode_totext(status
, &b
);
2233 INSIST(tresult
== ISC_R_SUCCESS
);
2234 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
2235 if (client
->message
->tsigkey
->generated
) {
2236 dns_name_format(client
->message
->tsigkey
->creator
,
2237 cnamebuf
, sizeof(cnamebuf
));
2238 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2239 NS_LOGMODULE_CLIENT
,
2241 "request has invalid signature: "
2242 "TSIG %s (%s): %s (%s)", namebuf
,
2244 isc_result_totext(result
),
2247 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2248 NS_LOGMODULE_CLIENT
,
2250 "request has invalid signature: "
2251 "TSIG %s: %s (%s)", namebuf
,
2252 isc_result_totext(result
),
2256 status
= client
->message
->sig0status
;
2257 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
2258 tresult
= dns_tsigrcode_totext(status
, &b
);
2259 INSIST(tresult
== ISC_R_SUCCESS
);
2260 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
2261 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2262 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
2263 "request has invalid signature: %s (%s)",
2264 isc_result_totext(result
), tsigrcode
);
2267 * Accept update messages signed by unknown keys so that
2268 * update forwarding works transparently through slaves
2269 * that don't have all the same keys as the master.
2271 if (!(client
->message
->tsigstatus
== dns_tsigerror_badkey
&&
2272 client
->message
->opcode
== dns_opcode_update
)) {
2273 ns_client_error(client
, sigresult
);
2279 * Decide whether recursive service is available to this client.
2280 * We do this here rather than in the query code so that we can
2281 * set the RA bit correctly on all kinds of responses, not just
2282 * responses to ordinary queries. Note if you can't query the
2283 * cache there is no point in setting RA.
2286 if (client
->view
->resolver
!= NULL
&&
2287 client
->view
->recursion
== ISC_TRUE
&&
2288 ns_client_checkaclsilent(client
, NULL
,
2289 client
->view
->recursionacl
,
2290 ISC_TRUE
) == ISC_R_SUCCESS
&&
2291 ns_client_checkaclsilent(client
, NULL
,
2292 client
->view
->cacheacl
,
2293 ISC_TRUE
) == ISC_R_SUCCESS
&&
2294 ns_client_checkaclsilent(client
, &client
->destaddr
,
2295 client
->view
->recursiononacl
,
2296 ISC_TRUE
) == ISC_R_SUCCESS
&&
2297 ns_client_checkaclsilent(client
, &client
->destaddr
,
2298 client
->view
->cacheonacl
,
2299 ISC_TRUE
) == ISC_R_SUCCESS
)
2303 client
->attributes
|= NS_CLIENTATTR_RA
;
2305 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
, NS_LOGMODULE_CLIENT
,
2306 ISC_LOG_DEBUG(3), ra
? "recursion available" :
2307 "recursion not available");
2310 * Adjust maximum UDP response size for this client.
2312 if (client
->udpsize
> 512) {
2313 dns_peer_t
*peer
= NULL
;
2314 isc_uint16_t udpsize
= view
->maxudp
;
2315 (void) dns_peerlist_peerbyaddr(view
->peers
, &netaddr
, &peer
);
2317 dns_peer_getmaxudp(peer
, &udpsize
);
2318 if (client
->udpsize
> udpsize
)
2319 client
->udpsize
= udpsize
;
2323 * Dispatch the request.
2325 switch (client
->message
->opcode
) {
2326 case dns_opcode_query
:
2328 ns_query_start(client
);
2330 case dns_opcode_update
:
2332 ns_client_settimeout(client
, 60);
2333 ns_update_start(client
, sigresult
);
2335 case dns_opcode_notify
:
2337 ns_client_settimeout(client
, 60);
2338 ns_notify_start(client
);
2340 case dns_opcode_iquery
:
2342 ns_client_error(client
, DNS_R_NOTIMP
);
2345 CTRACE("unknown opcode");
2346 ns_client_error(client
, DNS_R_NOTIMP
);
2354 client_timeout(isc_task_t
*task
, isc_event_t
*event
) {
2355 ns_client_t
*client
;
2357 REQUIRE(event
!= NULL
);
2358 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_LIFE
||
2359 event
->ev_type
== ISC_TIMEREVENT_IDLE
);
2360 client
= event
->ev_arg
;
2361 REQUIRE(NS_CLIENT_VALID(client
));
2362 REQUIRE(task
== client
->task
);
2363 REQUIRE(client
->timer
!= NULL
);
2369 isc_event_free(&event
);
2371 if (client
->shutdown
!= NULL
) {
2372 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_TIMEDOUT
);
2373 client
->shutdown
= NULL
;
2374 client
->shutdown_arg
= NULL
;
2377 if (client
->newstate
> NS_CLIENTSTATE_READY
)
2378 client
->newstate
= NS_CLIENTSTATE_READY
;
2379 (void)exit_check(client
);
2383 get_clientmctx(ns_clientmgr_t
*manager
, isc_mem_t
**mctxp
) {
2384 isc_mem_t
*clientmctx
;
2385 isc_result_t result
;
2387 unsigned int nextmctx
;
2390 MTRACE("clientmctx");
2393 * Caller must be holding the manager lock.
2395 if (ns_g_clienttest
) {
2396 result
= isc_mem_create(0, 0, mctxp
);
2397 if (result
== ISC_R_SUCCESS
)
2398 isc_mem_setname(*mctxp
, "client", NULL
);
2402 nextmctx
= manager
->nextmctx
++;
2403 if (manager
->nextmctx
== NMCTXS
)
2404 manager
->nextmctx
= 0;
2406 INSIST(nextmctx
< NMCTXS
);
2408 clientmctx
= manager
->mctxpool
[nextmctx
];
2409 if (clientmctx
== NULL
) {
2410 result
= isc_mem_create(0, 0, &clientmctx
);
2411 if (result
!= ISC_R_SUCCESS
)
2413 isc_mem_setname(clientmctx
, "client", NULL
);
2415 manager
->mctxpool
[nextmctx
] = clientmctx
;
2418 clientmctx
= manager
->mctx
;
2421 isc_mem_attach(clientmctx
, mctxp
);
2423 return (ISC_R_SUCCESS
);
2427 client_create(ns_clientmgr_t
*manager
, ns_client_t
**clientp
) {
2428 ns_client_t
*client
;
2429 isc_result_t result
;
2430 isc_mem_t
*mctx
= NULL
;
2433 * Caller must be holding the manager lock.
2435 * Note: creating a client does not add the client to the
2436 * manager's client list or set the client's manager pointer.
2437 * The caller is responsible for that.
2440 REQUIRE(clientp
!= NULL
&& *clientp
== NULL
);
2442 result
= get_clientmctx(manager
, &mctx
);
2443 if (result
!= ISC_R_SUCCESS
)
2446 client
= isc_mem_get(mctx
, sizeof(*client
));
2447 if (client
== NULL
) {
2448 isc_mem_detach(&mctx
);
2449 return (ISC_R_NOMEMORY
);
2451 client
->mctx
= mctx
;
2453 client
->task
= NULL
;
2454 result
= isc_task_create(manager
->taskmgr
, 0, &client
->task
);
2455 if (result
!= ISC_R_SUCCESS
)
2456 goto cleanup_client
;
2457 isc_task_setname(client
->task
, "client", client
);
2459 client
->timer
= NULL
;
2460 result
= isc_timer_create(manager
->timermgr
, isc_timertype_inactive
,
2461 NULL
, NULL
, client
->task
, client_timeout
,
2462 client
, &client
->timer
);
2463 if (result
!= ISC_R_SUCCESS
)
2465 client
->timerset
= ISC_FALSE
;
2467 client
->delaytimer
= NULL
;
2469 client
->message
= NULL
;
2470 result
= dns_message_create(client
->mctx
, DNS_MESSAGE_INTENTPARSE
,
2472 if (result
!= ISC_R_SUCCESS
)
2475 /* XXXRTH Hardwired constants */
2477 client
->sendevent
= isc_socket_socketevent(client
->mctx
, client
,
2478 ISC_SOCKEVENT_SENDDONE
,
2479 client_senddone
, client
);
2480 if (client
->sendevent
== NULL
) {
2481 result
= ISC_R_NOMEMORY
;
2482 goto cleanup_message
;
2485 client
->recvbuf
= isc_mem_get(client
->mctx
, RECV_BUFFER_SIZE
);
2486 if (client
->recvbuf
== NULL
) {
2487 result
= ISC_R_NOMEMORY
;
2488 goto cleanup_sendevent
;
2491 client
->recvevent
= isc_socket_socketevent(client
->mctx
, client
,
2492 ISC_SOCKEVENT_RECVDONE
,
2493 client_request
, client
);
2494 if (client
->recvevent
== NULL
) {
2495 result
= ISC_R_NOMEMORY
;
2496 goto cleanup_recvbuf
;
2499 client
->magic
= NS_CLIENT_MAGIC
;
2500 client
->manager
= NULL
;
2501 client
->state
= NS_CLIENTSTATE_INACTIVE
;
2502 client
->newstate
= NS_CLIENTSTATE_MAX
;
2503 client
->naccepts
= 0;
2507 client
->nupdates
= 0;
2509 client
->references
= 0;
2510 client
->attributes
= 0;
2511 client
->view
= NULL
;
2512 client
->dispatch
= NULL
;
2513 client
->udpsocket
= NULL
;
2514 client
->tcplistener
= NULL
;
2515 client
->tcpsocket
= NULL
;
2516 client
->tcpmsg_valid
= ISC_FALSE
;
2517 client
->tcpbuf
= NULL
;
2519 client
->udpsize
= 512;
2521 client
->extflags
= 0;
2522 client
->ednsversion
= -1;
2523 client
->next
= NULL
;
2524 client
->shutdown
= NULL
;
2525 client
->shutdown_arg
= NULL
;
2526 client
->signer
= NULL
;
2527 dns_name_init(&client
->signername
, NULL
);
2528 client
->mortal
= ISC_FALSE
;
2529 client
->tcpquota
= NULL
;
2530 client
->recursionquota
= NULL
;
2531 client
->interface
= NULL
;
2532 client
->peeraddr_valid
= ISC_FALSE
;
2533 #ifdef ALLOW_FILTER_AAAA
2534 client
->filter_aaaa
= dns_aaaa_ok
;
2536 client
->needshutdown
= ns_g_clienttest
;
2538 ISC_EVENT_INIT(&client
->ctlevent
, sizeof(client
->ctlevent
), 0, NULL
,
2539 NS_EVENT_CLIENTCONTROL
, client_start
, client
, client
,
2542 * Initialize FORMERR cache to sentinel value that will not match
2543 * any actual FORMERR response.
2545 isc_sockaddr_any(&client
->formerrcache
.addr
);
2546 client
->formerrcache
.time
= 0;
2547 client
->formerrcache
.id
= 0;
2548 ISC_LINK_INIT(client
, link
);
2549 ISC_LINK_INIT(client
, rlink
);
2550 ISC_QLINK_INIT(client
, ilink
);
2553 * We call the init routines for the various kinds of client here,
2554 * after we have created an otherwise valid client, because some
2555 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2557 result
= ns_query_init(client
);
2558 if (result
!= ISC_R_SUCCESS
)
2559 goto cleanup_recvevent
;
2561 result
= isc_task_onshutdown(client
->task
, client_shutdown
, client
);
2562 if (result
!= ISC_R_SUCCESS
)
2569 return (ISC_R_SUCCESS
);
2572 ns_query_free(client
);
2575 isc_event_free((isc_event_t
**)&client
->recvevent
);
2578 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
2581 isc_event_free((isc_event_t
**)&client
->sendevent
);
2586 dns_message_destroy(&client
->message
);
2589 isc_timer_detach(&client
->timer
);
2592 isc_task_detach(&client
->task
);
2595 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
2601 client_read(ns_client_t
*client
) {
2602 isc_result_t result
;
2606 result
= dns_tcpmsg_readmessage(&client
->tcpmsg
, client
->task
,
2607 client_request
, client
);
2608 if (result
!= ISC_R_SUCCESS
)
2612 * Set a timeout to limit the amount of time we will wait
2613 * for a request on this TCP connection.
2615 ns_client_settimeout(client
, 30);
2617 client
->state
= client
->newstate
= NS_CLIENTSTATE_READING
;
2618 INSIST(client
->nreads
== 0);
2619 INSIST(client
->recursionquota
== NULL
);
2624 ns_client_next(client
, result
);
2628 client_newconn(isc_task_t
*task
, isc_event_t
*event
) {
2629 ns_client_t
*client
= event
->ev_arg
;
2630 isc_socket_newconnev_t
*nevent
= (isc_socket_newconnev_t
*)event
;
2631 isc_result_t result
;
2633 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_NEWCONN
);
2634 REQUIRE(NS_CLIENT_VALID(client
));
2635 REQUIRE(client
->task
== task
);
2639 INSIST(client
->state
== NS_CLIENTSTATE_READY
);
2641 INSIST(client
->naccepts
== 1);
2644 LOCK(&client
->interface
->lock
);
2645 INSIST(client
->interface
->ntcpcurrent
> 0);
2646 client
->interface
->ntcpcurrent
--;
2647 UNLOCK(&client
->interface
->lock
);
2650 * We must take ownership of the new socket before the exit
2651 * check to make sure it gets destroyed if we decide to exit.
2653 if (nevent
->result
== ISC_R_SUCCESS
) {
2654 client
->tcpsocket
= nevent
->newsocket
;
2655 isc_socket_setname(client
->tcpsocket
, "client-tcp", NULL
);
2656 client
->state
= NS_CLIENTSTATE_READING
;
2657 INSIST(client
->recursionquota
== NULL
);
2659 (void)isc_socket_getpeername(client
->tcpsocket
,
2661 client
->peeraddr_valid
= ISC_TRUE
;
2662 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2663 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2664 "new TCP connection");
2667 * XXXRTH What should we do? We're trying to accept but
2668 * it didn't work. If we just give up, then TCP
2669 * service may eventually stop.
2671 * For now, we just go idle.
2673 * Going idle is probably the right thing if the
2676 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2677 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2678 "accept failed: %s",
2679 isc_result_totext(nevent
->result
));
2682 if (exit_check(client
))
2685 if (nevent
->result
== ISC_R_SUCCESS
) {
2687 isc_netaddr_t netaddr
;
2689 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2691 if (ns_g_server
->blackholeacl
!= NULL
&&
2692 dns_acl_match(&netaddr
, NULL
,
2693 ns_g_server
->blackholeacl
,
2694 &ns_g_server
->aclenv
,
2695 &match
, NULL
) == ISC_R_SUCCESS
&&
2698 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2699 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2700 "blackholed connection attempt");
2701 client
->newstate
= NS_CLIENTSTATE_READY
;
2702 (void)exit_check(client
);
2706 INSIST(client
->tcpmsg_valid
== ISC_FALSE
);
2707 dns_tcpmsg_init(client
->mctx
, client
->tcpsocket
,
2709 client
->tcpmsg_valid
= ISC_TRUE
;
2712 * Let a new client take our place immediately, before
2713 * we wait for a request packet. If we don't,
2714 * telnetting to port 53 (once per CPU) will
2715 * deny service to legitimate TCP clients.
2717 result
= isc_quota_attach(&ns_g_server
->tcpquota
,
2719 if (result
== ISC_R_SUCCESS
)
2720 result
= ns_client_replace(client
);
2721 if (result
!= ISC_R_SUCCESS
) {
2722 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2723 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
2724 "no more TCP clients: %s",
2725 isc_result_totext(result
));
2728 client_read(client
);
2732 isc_event_free(&event
);
2736 client_accept(ns_client_t
*client
) {
2737 isc_result_t result
;
2741 result
= isc_socket_accept(client
->tcplistener
, client
->task
,
2742 client_newconn
, client
);
2743 if (result
!= ISC_R_SUCCESS
) {
2744 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2745 "isc_socket_accept() failed: %s",
2746 isc_result_totext(result
));
2748 * XXXRTH What should we do? We're trying to accept but
2749 * it didn't work. If we just give up, then TCP
2750 * service may eventually stop.
2752 * For now, we just go idle.
2756 INSIST(client
->naccepts
== 0);
2758 LOCK(&client
->interface
->lock
);
2759 client
->interface
->ntcpcurrent
++;
2760 UNLOCK(&client
->interface
->lock
);
2764 client_udprecv(ns_client_t
*client
) {
2765 isc_result_t result
;
2770 r
.base
= client
->recvbuf
;
2771 r
.length
= RECV_BUFFER_SIZE
;
2772 result
= isc_socket_recv2(client
->udpsocket
, &r
, 1,
2773 client
->task
, client
->recvevent
, 0);
2774 if (result
!= ISC_R_SUCCESS
) {
2775 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2776 "isc_socket_recv2() failed: %s",
2777 isc_result_totext(result
));
2779 * This cannot happen in the current implementation, since
2780 * isc_socket_recv2() cannot fail if flags == 0.
2782 * If this does fail, we just go idle.
2786 INSIST(client
->nrecvs
== 0);
2791 ns_client_attach(ns_client_t
*source
, ns_client_t
**targetp
) {
2792 REQUIRE(NS_CLIENT_VALID(source
));
2793 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
2795 source
->references
++;
2796 ns_client_log(source
, NS_LOGCATEGORY_CLIENT
,
2797 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2798 "ns_client_attach: ref = %d", source
->references
);
2803 ns_client_detach(ns_client_t
**clientp
) {
2804 ns_client_t
*client
= *clientp
;
2806 client
->references
--;
2807 INSIST(client
->references
>= 0);
2809 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2810 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2811 "ns_client_detach: ref = %d", client
->references
);
2812 (void)exit_check(client
);
2816 ns_client_shuttingdown(ns_client_t
*client
) {
2817 return (ISC_TF(client
->newstate
== NS_CLIENTSTATE_FREED
));
2821 ns_client_replace(ns_client_t
*client
) {
2822 isc_result_t result
;
2826 REQUIRE(client
!= NULL
);
2827 REQUIRE(client
->manager
!= NULL
);
2829 result
= get_client(client
->manager
, client
->interface
,
2830 client
->dispatch
, TCP_CLIENT(client
));
2831 if (result
!= ISC_R_SUCCESS
)
2835 * The responsibility for listening for new requests is hereby
2836 * transferred to the new client. Therefore, the old client
2837 * should refrain from listening for any more requests.
2839 client
->mortal
= ISC_TRUE
;
2841 return (ISC_R_SUCCESS
);
2849 clientmgr_destroy(ns_clientmgr_t
*manager
) {
2854 REQUIRE(ISC_LIST_EMPTY(manager
->clients
));
2856 MTRACE("clientmgr_destroy");
2859 for (i
= 0; i
< NMCTXS
; i
++) {
2860 if (manager
->mctxpool
[i
] != NULL
)
2861 isc_mem_detach(&manager
->mctxpool
[i
]);
2865 ISC_QUEUE_DESTROY(manager
->inactive
);
2866 DESTROYLOCK(&manager
->lock
);
2867 DESTROYLOCK(&manager
->listlock
);
2868 DESTROYLOCK(&manager
->reclock
);
2870 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2874 ns_clientmgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
2875 isc_timermgr_t
*timermgr
, ns_clientmgr_t
**managerp
)
2877 ns_clientmgr_t
*manager
;
2878 isc_result_t result
;
2883 manager
= isc_mem_get(mctx
, sizeof(*manager
));
2884 if (manager
== NULL
)
2885 return (ISC_R_NOMEMORY
);
2887 result
= isc_mutex_init(&manager
->lock
);
2888 if (result
!= ISC_R_SUCCESS
)
2889 goto cleanup_manager
;
2891 result
= isc_mutex_init(&manager
->listlock
);
2892 if (result
!= ISC_R_SUCCESS
)
2895 result
= isc_mutex_init(&manager
->reclock
);
2896 if (result
!= ISC_R_SUCCESS
)
2897 goto cleanup_listlock
;
2899 manager
->mctx
= mctx
;
2900 manager
->taskmgr
= taskmgr
;
2901 manager
->timermgr
= timermgr
;
2902 manager
->exiting
= ISC_FALSE
;
2903 ISC_LIST_INIT(manager
->clients
);
2904 ISC_LIST_INIT(manager
->recursing
);
2905 ISC_QUEUE_INIT(manager
->inactive
, ilink
);
2907 manager
->nextmctx
= 0;
2908 for (i
= 0; i
< NMCTXS
; i
++)
2909 manager
->mctxpool
[i
] = NULL
; /* will be created on-demand */
2911 manager
->magic
= MANAGER_MAGIC
;
2915 *managerp
= manager
;
2917 return (ISC_R_SUCCESS
);
2920 (void) isc_mutex_destroy(&manager
->listlock
);
2923 (void) isc_mutex_destroy(&manager
->lock
);
2926 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2932 ns_clientmgr_destroy(ns_clientmgr_t
**managerp
) {
2933 isc_result_t result
;
2934 ns_clientmgr_t
*manager
;
2935 ns_client_t
*client
;
2936 isc_boolean_t need_destroy
= ISC_FALSE
, unlock
= ISC_FALSE
;
2938 REQUIRE(managerp
!= NULL
);
2939 manager
= *managerp
;
2940 REQUIRE(VALID_MANAGER(manager
));
2945 * Check for success because we may already be task-exclusive
2946 * at this point. Only if we succeed at obtaining an exclusive
2947 * lock now will we need to relinquish it later.
2949 result
= isc_task_beginexclusive(ns_g_server
->task
);
2950 if (result
== ISC_R_SUCCESS
)
2953 manager
->exiting
= ISC_TRUE
;
2955 for (client
= ISC_LIST_HEAD(manager
->clients
);
2957 client
= ISC_LIST_NEXT(client
, link
))
2958 isc_task_shutdown(client
->task
);
2960 if (ISC_LIST_EMPTY(manager
->clients
))
2961 need_destroy
= ISC_TRUE
;
2964 isc_task_endexclusive(ns_g_server
->task
);
2967 clientmgr_destroy(manager
);
2973 get_client(ns_clientmgr_t
*manager
, ns_interface_t
*ifp
,
2974 dns_dispatch_t
*disp
, isc_boolean_t tcp
)
2976 isc_result_t result
= ISC_R_SUCCESS
;
2978 ns_client_t
*client
;
2979 MTRACE("get client");
2981 REQUIRE(manager
!= NULL
);
2983 if (manager
->exiting
)
2984 return (ISC_R_SHUTTINGDOWN
);
2987 * Allocate a client. First try to get a recycled one;
2988 * if that fails, make a new one.
2991 if (!ns_g_clienttest
)
2992 ISC_QUEUE_POP(manager
->inactive
, ilink
, client
);
2997 MTRACE("create new");
2999 LOCK(&manager
->lock
);
3000 result
= client_create(manager
, &client
);
3001 UNLOCK(&manager
->lock
);
3002 if (result
!= ISC_R_SUCCESS
)
3005 LOCK(&manager
->listlock
);
3006 ISC_LIST_APPEND(manager
->clients
, client
, link
);
3007 UNLOCK(&manager
->listlock
);
3010 client
->manager
= manager
;
3011 ns_interface_attach(ifp
, &client
->interface
);
3012 client
->state
= NS_CLIENTSTATE_READY
;
3013 INSIST(client
->recursionquota
== NULL
);
3015 client
->dscp
= ifp
->dscp
;
3018 client
->attributes
|= NS_CLIENTATTR_TCP
;
3019 isc_socket_attach(ifp
->tcpsocket
,
3020 &client
->tcplistener
);
3024 dns_dispatch_attach(disp
, &client
->dispatch
);
3025 sock
= dns_dispatch_getsocket(client
->dispatch
);
3026 isc_socket_attach(sock
, &client
->udpsocket
);
3029 INSIST(client
->nctls
== 0);
3031 ev
= &client
->ctlevent
;
3032 isc_task_send(client
->task
, &ev
);
3034 return (ISC_R_SUCCESS
);
3038 ns_clientmgr_createclients(ns_clientmgr_t
*manager
, unsigned int n
,
3039 ns_interface_t
*ifp
, isc_boolean_t tcp
)
3041 isc_result_t result
= ISC_R_SUCCESS
;
3044 REQUIRE(VALID_MANAGER(manager
));
3047 MTRACE("createclients");
3049 for (disp
= 0; disp
< n
; disp
++) {
3050 result
= get_client(manager
, ifp
, ifp
->udpdispatch
[disp
], tcp
);
3051 if (result
!= ISC_R_SUCCESS
)
3059 ns_client_getsockaddr(ns_client_t
*client
) {
3060 return (&client
->peeraddr
);
3064 ns_client_checkaclsilent(ns_client_t
*client
, isc_netaddr_t
*netaddr
,
3065 dns_acl_t
*acl
, isc_boolean_t default_allow
)
3067 isc_result_t result
;
3068 isc_netaddr_t tmpnetaddr
;
3078 if (netaddr
== NULL
) {
3079 isc_netaddr_fromsockaddr(&tmpnetaddr
, &client
->peeraddr
);
3080 netaddr
= &tmpnetaddr
;
3083 result
= dns_acl_match(netaddr
, client
->signer
, acl
,
3084 &ns_g_server
->aclenv
, &match
, NULL
);
3086 if (result
!= ISC_R_SUCCESS
)
3087 goto deny
; /* Internal error, already logged. */
3090 goto deny
; /* Negative match or no match. */
3093 return (ISC_R_SUCCESS
);
3096 return (DNS_R_REFUSED
);
3100 ns_client_checkacl(ns_client_t
*client
, isc_sockaddr_t
*sockaddr
,
3101 const char *opname
, dns_acl_t
*acl
,
3102 isc_boolean_t default_allow
, int log_level
)
3104 isc_result_t result
;
3105 isc_netaddr_t netaddr
;
3107 if (sockaddr
!= NULL
)
3108 isc_netaddr_fromsockaddr(&netaddr
, sockaddr
);
3110 result
= ns_client_checkaclsilent(client
, sockaddr
? &netaddr
: NULL
,
3111 acl
, default_allow
);
3113 pfilter_notify(result
, client
, opname
);
3114 if (result
== ISC_R_SUCCESS
)
3115 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
3116 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
3117 "%s approved", opname
);
3119 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
3120 NS_LOGMODULE_CLIENT
,
3121 log_level
, "%s denied", opname
);
3126 ns_client_name(ns_client_t
*client
, char *peerbuf
, size_t len
) {
3127 if (client
->peeraddr_valid
)
3128 isc_sockaddr_format(&client
->peeraddr
, peerbuf
,
3131 snprintf(peerbuf
, len
, "@%p", client
);
3135 ns_client_logv(ns_client_t
*client
, isc_logcategory_t
*category
,
3136 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
3139 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
3140 char signerbuf
[DNS_NAME_FORMATSIZE
], qnamebuf
[DNS_NAME_FORMATSIZE
];
3141 const char *viewname
= "";
3142 const char *sep1
= "", *sep2
= "", *sep3
= "", *sep4
= "";
3143 const char *signer
= "", *qname
= "";
3144 dns_name_t
*q
= NULL
;
3146 vsnprintf(msgbuf
, sizeof(msgbuf
), fmt
, ap
);
3148 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
3150 if (client
->signer
!= NULL
) {
3151 dns_name_format(client
->signer
, signerbuf
, sizeof(signerbuf
));
3156 q
= client
->query
.origqname
!= NULL
3157 ? client
->query
.origqname
: client
->query
.qname
;
3159 dns_name_format(q
, qnamebuf
, sizeof(qnamebuf
));
3165 if (client
->view
!= NULL
&& strcmp(client
->view
->name
, "_bind") != 0 &&
3166 strcmp(client
->view
->name
, "_default") != 0) {
3168 viewname
= client
->view
->name
;
3171 isc_log_write(ns_g_lctx
, category
, module
, level
,
3172 "client %s%s%s%s%s%s%s%s: %s",
3173 peerbuf
, sep1
, signer
, sep2
, qname
, sep3
,
3174 sep4
, viewname
, msgbuf
);
3178 ns_client_log(ns_client_t
*client
, isc_logcategory_t
*category
,
3179 isc_logmodule_t
*module
, int level
, const char *fmt
, ...)
3183 if (! isc_log_wouldlog(ns_g_lctx
, level
))
3187 ns_client_logv(client
, category
, module
, level
, fmt
, ap
);
3192 ns_client_aclmsg(const char *msg
, dns_name_t
*name
, dns_rdatatype_t type
,
3193 dns_rdataclass_t rdclass
, char *buf
, size_t len
)
3195 char namebuf
[DNS_NAME_FORMATSIZE
];
3196 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3197 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
3199 dns_name_format(name
, namebuf
, sizeof(namebuf
));
3200 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
3201 dns_rdataclass_format(rdclass
, classbuf
, sizeof(classbuf
));
3202 (void)snprintf(buf
, len
, "%s '%s/%s/%s'", msg
, namebuf
, typebuf
,
3207 ns_client_dumpmessage(ns_client_t
*client
, const char *reason
) {
3208 isc_buffer_t buffer
;
3211 isc_result_t result
;
3213 if (!isc_log_wouldlog(ns_g_lctx
, ISC_LOG_DEBUG(1)))
3217 * Note that these are multiline debug messages. We want a newline
3218 * to appear in the log after each message.
3222 buf
= isc_mem_get(client
->mctx
, len
);
3225 isc_buffer_init(&buffer
, buf
, len
);
3226 result
= dns_message_totext(client
->message
,
3227 &dns_master_style_debug
,
3229 if (result
== ISC_R_NOSPACE
) {
3230 isc_mem_put(client
->mctx
, buf
, len
);
3232 } else if (result
== ISC_R_SUCCESS
)
3233 ns_client_log(client
, NS_LOGCATEGORY_UNMATCHED
,
3234 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
3236 (int)isc_buffer_usedlength(&buffer
),
3238 } while (result
== ISC_R_NOSPACE
);
3241 isc_mem_put(client
->mctx
, buf
, len
);
3245 ns_client_dumprecursing(FILE *f
, ns_clientmgr_t
*manager
) {
3246 ns_client_t
*client
;
3247 char namebuf
[DNS_NAME_FORMATSIZE
];
3248 char original
[DNS_NAME_FORMATSIZE
];
3249 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
3250 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3251 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
3254 const char *origfor
;
3255 dns_rdataset_t
*rdataset
;
3257 REQUIRE(VALID_MANAGER(manager
));
3259 LOCK(&manager
->reclock
);
3260 client
= ISC_LIST_HEAD(manager
->recursing
);
3261 while (client
!= NULL
) {
3262 INSIST(client
->state
== NS_CLIENTSTATE_RECURSING
);
3264 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
3265 if (client
->view
!= NULL
&&
3266 strcmp(client
->view
->name
, "_bind") != 0 &&
3267 strcmp(client
->view
->name
, "_default") != 0) {
3268 name
= client
->view
->name
;
3275 LOCK(&client
->query
.fetchlock
);
3276 INSIST(client
->query
.qname
!= NULL
);
3277 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
3278 if (client
->query
.qname
!= client
->query
.origqname
&&
3279 client
->query
.origqname
!= NULL
) {
3281 dns_name_format(client
->query
.origqname
, original
,
3287 rdataset
= ISC_LIST_HEAD(client
->query
.qname
->list
);
3288 if (rdataset
== NULL
&& client
->query
.origqname
!= NULL
)
3289 rdataset
= ISC_LIST_HEAD(client
->query
.origqname
->list
);
3290 if (rdataset
!= NULL
) {
3291 dns_rdatatype_format(rdataset
->type
, typebuf
,
3293 dns_rdataclass_format(rdataset
->rdclass
, classbuf
,
3296 strcpy(typebuf
, "-");
3297 strcpy(classbuf
, "-");
3299 UNLOCK(&client
->query
.fetchlock
);
3300 fprintf(f
, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
3301 "requesttime %d\n", peerbuf
, sep
, name
,
3302 client
->message
->id
, namebuf
, typebuf
, classbuf
,
3303 origfor
, original
, client
->requesttime
);
3304 client
= ISC_LIST_NEXT(client
, rlink
);
3306 UNLOCK(&manager
->reclock
);
3310 ns_client_qnamereplace(ns_client_t
*client
, dns_name_t
*name
) {
3311 LOCK(&client
->query
.fetchlock
);
3312 if (client
->query
.restarts
> 0) {
3314 * client->query.qname was dynamically allocated.
3316 dns_message_puttempname(client
->message
,
3317 &client
->query
.qname
);
3319 client
->query
.qname
= name
;
3320 UNLOCK(&client
->query
.fetchlock
);
3324 ns_client_sourceip(dns_clientinfo_t
*ci
, isc_sockaddr_t
**addrp
) {
3325 ns_client_t
*client
= (ns_client_t
*) ci
->data
;
3327 REQUIRE(NS_CLIENT_VALID(client
));
3328 REQUIRE(addrp
!= NULL
);
3330 *addrp
= &client
->peeraddr
;
3331 return (ISC_R_SUCCESS
);