4 * Copyright (C) 2004-2009 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.266 2009/10/26 23:14:53 each Exp */
24 #include <isc/formatcheck.h>
25 #include <isc/mutex.h>
27 #include <isc/platform.h>
28 #include <isc/print.h>
29 #include <isc/stats.h>
30 #include <isc/stdio.h>
31 #include <isc/string.h>
33 #include <isc/timer.h>
37 #include <dns/dispatch.h>
38 #include <dns/events.h>
39 #include <dns/message.h>
41 #include <dns/rcode.h>
42 #include <dns/rdata.h>
43 #include <dns/rdataclass.h>
44 #include <dns/rdatalist.h>
45 #include <dns/rdataset.h>
46 #include <dns/resolver.h>
47 #include <dns/stats.h>
52 #include <named/interfacemgr.h>
53 #include <named/log.h>
54 #include <named/notify.h>
56 #include <named/server.h>
57 #include <named/update.h>
68 * All client state changes, other than that from idle to listening, occur
69 * as a result of events. This guarantees serialization and avoids the
72 * If a routine is ever created that allows someone other than the client's
73 * task to change the client, then the client will have to be locked.
76 #define NS_CLIENT_TRACE
77 #ifdef NS_CLIENT_TRACE
78 #define CTRACE(m) ns_client_log(client, \
79 NS_LOGCATEGORY_CLIENT, \
80 NS_LOGMODULE_CLIENT, \
83 #define MTRACE(m) isc_log_write(ns_g_lctx, \
84 NS_LOGCATEGORY_GENERAL, \
85 NS_LOGMODULE_CLIENT, \
87 "clientmgr @%p: %s", manager, (m))
89 #define CTRACE(m) ((void)(m))
90 #define MTRACE(m) ((void)(m))
93 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
95 #define TCP_BUFFER_SIZE (65535 + 2)
96 #define SEND_BUFFER_SIZE 4096
97 #define RECV_BUFFER_SIZE 4096
99 #ifdef ISC_PLATFORM_USETHREADS
102 * Number of 'mctx pools' for clients. (Should this be configurable?)
103 * When enabling threads, we use a pool of memory contexts shared by
104 * client objects, since concurrent access to a shared context would cause
105 * heavy contentions. The above constant is expected to be enough for
106 * completely avoiding contentions among threads for an authoritative-only
112 * If named with built without thread, simply share manager's context. Using
113 * a separate context in this case would simply waste memory.
117 /*% nameserver client manager structure */
118 struct ns_clientmgr
{
122 isc_taskmgr_t
* taskmgr
;
123 isc_timermgr_t
* timermgr
;
125 /* Locked by lock. */
126 isc_boolean_t exiting
;
127 client_list_t active
; /*%< Active clients */
128 client_list_t recursing
; /*%< Recursing clients */
129 client_list_t inactive
; /*%< To be recycled */
131 /*%< mctx pool for clients. */
132 unsigned int nextmctx
;
133 isc_mem_t
* mctxpool
[NMCTXS
];
137 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
138 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
141 * Client object states. Ordering is significant: higher-numbered
142 * states are generally "more active", meaning that the client can
143 * have more dynamically allocated data, outstanding events, etc.
144 * In the list below, any such properties listed for state N
145 * also apply to any state > N.
147 * To force the client into a less active state, set client->newstate
148 * to that state and call exit_check(). This will cause any
149 * activities defined for higher-numbered states to be aborted.
152 #define NS_CLIENTSTATE_FREED 0
154 * The client object no longer exists.
157 #define NS_CLIENTSTATE_INACTIVE 1
159 * The client object exists and has a task and timer.
160 * Its "query" struct and sendbuf are initialized.
161 * It is on the client manager's list of inactive clients.
162 * It has a message and OPT, both in the reset state.
165 #define NS_CLIENTSTATE_READY 2
167 * The client object is either a TCP or a UDP one, and
168 * it is associated with a network interface. It is on the
169 * client manager's list of active clients.
171 * If it is a TCP client object, it has a TCP listener socket
172 * and an outstanding TCP listen request.
174 * If it is a UDP client object, it has a UDP listener socket
175 * and an outstanding UDP receive request.
178 #define NS_CLIENTSTATE_READING 3
180 * The client object is a TCP client object that has received
181 * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
182 * outstanding TCP read request. This state is not used for
183 * UDP client objects.
186 #define NS_CLIENTSTATE_WORKING 4
188 * The client object has received a request and is working
189 * on it. It has a view, and it may have any of a non-reset OPT,
190 * recursion quota, and an outstanding write request.
193 #define NS_CLIENTSTATE_MAX 9
195 * Sentinel value used to indicate "no state". When client->newstate
196 * has this value, we are not attempting to exit the current state.
197 * Must be greater than any valid state.
201 * Enable ns_client_dropport() by default.
203 #ifndef NS_CLIENT_DROPPORT
204 #define NS_CLIENT_DROPPORT 1
207 unsigned int ns_client_requests
;
209 static void client_read(ns_client_t
*client
);
210 static void client_accept(ns_client_t
*client
);
211 static void client_udprecv(ns_client_t
*client
);
212 static void clientmgr_destroy(ns_clientmgr_t
*manager
);
213 static isc_boolean_t
exit_check(ns_client_t
*client
);
214 static void ns_client_endrequest(ns_client_t
*client
);
215 static void ns_client_checkactive(ns_client_t
*client
);
216 static void client_start(isc_task_t
*task
, isc_event_t
*event
);
217 static void client_request(isc_task_t
*task
, isc_event_t
*event
);
218 static void ns_client_dumpmessage(ns_client_t
*client
, const char *reason
);
221 ns_client_recursing(ns_client_t
*client
) {
222 REQUIRE(NS_CLIENT_VALID(client
));
224 LOCK(&client
->manager
->lock
);
225 ISC_LIST_UNLINK(*client
->list
, client
, link
);
226 ISC_LIST_APPEND(client
->manager
->recursing
, client
, link
);
227 client
->list
= &client
->manager
->recursing
;
228 UNLOCK(&client
->manager
->lock
);
232 ns_client_killoldestquery(ns_client_t
*client
) {
234 REQUIRE(NS_CLIENT_VALID(client
));
236 LOCK(&client
->manager
->lock
);
237 oldest
= ISC_LIST_HEAD(client
->manager
->recursing
);
238 if (oldest
!= NULL
) {
239 ns_query_cancel(oldest
);
240 ISC_LIST_UNLINK(*oldest
->list
, oldest
, link
);
241 ISC_LIST_APPEND(client
->manager
->active
, oldest
, link
);
242 oldest
->list
= &client
->manager
->active
;
244 UNLOCK(&client
->manager
->lock
);
248 ns_client_settimeout(ns_client_t
*client
, unsigned int seconds
) {
250 isc_interval_t interval
;
252 isc_interval_set(&interval
, seconds
, 0);
253 result
= isc_timer_reset(client
->timer
, isc_timertype_once
, NULL
,
254 &interval
, ISC_FALSE
);
255 client
->timerset
= ISC_TRUE
;
256 if (result
!= ISC_R_SUCCESS
) {
257 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
258 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
259 "setting timeout: %s",
260 isc_result_totext(result
));
261 /* Continue anyway. */
266 * Check for a deactivation or shutdown request and take appropriate
267 * action. Returns ISC_TRUE if either is in progress; in this case
268 * the caller must no longer use the client object as it may have been
272 exit_check(ns_client_t
*client
) {
273 ns_clientmgr_t
*locked_manager
= NULL
;
274 ns_clientmgr_t
*destroy_manager
= NULL
;
276 REQUIRE(NS_CLIENT_VALID(client
));
278 if (client
->state
<= client
->newstate
)
279 return (ISC_FALSE
); /* Business as usual. */
281 INSIST(client
->newstate
< NS_CLIENTSTATE_WORKING
);
284 * We need to detach from the view early when shutting down
285 * the server to break the following vicious circle:
287 * - The resolver will not shut down until the view refcount is zero
288 * - The view refcount does not go to zero until all clients detach
289 * - The client does not detach from the view until references is zero
290 * - references does not go to zero until the resolver has shut down
292 * Keep the view attached until any outstanding updates complete.
294 if (client
->nupdates
== 0 &&
295 client
->newstate
== NS_CLIENTSTATE_FREED
&& client
->view
!= NULL
)
296 dns_view_detach(&client
->view
);
298 if (client
->state
== NS_CLIENTSTATE_WORKING
) {
299 INSIST(client
->newstate
<= NS_CLIENTSTATE_READING
);
301 * Let the update processing complete.
303 if (client
->nupdates
> 0)
306 * We are trying to abort request processing.
308 if (client
->nsends
> 0) {
309 isc_socket_t
*socket
;
310 if (TCP_CLIENT(client
))
311 socket
= client
->tcpsocket
;
313 socket
= client
->udpsocket
;
314 isc_socket_cancel(socket
, client
->task
,
315 ISC_SOCKCANCEL_SEND
);
318 if (! (client
->nsends
== 0 && client
->nrecvs
== 0 &&
319 client
->references
== 0))
322 * Still waiting for I/O cancel completion.
323 * or lingering references.
328 * I/O cancel is complete. Burn down all state
329 * related to the current request. Ensure that
330 * the client is on the active list and not the
333 LOCK(&client
->manager
->lock
);
334 if (client
->list
== &client
->manager
->recursing
) {
335 ISC_LIST_UNLINK(*client
->list
, client
, link
);
336 ISC_LIST_APPEND(client
->manager
->active
, client
, link
);
337 client
->list
= &client
->manager
->active
;
339 UNLOCK(&client
->manager
->lock
);
340 ns_client_endrequest(client
);
342 client
->state
= NS_CLIENTSTATE_READING
;
343 INSIST(client
->recursionquota
== NULL
);
344 if (NS_CLIENTSTATE_READING
== client
->newstate
) {
346 client
->newstate
= NS_CLIENTSTATE_MAX
;
347 return (ISC_TRUE
); /* We're done. */
351 if (client
->state
== NS_CLIENTSTATE_READING
) {
353 * We are trying to abort the current TCP connection,
356 INSIST(client
->recursionquota
== NULL
);
357 INSIST(client
->newstate
<= NS_CLIENTSTATE_READY
);
358 if (client
->nreads
> 0)
359 dns_tcpmsg_cancelread(&client
->tcpmsg
);
360 if (! client
->nreads
== 0) {
361 /* Still waiting for read cancel completion. */
365 if (client
->tcpmsg_valid
) {
366 dns_tcpmsg_invalidate(&client
->tcpmsg
);
367 client
->tcpmsg_valid
= ISC_FALSE
;
369 if (client
->tcpsocket
!= NULL
) {
371 isc_socket_detach(&client
->tcpsocket
);
374 if (client
->tcpquota
!= NULL
)
375 isc_quota_detach(&client
->tcpquota
);
377 if (client
->timerset
) {
378 (void)isc_timer_reset(client
->timer
,
379 isc_timertype_inactive
,
380 NULL
, NULL
, ISC_TRUE
);
381 client
->timerset
= ISC_FALSE
;
384 client
->peeraddr_valid
= ISC_FALSE
;
386 client
->state
= NS_CLIENTSTATE_READY
;
387 INSIST(client
->recursionquota
== NULL
);
390 * Now the client is ready to accept a new TCP connection
391 * or UDP request, but we may have enough clients doing
392 * that already. Check whether this client needs to remain
393 * active and force it to go inactive if not.
395 ns_client_checkactive(client
);
397 if (NS_CLIENTSTATE_READY
== client
->newstate
) {
398 if (TCP_CLIENT(client
)) {
399 client_accept(client
);
401 client_udprecv(client
);
402 client
->newstate
= NS_CLIENTSTATE_MAX
;
407 if (client
->state
== NS_CLIENTSTATE_READY
) {
408 INSIST(client
->newstate
<= NS_CLIENTSTATE_INACTIVE
);
410 * We are trying to enter the inactive state.
412 if (client
->naccepts
> 0)
413 isc_socket_cancel(client
->tcplistener
, client
->task
,
414 ISC_SOCKCANCEL_ACCEPT
);
416 if (! (client
->naccepts
== 0)) {
417 /* Still waiting for accept cancel completion. */
420 /* Accept cancel is complete. */
422 if (client
->nrecvs
> 0)
423 isc_socket_cancel(client
->udpsocket
, client
->task
,
424 ISC_SOCKCANCEL_RECV
);
425 if (! (client
->nrecvs
== 0)) {
426 /* Still waiting for recv cancel completion. */
429 /* Recv cancel is complete. */
431 if (client
->nctls
> 0) {
432 /* Still waiting for control event to be delivered */
436 /* Deactivate the client. */
437 if (client
->interface
)
438 ns_interface_detach(&client
->interface
);
440 INSIST(client
->naccepts
== 0);
441 INSIST(client
->recursionquota
== NULL
);
442 if (client
->tcplistener
!= NULL
)
443 isc_socket_detach(&client
->tcplistener
);
445 if (client
->udpsocket
!= NULL
)
446 isc_socket_detach(&client
->udpsocket
);
448 if (client
->dispatch
!= NULL
)
449 dns_dispatch_detach(&client
->dispatch
);
451 client
->attributes
= 0;
452 client
->mortal
= ISC_FALSE
;
454 LOCK(&client
->manager
->lock
);
456 * Put the client on the inactive list. If we are aiming for
457 * the "freed" state, it will be removed from the inactive
458 * list shortly, and we need to keep the manager locked until
459 * that has been done, lest the manager decide to reactivate
460 * the dying client inbetween.
462 locked_manager
= client
->manager
;
463 ISC_LIST_UNLINK(*client
->list
, client
, link
);
464 ISC_LIST_APPEND(client
->manager
->inactive
, client
, link
);
465 client
->list
= &client
->manager
->inactive
;
466 client
->state
= NS_CLIENTSTATE_INACTIVE
;
467 INSIST(client
->recursionquota
== NULL
);
469 if (client
->state
== client
->newstate
) {
470 client
->newstate
= NS_CLIENTSTATE_MAX
;
471 if (client
->needshutdown
)
472 isc_task_shutdown(client
->task
);
477 if (client
->state
== NS_CLIENTSTATE_INACTIVE
) {
478 INSIST(client
->newstate
== NS_CLIENTSTATE_FREED
);
480 * We are trying to free the client.
482 * When "shuttingdown" is true, either the task has received
483 * its shutdown event or no shutdown event has ever been
484 * set up. Thus, we have no outstanding shutdown
485 * event at this point.
487 REQUIRE(client
->state
== NS_CLIENTSTATE_INACTIVE
);
489 INSIST(client
->recursionquota
== NULL
);
491 ns_query_free(client
);
492 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
493 isc_event_free((isc_event_t
**)&client
->sendevent
);
494 isc_event_free((isc_event_t
**)&client
->recvevent
);
495 isc_timer_detach(&client
->timer
);
497 if (client
->tcpbuf
!= NULL
)
498 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
499 if (client
->opt
!= NULL
) {
500 INSIST(dns_rdataset_isassociated(client
->opt
));
501 dns_rdataset_disassociate(client
->opt
);
502 dns_message_puttemprdataset(client
->message
, &client
->opt
);
504 dns_message_destroy(&client
->message
);
505 if (client
->manager
!= NULL
) {
506 ns_clientmgr_t
*manager
= client
->manager
;
507 if (locked_manager
== NULL
) {
508 LOCK(&manager
->lock
);
509 locked_manager
= manager
;
511 ISC_LIST_UNLINK(*client
->list
, client
, link
);
513 if (manager
->exiting
&&
514 ISC_LIST_EMPTY(manager
->active
) &&
515 ISC_LIST_EMPTY(manager
->inactive
) &&
516 ISC_LIST_EMPTY(manager
->recursing
))
517 destroy_manager
= manager
;
520 * Detaching the task must be done after unlinking from
521 * the manager's lists because the manager accesses
524 if (client
->task
!= NULL
)
525 isc_task_detach(&client
->task
);
530 * Check that there are no other external references to
531 * the memory context.
533 if (ns_g_clienttest
&& isc_mem_references(client
->mctx
) != 1) {
534 isc_mem_stats(client
->mctx
, stderr
);
537 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
543 if (locked_manager
!= NULL
) {
544 UNLOCK(&locked_manager
->lock
);
545 locked_manager
= NULL
;
549 * Only now is it safe to destroy the client manager (if needed),
550 * because we have accessed its lock for the last time.
552 if (destroy_manager
!= NULL
)
553 clientmgr_destroy(destroy_manager
);
559 * The client's task has received the client's control event
560 * as part of the startup process.
563 client_start(isc_task_t
*task
, isc_event_t
*event
) {
564 ns_client_t
*client
= (ns_client_t
*) event
->ev_arg
;
566 INSIST(task
== client
->task
);
570 INSIST(client
->nctls
== 1);
573 if (exit_check(client
))
576 if (TCP_CLIENT(client
)) {
577 client_accept(client
);
579 client_udprecv(client
);
585 * The client's task has received a shutdown event.
588 client_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
591 REQUIRE(event
!= NULL
);
592 REQUIRE(event
->ev_type
== ISC_TASKEVENT_SHUTDOWN
);
593 client
= event
->ev_arg
;
594 REQUIRE(NS_CLIENT_VALID(client
));
595 REQUIRE(task
== client
->task
);
601 isc_event_free(&event
);
603 if (client
->shutdown
!= NULL
) {
604 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_SHUTTINGDOWN
);
605 client
->shutdown
= NULL
;
606 client
->shutdown_arg
= NULL
;
609 client
->newstate
= NS_CLIENTSTATE_FREED
;
610 client
->needshutdown
= ISC_FALSE
;
611 (void)exit_check(client
);
615 ns_client_endrequest(ns_client_t
*client
) {
616 INSIST(client
->naccepts
== 0);
617 INSIST(client
->nreads
== 0);
618 INSIST(client
->nsends
== 0);
619 INSIST(client
->nrecvs
== 0);
620 INSIST(client
->nupdates
== 0);
621 INSIST(client
->state
== NS_CLIENTSTATE_WORKING
);
623 CTRACE("endrequest");
625 if (client
->next
!= NULL
) {
626 (client
->next
)(client
);
630 if (client
->view
!= NULL
)
631 dns_view_detach(&client
->view
);
632 if (client
->opt
!= NULL
) {
633 INSIST(dns_rdataset_isassociated(client
->opt
));
634 dns_rdataset_disassociate(client
->opt
);
635 dns_message_puttemprdataset(client
->message
, &client
->opt
);
638 client
->udpsize
= 512;
639 client
->extflags
= 0;
640 client
->ednsversion
= -1;
641 dns_message_reset(client
->message
, DNS_MESSAGE_INTENTPARSE
);
643 if (client
->recursionquota
!= NULL
)
644 isc_quota_detach(&client
->recursionquota
);
647 * Clear all client attributes that are specific to
648 * the request; that's all except the TCP flag.
650 client
->attributes
&= NS_CLIENTATTR_TCP
;
654 ns_client_checkactive(ns_client_t
*client
) {
655 if (client
->mortal
) {
657 * This client object should normally go inactive
658 * at this point, but if we have fewer active client
659 * objects than desired due to earlier quota exhaustion,
660 * keep it active to make up for the shortage.
662 isc_boolean_t need_another_client
= ISC_FALSE
;
663 if (TCP_CLIENT(client
) && !ns_g_clienttest
) {
664 LOCK(&client
->interface
->lock
);
665 if (client
->interface
->ntcpcurrent
<
666 client
->interface
->ntcptarget
)
667 need_another_client
= ISC_TRUE
;
668 UNLOCK(&client
->interface
->lock
);
671 * The UDP client quota is enforced by making
672 * requests fail rather than by not listening
673 * for new ones. Therefore, there is always a
674 * full set of UDP clients listening.
677 if (! need_another_client
) {
679 * We don't need this client object. Recycle it.
681 if (client
->newstate
>= NS_CLIENTSTATE_INACTIVE
)
682 client
->newstate
= NS_CLIENTSTATE_INACTIVE
;
688 ns_client_next(ns_client_t
*client
, isc_result_t result
) {
691 REQUIRE(NS_CLIENT_VALID(client
));
692 REQUIRE(client
->state
== NS_CLIENTSTATE_WORKING
||
693 client
->state
== NS_CLIENTSTATE_READING
);
697 if (result
!= ISC_R_SUCCESS
)
698 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
699 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
700 "request failed: %s", isc_result_totext(result
));
703 * An error processing a TCP request may have left
704 * the connection out of sync. To be safe, we always
705 * sever the connection when result != ISC_R_SUCCESS.
707 if (result
== ISC_R_SUCCESS
&& TCP_CLIENT(client
))
708 newstate
= NS_CLIENTSTATE_READING
;
710 newstate
= NS_CLIENTSTATE_READY
;
712 if (client
->newstate
> newstate
)
713 client
->newstate
= newstate
;
714 (void)exit_check(client
);
719 client_senddone(isc_task_t
*task
, isc_event_t
*event
) {
721 isc_socketevent_t
*sevent
= (isc_socketevent_t
*) event
;
723 REQUIRE(sevent
!= NULL
);
724 REQUIRE(sevent
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
725 client
= sevent
->ev_arg
;
726 REQUIRE(NS_CLIENT_VALID(client
));
727 REQUIRE(task
== client
->task
);
728 REQUIRE(sevent
== client
->sendevent
);
734 if (sevent
->result
!= ISC_R_SUCCESS
)
735 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
736 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
737 "error sending response: %s",
738 isc_result_totext(sevent
->result
));
740 INSIST(client
->nsends
> 0);
743 if (client
->tcpbuf
!= NULL
) {
744 INSIST(TCP_CLIENT(client
));
745 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
746 client
->tcpbuf
= NULL
;
749 if (exit_check(client
))
752 ns_client_next(client
, ISC_R_SUCCESS
);
756 * We only want to fail with ISC_R_NOSPACE when called from
757 * ns_client_sendraw() and not when called from ns_client_send(),
758 * tcpbuffer is NULL when called from ns_client_sendraw() and
759 * length != 0. tcpbuffer != NULL when called from ns_client_send()
764 client_allocsendbuf(ns_client_t
*client
, isc_buffer_t
*buffer
,
765 isc_buffer_t
*tcpbuffer
, isc_uint32_t length
,
766 unsigned char *sendbuf
, unsigned char **datap
)
769 isc_uint32_t bufsize
;
772 INSIST(datap
!= NULL
);
773 INSIST((tcpbuffer
== NULL
&& length
!= 0) ||
774 (tcpbuffer
!= NULL
&& length
== 0));
776 if (TCP_CLIENT(client
)) {
777 INSIST(client
->tcpbuf
== NULL
);
778 if (length
+ 2 > TCP_BUFFER_SIZE
) {
779 result
= ISC_R_NOSPACE
;
782 client
->tcpbuf
= isc_mem_get(client
->mctx
, TCP_BUFFER_SIZE
);
783 if (client
->tcpbuf
== NULL
) {
784 result
= ISC_R_NOMEMORY
;
787 data
= client
->tcpbuf
;
788 if (tcpbuffer
!= NULL
) {
789 isc_buffer_init(tcpbuffer
, data
, TCP_BUFFER_SIZE
);
790 isc_buffer_init(buffer
, data
+ 2, TCP_BUFFER_SIZE
- 2);
792 isc_buffer_init(buffer
, data
, TCP_BUFFER_SIZE
);
793 INSIST(length
<= 0xffff);
794 isc_buffer_putuint16(buffer
, (isc_uint16_t
)length
);
798 if (client
->udpsize
< SEND_BUFFER_SIZE
)
799 bufsize
= client
->udpsize
;
801 bufsize
= SEND_BUFFER_SIZE
;
802 if (length
> bufsize
) {
803 result
= ISC_R_NOSPACE
;
806 isc_buffer_init(buffer
, data
, bufsize
);
809 result
= ISC_R_SUCCESS
;
816 client_sendpkg(ns_client_t
*client
, isc_buffer_t
*buffer
) {
817 struct in6_pktinfo
*pktinfo
;
820 isc_sockaddr_t
*address
;
821 isc_socket_t
*socket
;
822 isc_netaddr_t netaddr
;
824 unsigned int sockflags
= ISC_SOCKFLAG_IMMEDIATE
;
826 if (TCP_CLIENT(client
)) {
827 socket
= client
->tcpsocket
;
830 socket
= client
->udpsocket
;
831 address
= &client
->peeraddr
;
833 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
834 if (ns_g_server
->blackholeacl
!= NULL
&&
835 dns_acl_match(&netaddr
, NULL
,
836 ns_g_server
->blackholeacl
,
837 &ns_g_server
->aclenv
,
838 &match
, NULL
) == ISC_R_SUCCESS
&&
840 return (DNS_R_BLACKHOLED
);
841 sockflags
|= ISC_SOCKFLAG_NORETRY
;
844 if ((client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0 &&
845 (client
->attributes
& NS_CLIENTATTR_MULTICAST
) == 0)
846 pktinfo
= &client
->pktinfo
;
850 isc_buffer_usedregion(buffer
, &r
);
854 result
= isc_socket_sendto2(socket
, &r
, client
->task
,
856 client
->sendevent
, sockflags
);
857 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_INPROGRESS
) {
859 if (result
== ISC_R_SUCCESS
)
860 client_senddone(client
->task
,
861 (isc_event_t
*)client
->sendevent
);
862 result
= ISC_R_SUCCESS
;
868 ns_client_sendraw(ns_client_t
*client
, dns_message_t
*message
) {
874 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
876 REQUIRE(NS_CLIENT_VALID(client
));
880 mr
= dns_message_getrawmessage(message
);
882 result
= ISC_R_UNEXPECTEDEND
;
886 result
= client_allocsendbuf(client
, &buffer
, NULL
, mr
->length
,
888 if (result
!= ISC_R_SUCCESS
)
892 * Copy message to buffer and fixup id.
894 isc_buffer_availableregion(&buffer
, &r
);
895 result
= isc_buffer_copyregion(&buffer
, mr
);
896 if (result
!= ISC_R_SUCCESS
)
898 r
.base
[0] = (client
->message
->id
>> 8) & 0xff;
899 r
.base
[1] = client
->message
->id
& 0xff;
901 result
= client_sendpkg(client
, &buffer
);
902 if (result
== ISC_R_SUCCESS
)
906 if (client
->tcpbuf
!= NULL
) {
907 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
908 client
->tcpbuf
= NULL
;
910 ns_client_next(client
, result
);
914 ns_client_send(ns_client_t
*client
) {
918 isc_buffer_t tcpbuffer
;
921 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
922 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
923 unsigned int render_opts
;
924 unsigned int preferred_glue
;
925 isc_boolean_t opt_included
= ISC_FALSE
;
927 REQUIRE(NS_CLIENT_VALID(client
));
931 if ((client
->attributes
& NS_CLIENTATTR_RA
) != 0)
932 client
->message
->flags
|= DNS_MESSAGEFLAG_RA
;
934 if ((client
->attributes
& NS_CLIENTATTR_WANTDNSSEC
) != 0)
937 render_opts
= DNS_MESSAGERENDER_OMITDNSSEC
;
938 #ifdef ALLOW_FILTER_AAAA_ON_V4
940 * filter-aaaa-on-v4 yes or break-dnssec option to suppress
942 * We already know that request came via IPv4,
943 * that we have both AAAA and A records,
944 * and that we either have no signatures that the client wants
945 * or we are supposed to break DNSSEC.
947 if ((client
->attributes
& NS_CLIENTATTR_FILTER_AAAA
) != 0)
948 render_opts
|= DNS_MESSAGERENDER_FILTER_AAAA
;
951 if (client
->view
!= NULL
) {
952 if (client
->view
->preferred_glue
== dns_rdatatype_a
)
953 preferred_glue
= DNS_MESSAGERENDER_PREFER_A
;
954 else if (client
->view
->preferred_glue
== dns_rdatatype_aaaa
)
955 preferred_glue
= DNS_MESSAGERENDER_PREFER_AAAA
;
959 * XXXRTH The following doesn't deal with TCP buffer resizing.
961 result
= client_allocsendbuf(client
, &buffer
, &tcpbuffer
, 0,
963 if (result
!= ISC_R_SUCCESS
)
966 result
= dns_compress_init(&cctx
, -1, client
->mctx
);
967 if (result
!= ISC_R_SUCCESS
)
969 cleanup_cctx
= ISC_TRUE
;
971 result
= dns_message_renderbegin(client
->message
, &cctx
, &buffer
);
972 if (result
!= ISC_R_SUCCESS
)
975 if (client
->opt
!= NULL
) {
976 result
= dns_message_setopt(client
->message
, client
->opt
);
977 opt_included
= ISC_TRUE
;
979 if (result
!= ISC_R_SUCCESS
)
982 result
= dns_message_rendersection(client
->message
,
983 DNS_SECTION_QUESTION
, 0);
984 if (result
== ISC_R_NOSPACE
) {
985 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
988 if (result
!= ISC_R_SUCCESS
)
990 result
= dns_message_rendersection(client
->message
,
992 DNS_MESSAGERENDER_PARTIAL
|
994 if (result
== ISC_R_NOSPACE
) {
995 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
998 if (result
!= ISC_R_SUCCESS
)
1000 result
= dns_message_rendersection(client
->message
,
1001 DNS_SECTION_AUTHORITY
,
1002 DNS_MESSAGERENDER_PARTIAL
|
1004 if (result
== ISC_R_NOSPACE
) {
1005 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
1008 if (result
!= ISC_R_SUCCESS
)
1010 result
= dns_message_rendersection(client
->message
,
1011 DNS_SECTION_ADDITIONAL
,
1012 preferred_glue
| render_opts
);
1013 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
1016 result
= dns_message_renderend(client
->message
);
1018 if (result
!= ISC_R_SUCCESS
)
1022 dns_compress_invalidate(&cctx
);
1023 cleanup_cctx
= ISC_FALSE
;
1026 if (TCP_CLIENT(client
)) {
1027 isc_buffer_usedregion(&buffer
, &r
);
1028 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
) r
.length
);
1029 isc_buffer_add(&tcpbuffer
, r
.length
);
1030 result
= client_sendpkg(client
, &tcpbuffer
);
1032 result
= client_sendpkg(client
, &buffer
);
1034 /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1035 isc_stats_increment(ns_g_server
->nsstats
, dns_nsstatscounter_response
);
1037 isc_stats_increment(ns_g_server
->nsstats
,
1038 dns_nsstatscounter_edns0out
);
1040 if (client
->message
->tsigkey
!= NULL
) {
1041 isc_stats_increment(ns_g_server
->nsstats
,
1042 dns_nsstatscounter_tsigout
);
1044 if (client
->message
->sig0key
!= NULL
) {
1045 isc_stats_increment(ns_g_server
->nsstats
,
1046 dns_nsstatscounter_sig0out
);
1048 if ((client
->message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
1049 isc_stats_increment(ns_g_server
->nsstats
,
1050 dns_nsstatscounter_truncatedresp
);
1052 if (result
== ISC_R_SUCCESS
)
1056 if (client
->tcpbuf
!= NULL
) {
1057 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
1058 client
->tcpbuf
= NULL
;
1062 dns_compress_invalidate(&cctx
);
1064 ns_client_next(client
, result
);
1067 #if NS_CLIENT_DROPPORT
1068 #define DROPPORT_NO 0
1069 #define DROPPORT_REQUEST 1
1070 #define DROPPORT_RESPONSE 2
1072 * ns_client_dropport determines if certain requests / responses
1073 * should be dropped based on the port number.
1076 * \li 0: Don't drop.
1077 * \li 1: Drop request.
1078 * \li 2: Drop (error) response.
1081 ns_client_dropport(in_port_t port
) {
1084 case 13: /* daytime */
1085 case 19: /* chargen */
1087 return (DROPPORT_REQUEST
);
1088 case 464: /* kpasswd */
1089 return (DROPPORT_RESPONSE
);
1091 return (DROPPORT_NO
);
1096 ns_client_error(ns_client_t
*client
, isc_result_t result
) {
1098 dns_message_t
*message
;
1100 REQUIRE(NS_CLIENT_VALID(client
));
1104 message
= client
->message
;
1105 rcode
= dns_result_torcode(result
);
1107 #if NS_CLIENT_DROPPORT
1109 * Don't send FORMERR to ports on the drop port list.
1111 if (rcode
== dns_rcode_formerr
&&
1112 ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) !=
1117 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
1118 if (dns_rcode_totext(rcode
, &b
) != ISC_R_SUCCESS
)
1119 isc_buffer_putstr(&b
, "UNKNOWN RCODE");
1120 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1121 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1122 "dropped error (%.*s) response: suspicious port",
1123 (int)isc_buffer_usedlength(&b
), buf
);
1124 ns_client_next(client
, ISC_R_SUCCESS
);
1130 * Message may be an in-progress reply that we had trouble
1131 * with, in which case QR will be set. We need to clear QR before
1132 * calling dns_message_reply() to avoid triggering an assertion.
1134 message
->flags
&= ~DNS_MESSAGEFLAG_QR
;
1136 * AA and AD shouldn't be set.
1138 message
->flags
&= ~(DNS_MESSAGEFLAG_AA
| DNS_MESSAGEFLAG_AD
);
1139 result
= dns_message_reply(message
, ISC_TRUE
);
1140 if (result
!= ISC_R_SUCCESS
) {
1142 * It could be that we've got a query with a good header,
1143 * but a bad question section, so we try again with
1144 * want_question_section set to ISC_FALSE.
1146 result
= dns_message_reply(message
, ISC_FALSE
);
1147 if (result
!= ISC_R_SUCCESS
) {
1148 ns_client_next(client
, result
);
1152 message
->rcode
= rcode
;
1155 * FORMERR loop avoidance: If we sent a FORMERR message
1156 * with the same ID to the same client less than two
1157 * seconds ago, assume that we are in an infinite error
1158 * packet dialog with a server for some protocol whose
1159 * error responses look enough like DNS queries to
1160 * elicit a FORMERR response. Drop a packet to break
1163 if (rcode
== dns_rcode_formerr
) {
1164 if (isc_sockaddr_equal(&client
->peeraddr
,
1165 &client
->formerrcache
.addr
) &&
1166 message
->id
== client
->formerrcache
.id
&&
1167 client
->requesttime
- client
->formerrcache
.time
< 2) {
1169 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1170 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1171 "possible error packet loop, "
1173 ns_client_next(client
, result
);
1176 client
->formerrcache
.addr
= client
->peeraddr
;
1177 client
->formerrcache
.time
= client
->requesttime
;
1178 client
->formerrcache
.id
= message
->id
;
1180 ns_client_send(client
);
1183 static inline isc_result_t
1184 client_addopt(ns_client_t
*client
) {
1185 dns_rdataset_t
*rdataset
;
1186 dns_rdatalist_t
*rdatalist
;
1188 isc_result_t result
;
1190 dns_resolver_t
*resolver
;
1191 isc_uint16_t udpsize
;
1193 REQUIRE(client
->opt
== NULL
); /* XXXRTH free old. */
1196 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
1197 if (result
!= ISC_R_SUCCESS
)
1200 result
= dns_message_gettemprdata(client
->message
, &rdata
);
1201 if (result
!= ISC_R_SUCCESS
)
1204 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
1205 if (result
!= ISC_R_SUCCESS
)
1207 dns_rdataset_init(rdataset
);
1209 rdatalist
->type
= dns_rdatatype_opt
;
1210 rdatalist
->covers
= 0;
1213 * Set the maximum UDP buffer size.
1215 view
= client
->view
;
1216 resolver
= (view
!= NULL
) ? view
->resolver
: NULL
;
1217 if (resolver
!= NULL
)
1218 udpsize
= dns_resolver_getudpsize(resolver
);
1220 udpsize
= ns_g_udpsize
;
1221 rdatalist
->rdclass
= udpsize
;
1224 * Set EXTENDED-RCODE, VERSION and Z to 0.
1226 rdatalist
->ttl
= (client
->extflags
& DNS_MESSAGEEXTFLAG_REPLYPRESERVE
);
1228 /* Set EDNS options if applicable */
1229 if (client
->attributes
& NS_CLIENTATTR_WANTNSID
&&
1230 (ns_g_server
->server_id
!= NULL
||
1231 ns_g_server
->server_usehostname
)) {
1233 * Space required for NSID data:
1234 * 2 bytes for opt code
1235 * + 2 bytes for NSID length
1238 char nsid
[BUFSIZ
], *nsidp
;
1239 isc_buffer_t
*buffer
= NULL
;
1241 if (ns_g_server
->server_usehostname
) {
1242 isc_result_t result
;
1243 result
= ns_os_gethostname(nsid
, sizeof(nsid
));
1244 if (result
!= ISC_R_SUCCESS
) {
1249 nsidp
= ns_g_server
->server_id
;
1251 rdata
->length
= strlen(nsidp
) + 4;
1252 result
= isc_buffer_allocate(client
->mctx
, &buffer
,
1254 if (result
!= ISC_R_SUCCESS
)
1257 isc_buffer_putuint16(buffer
, DNS_OPT_NSID
);
1258 isc_buffer_putuint16(buffer
, strlen(nsidp
));
1259 isc_buffer_putstr(buffer
, nsidp
);
1260 rdata
->data
= buffer
->base
;
1261 dns_message_takebuffer(client
->message
, &buffer
);
1268 rdata
->rdclass
= rdatalist
->rdclass
;
1269 rdata
->type
= rdatalist
->type
;
1272 ISC_LIST_INIT(rdatalist
->rdata
);
1273 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1274 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
)
1277 client
->opt
= rdataset
;
1279 return (ISC_R_SUCCESS
);
1282 static inline isc_boolean_t
1283 allowed(isc_netaddr_t
*addr
, dns_name_t
*signer
, dns_acl_t
*acl
) {
1285 isc_result_t result
;
1289 result
= dns_acl_match(addr
, signer
, acl
, &ns_g_server
->aclenv
,
1291 if (result
== ISC_R_SUCCESS
&& match
> 0)
1297 * Callback to see if a non-recursive query coming from 'srcaddr' to
1298 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1299 * delivered to 'myview'.
1301 * We run this unlocked as both the view list and the interface list
1302 * are updated when the appropriate task has exclusivity.
1305 ns_client_isself(dns_view_t
*myview
, dns_tsigkey_t
*mykey
,
1306 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*dstaddr
,
1307 dns_rdataclass_t rdclass
, void *arg
)
1310 dns_tsigkey_t
*key
= NULL
;
1311 dns_name_t
*tsig
= NULL
;
1312 isc_netaddr_t netsrc
;
1313 isc_netaddr_t netdst
;
1317 if (!ns_interfacemgr_listeningon(ns_g_server
->interfacemgr
, dstaddr
))
1320 isc_netaddr_fromsockaddr(&netsrc
, srcaddr
);
1321 isc_netaddr_fromsockaddr(&netdst
, dstaddr
);
1323 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1325 view
= ISC_LIST_NEXT(view
, link
)) {
1327 if (view
->matchrecursiveonly
)
1330 if (rdclass
!= view
->rdclass
)
1333 if (mykey
!= NULL
) {
1334 isc_boolean_t match
;
1335 isc_result_t result
;
1337 result
= dns_view_gettsig(view
, &mykey
->name
, &key
);
1338 if (result
!= ISC_R_SUCCESS
)
1340 match
= dst_key_compare(mykey
->key
, key
->key
);
1341 dns_tsigkey_detach(&key
);
1344 tsig
= dns_tsigkey_identity(mykey
);
1347 if (allowed(&netsrc
, tsig
, view
->matchclients
) &&
1348 allowed(&netdst
, tsig
, view
->matchdestinations
))
1351 return (ISC_TF(view
== myview
));
1355 * Handle an incoming request event from the socket (UDP case)
1356 * or tcpmsg (TCP case).
1359 client_request(isc_task_t
*task
, isc_event_t
*event
) {
1360 ns_client_t
*client
;
1361 isc_socketevent_t
*sevent
;
1362 isc_result_t result
;
1363 isc_result_t sigresult
= ISC_R_SUCCESS
;
1364 isc_buffer_t
*buffer
;
1365 isc_buffer_t tbuffer
;
1367 dns_rdataset_t
*opt
;
1368 dns_name_t
*signame
;
1369 isc_boolean_t ra
; /* Recursion available. */
1370 isc_netaddr_t netaddr
;
1374 isc_boolean_t notimp
;
1376 isc_uint16_t optcode
;
1378 REQUIRE(event
!= NULL
);
1379 client
= event
->ev_arg
;
1380 REQUIRE(NS_CLIENT_VALID(client
));
1381 REQUIRE(task
== client
->task
);
1383 INSIST(client
->recursionquota
== NULL
);
1385 INSIST(client
->state
==
1386 TCP_CLIENT(client
) ?
1387 NS_CLIENTSTATE_READING
:
1388 NS_CLIENTSTATE_READY
);
1390 ns_client_requests
++;
1392 if (event
->ev_type
== ISC_SOCKEVENT_RECVDONE
) {
1393 INSIST(!TCP_CLIENT(client
));
1394 sevent
= (isc_socketevent_t
*)event
;
1395 REQUIRE(sevent
== client
->recvevent
);
1396 isc_buffer_init(&tbuffer
, sevent
->region
.base
, sevent
->n
);
1397 isc_buffer_add(&tbuffer
, sevent
->n
);
1399 result
= sevent
->result
;
1400 if (result
== ISC_R_SUCCESS
) {
1401 client
->peeraddr
= sevent
->address
;
1402 client
->peeraddr_valid
= ISC_TRUE
;
1404 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_PKTINFO
) != 0) {
1405 client
->attributes
|= NS_CLIENTATTR_PKTINFO
;
1406 client
->pktinfo
= sevent
->pktinfo
;
1408 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_MULTICAST
) != 0)
1409 client
->attributes
|= NS_CLIENTATTR_MULTICAST
;
1412 INSIST(TCP_CLIENT(client
));
1413 REQUIRE(event
->ev_type
== DNS_EVENT_TCPMSG
);
1414 REQUIRE(event
->ev_sender
== &client
->tcpmsg
);
1415 buffer
= &client
->tcpmsg
.buffer
;
1416 result
= client
->tcpmsg
.result
;
1417 INSIST(client
->nreads
== 1);
1419 * client->peeraddr was set when the connection was accepted.
1424 if (exit_check(client
))
1426 client
->state
= client
->newstate
= NS_CLIENTSTATE_WORKING
;
1428 isc_task_getcurrenttime(task
, &client
->requesttime
);
1429 client
->now
= client
->requesttime
;
1431 if (result
!= ISC_R_SUCCESS
) {
1432 if (TCP_CLIENT(client
)) {
1433 ns_client_next(client
, result
);
1435 if (result
!= ISC_R_CANCELED
)
1436 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_CLIENT
,
1437 NS_LOGMODULE_CLIENT
,
1439 "UDP client handler shutting "
1440 "down due to fatal receive "
1442 isc_result_totext(result
));
1443 isc_task_shutdown(client
->task
);
1448 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1450 #if NS_CLIENT_DROPPORT
1451 if (ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) ==
1453 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1454 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1455 "dropped request: suspicious port");
1456 ns_client_next(client
, ISC_R_SUCCESS
);
1461 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1462 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1464 TCP_CLIENT(client
) ? "TCP" : "UDP");
1467 * Check the blackhole ACL for UDP only, since TCP is done in
1470 if (!TCP_CLIENT(client
)) {
1472 if (ns_g_server
->blackholeacl
!= NULL
&&
1473 dns_acl_match(&netaddr
, NULL
, ns_g_server
->blackholeacl
,
1474 &ns_g_server
->aclenv
,
1475 &match
, NULL
) == ISC_R_SUCCESS
&&
1478 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1479 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1480 "blackholed UDP datagram");
1481 ns_client_next(client
, ISC_R_SUCCESS
);
1487 * Silently drop multicast requests for the present.
1488 * XXXMPA revisit this as mDNS spec was published.
1490 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0) {
1491 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1492 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(2),
1493 "dropping multicast request");
1494 ns_client_next(client
, DNS_R_REFUSED
);
1498 result
= dns_message_peekheader(buffer
, &id
, &flags
);
1499 if (result
!= ISC_R_SUCCESS
) {
1501 * There isn't enough header to determine whether
1502 * this was a request or a response. Drop it.
1504 ns_client_next(client
, result
);
1509 * The client object handles requests, not responses.
1510 * If this is a UDP response, forward it to the dispatcher.
1511 * If it's a TCP response, discard it here.
1513 if ((flags
& DNS_MESSAGEFLAG_QR
) != 0) {
1514 if (TCP_CLIENT(client
)) {
1515 CTRACE("unexpected response");
1516 ns_client_next(client
, DNS_R_FORMERR
);
1519 dns_dispatch_importrecv(client
->dispatch
, event
);
1520 ns_client_next(client
, ISC_R_SUCCESS
);
1526 * Update some statistics counters. Don't count responses.
1528 if (isc_sockaddr_pf(&client
->peeraddr
) == PF_INET
) {
1529 isc_stats_increment(ns_g_server
->nsstats
,
1530 dns_nsstatscounter_requestv4
);
1532 isc_stats_increment(ns_g_server
->nsstats
,
1533 dns_nsstatscounter_requestv6
);
1535 if (TCP_CLIENT(client
))
1536 isc_stats_increment(ns_g_server
->nsstats
,
1537 dns_nsstatscounter_tcp
);
1540 * It's a request. Parse it.
1542 result
= dns_message_parse(client
->message
, buffer
, 0);
1543 if (result
!= ISC_R_SUCCESS
) {
1545 * Parsing the request failed. Send a response
1546 * (typically FORMERR or SERVFAIL).
1548 ns_client_error(client
, result
);
1552 dns_opcodestats_increment(ns_g_server
->opcodestats
,
1553 client
->message
->opcode
);
1554 switch (client
->message
->opcode
) {
1555 case dns_opcode_query
:
1556 case dns_opcode_update
:
1557 case dns_opcode_notify
:
1560 case dns_opcode_iquery
:
1566 client
->message
->rcode
= dns_rcode_noerror
;
1568 /* RFC1123 section 6.1.3.2 */
1569 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0)
1570 client
->message
->flags
&= ~DNS_MESSAGEFLAG_RD
;
1575 opt
= dns_message_getopt(client
->message
);
1578 * Set the client's UDP buffer size.
1580 client
->udpsize
= opt
->rdclass
;
1583 * If the requested UDP buffer size is less than 512,
1584 * ignore it and use 512.
1586 if (client
->udpsize
< 512)
1587 client
->udpsize
= 512;
1590 * Get the flags out of the OPT record.
1592 client
->extflags
= (isc_uint16_t
)(opt
->ttl
& 0xFFFF);
1595 * Do we understand this version of EDNS?
1597 * XXXRTH need library support for this!
1599 client
->ednsversion
= (opt
->ttl
& 0x00FF0000) >> 16;
1600 if (client
->ednsversion
> 0) {
1601 isc_stats_increment(ns_g_server
->nsstats
,
1602 dns_nsstatscounter_badednsver
);
1603 result
= client_addopt(client
);
1604 if (result
== ISC_R_SUCCESS
)
1605 result
= DNS_R_BADVERS
;
1606 ns_client_error(client
, result
);
1610 /* Check for NSID request */
1611 result
= dns_rdataset_first(opt
);
1612 if (result
== ISC_R_SUCCESS
) {
1613 dns_rdata_init(&rdata
);
1614 dns_rdataset_current(opt
, &rdata
);
1615 if (rdata
.length
>= 2) {
1616 isc_buffer_t nsidbuf
;
1617 isc_buffer_init(&nsidbuf
,
1618 rdata
.data
, rdata
.length
);
1619 isc_buffer_add(&nsidbuf
, rdata
.length
);
1620 optcode
= isc_buffer_getuint16(&nsidbuf
);
1621 if (optcode
== DNS_OPT_NSID
)
1622 client
->attributes
|=
1623 NS_CLIENTATTR_WANTNSID
;
1627 isc_stats_increment(ns_g_server
->nsstats
,
1628 dns_nsstatscounter_edns0in
);
1631 * Create an OPT for our reply.
1633 result
= client_addopt(client
);
1634 if (result
!= ISC_R_SUCCESS
) {
1635 ns_client_error(client
, result
);
1640 if (client
->message
->rdclass
== 0) {
1641 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1642 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1643 "message class could not be determined");
1644 ns_client_dumpmessage(client
,
1645 "message class could not be determined");
1646 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_FORMERR
);
1651 * Determine the destination address. If the receiving interface is
1652 * bound to a specific address, we simply use it regardless of the
1653 * address family. All IPv4 queries should fall into this case.
1654 * Otherwise, if this is a TCP query, get the address from the
1655 * receiving socket (this needs a system call and can be heavy).
1656 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1658 * If all the attempts fail (this can happen due to memory shortage,
1659 * etc), we regard this as an error for safety.
1661 if ((client
->interface
->flags
& NS_INTERFACEFLAG_ANYADDR
) == 0)
1662 isc_netaddr_fromsockaddr(&client
->destaddr
,
1663 &client
->interface
->addr
);
1665 isc_sockaddr_t sockaddr
;
1666 result
= ISC_R_FAILURE
;
1668 if (TCP_CLIENT(client
))
1669 result
= isc_socket_getsockname(client
->tcpsocket
,
1671 if (result
== ISC_R_SUCCESS
)
1672 isc_netaddr_fromsockaddr(&client
->destaddr
, &sockaddr
);
1673 if (result
!= ISC_R_SUCCESS
&&
1674 client
->interface
->addr
.type
.sa
.sa_family
== AF_INET6
&&
1675 (client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0) {
1677 * XXXJT technically, we should convert the receiving
1678 * interface ID to a proper scope zone ID. However,
1679 * due to the fact there is no standard API for this,
1680 * we only handle link-local addresses and use the
1681 * interface index as link ID. Despite the assumption,
1682 * it should cover most typical cases.
1684 isc_netaddr_fromin6(&client
->destaddr
,
1685 &client
->pktinfo
.ipi6_addr
);
1686 if (IN6_IS_ADDR_LINKLOCAL(&client
->pktinfo
.ipi6_addr
))
1687 isc_netaddr_setzone(&client
->destaddr
,
1688 client
->pktinfo
.ipi6_ifindex
);
1689 result
= ISC_R_SUCCESS
;
1691 if (result
!= ISC_R_SUCCESS
) {
1692 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1693 "failed to get request's "
1695 isc_result_totext(result
));
1696 ns_client_next(client
, ISC_R_SUCCESS
);
1702 * Find a view that matches the client's source address.
1704 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1706 view
= ISC_LIST_NEXT(view
, link
)) {
1707 if (client
->message
->rdclass
== view
->rdclass
||
1708 client
->message
->rdclass
== dns_rdataclass_any
)
1710 dns_name_t
*tsig
= NULL
;
1712 sigresult
= dns_message_rechecksig(client
->message
,
1714 if (sigresult
== ISC_R_SUCCESS
)
1715 tsig
= dns_tsigkey_identity(client
->message
->tsigkey
);
1717 if (allowed(&netaddr
, tsig
, view
->matchclients
) &&
1718 allowed(&client
->destaddr
, tsig
,
1719 view
->matchdestinations
) &&
1720 !((client
->message
->flags
& DNS_MESSAGEFLAG_RD
)
1721 == 0 && view
->matchrecursiveonly
))
1723 dns_view_attach(view
, &client
->view
);
1730 char classname
[DNS_RDATACLASS_FORMATSIZE
];
1733 * Do a dummy TSIG verification attempt so that the
1734 * response will have a TSIG if the query did, as
1735 * required by RFC2845.
1740 dns_message_resetsig(client
->message
);
1742 r
= dns_message_getrawmessage(client
->message
);
1743 isc_buffer_init(&b
, r
->base
, r
->length
);
1744 isc_buffer_add(&b
, r
->length
);
1745 (void)dns_tsig_verify(&b
, client
->message
, NULL
, NULL
);
1747 dns_rdataclass_format(client
->message
->rdclass
, classname
,
1749 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1750 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1751 "no matching view in class '%s'", classname
);
1752 ns_client_dumpmessage(client
, "no matching view in class");
1753 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_REFUSED
);
1757 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1758 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(5),
1759 "using view '%s'", view
->name
);
1762 * Check for a signature. We log bad signatures regardless of
1763 * whether they ultimately cause the request to be rejected or
1764 * not. We do not log the lack of a signature unless we are
1767 client
->signer
= NULL
;
1768 dns_name_init(&client
->signername
, NULL
);
1769 result
= dns_message_signer(client
->message
, &client
->signername
);
1770 if (result
!= ISC_R_NOTFOUND
) {
1772 if (dns_message_gettsig(client
->message
, &signame
) != NULL
) {
1773 isc_stats_increment(ns_g_server
->nsstats
,
1774 dns_nsstatscounter_tsigin
);
1776 isc_stats_increment(ns_g_server
->nsstats
,
1777 dns_nsstatscounter_sig0in
);
1781 if (result
== ISC_R_SUCCESS
) {
1782 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1783 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1784 "request has valid signature");
1785 client
->signer
= &client
->signername
;
1786 } else if (result
== ISC_R_NOTFOUND
) {
1787 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1788 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1789 "request is not signed");
1790 } else if (result
== DNS_R_NOIDENTITY
) {
1791 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1792 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1793 "request is signed by a nonauthoritative key");
1798 isc_result_t tresult
;
1800 /* There is a signature, but it is bad. */
1801 isc_stats_increment(ns_g_server
->nsstats
,
1802 dns_nsstatscounter_invalidsig
);
1804 if (dns_message_gettsig(client
->message
, &signame
) != NULL
) {
1805 char namebuf
[DNS_NAME_FORMATSIZE
];
1806 char cnamebuf
[DNS_NAME_FORMATSIZE
];
1807 dns_name_format(signame
, namebuf
, sizeof(namebuf
));
1808 status
= client
->message
->tsigstatus
;
1809 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
1810 tresult
= dns_tsigrcode_totext(status
, &b
);
1811 INSIST(tresult
== ISC_R_SUCCESS
);
1812 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
1813 if (client
->message
->tsigkey
->generated
) {
1814 dns_name_format(client
->message
->tsigkey
->creator
,
1815 cnamebuf
, sizeof(cnamebuf
));
1816 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1817 NS_LOGMODULE_CLIENT
,
1819 "request has invalid signature: "
1820 "TSIG %s (%s): %s (%s)", namebuf
,
1822 isc_result_totext(result
),
1825 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1826 NS_LOGMODULE_CLIENT
,
1828 "request has invalid signature: "
1829 "TSIG %s: %s (%s)", namebuf
,
1830 isc_result_totext(result
),
1834 status
= client
->message
->sig0status
;
1835 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
1836 tresult
= dns_tsigrcode_totext(status
, &b
);
1837 INSIST(tresult
== ISC_R_SUCCESS
);
1838 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
1839 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1840 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
1841 "request has invalid signature: %s (%s)",
1842 isc_result_totext(result
), tsigrcode
);
1845 * Accept update messages signed by unknown keys so that
1846 * update forwarding works transparently through slaves
1847 * that don't have all the same keys as the master.
1849 if (!(client
->message
->tsigstatus
== dns_tsigerror_badkey
&&
1850 client
->message
->opcode
== dns_opcode_update
)) {
1851 ns_client_error(client
, sigresult
);
1857 * Decide whether recursive service is available to this client.
1858 * We do this here rather than in the query code so that we can
1859 * set the RA bit correctly on all kinds of responses, not just
1860 * responses to ordinary queries. Note if you can't query the
1861 * cache there is no point in setting RA.
1864 if (client
->view
->resolver
!= NULL
&&
1865 client
->view
->recursion
== ISC_TRUE
&&
1866 ns_client_checkaclsilent(client
, NULL
,
1867 client
->view
->recursionacl
,
1868 ISC_TRUE
) == ISC_R_SUCCESS
&&
1869 ns_client_checkaclsilent(client
, NULL
,
1870 client
->view
->queryacl
,
1871 ISC_TRUE
) == ISC_R_SUCCESS
&&
1872 ns_client_checkaclsilent(client
, &client
->destaddr
,
1873 client
->view
->recursiononacl
,
1874 ISC_TRUE
) == ISC_R_SUCCESS
&&
1875 ns_client_checkaclsilent(client
, &client
->destaddr
,
1876 client
->view
->queryonacl
,
1877 ISC_TRUE
) == ISC_R_SUCCESS
)
1881 client
->attributes
|= NS_CLIENTATTR_RA
;
1883 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
, NS_LOGMODULE_CLIENT
,
1884 ISC_LOG_DEBUG(3), ra
? "recursion available" :
1885 "recursion not available");
1888 * Adjust maximum UDP response size for this client.
1890 if (client
->udpsize
> 512) {
1891 dns_peer_t
*peer
= NULL
;
1892 isc_uint16_t udpsize
= view
->maxudp
;
1893 (void) dns_peerlist_peerbyaddr(view
->peers
, &netaddr
, &peer
);
1895 dns_peer_getmaxudp(peer
, &udpsize
);
1896 if (client
->udpsize
> udpsize
)
1897 client
->udpsize
= udpsize
;
1901 * Dispatch the request.
1903 switch (client
->message
->opcode
) {
1904 case dns_opcode_query
:
1906 ns_query_start(client
);
1908 case dns_opcode_update
:
1910 ns_client_settimeout(client
, 60);
1911 ns_update_start(client
, sigresult
);
1913 case dns_opcode_notify
:
1915 ns_client_settimeout(client
, 60);
1916 ns_notify_start(client
);
1918 case dns_opcode_iquery
:
1920 ns_client_error(client
, DNS_R_NOTIMP
);
1923 CTRACE("unknown opcode");
1924 ns_client_error(client
, DNS_R_NOTIMP
);
1932 client_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1933 ns_client_t
*client
;
1935 REQUIRE(event
!= NULL
);
1936 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_LIFE
||
1937 event
->ev_type
== ISC_TIMEREVENT_IDLE
);
1938 client
= event
->ev_arg
;
1939 REQUIRE(NS_CLIENT_VALID(client
));
1940 REQUIRE(task
== client
->task
);
1941 REQUIRE(client
->timer
!= NULL
);
1947 isc_event_free(&event
);
1949 if (client
->shutdown
!= NULL
) {
1950 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_TIMEDOUT
);
1951 client
->shutdown
= NULL
;
1952 client
->shutdown_arg
= NULL
;
1955 if (client
->newstate
> NS_CLIENTSTATE_READY
)
1956 client
->newstate
= NS_CLIENTSTATE_READY
;
1957 (void)exit_check(client
);
1961 get_clientmctx(ns_clientmgr_t
*manager
, isc_mem_t
**mctxp
) {
1962 isc_mem_t
*clientmctx
;
1963 isc_result_t result
;
1966 * Caller must be holding the manager lock.
1968 if (ns_g_clienttest
) {
1969 result
= isc_mem_create(0, 0, mctxp
);
1970 if (result
== ISC_R_SUCCESS
)
1971 isc_mem_setname(*mctxp
, "client", NULL
);
1975 INSIST(manager
->nextmctx
< NMCTXS
);
1976 clientmctx
= manager
->mctxpool
[manager
->nextmctx
];
1977 if (clientmctx
== NULL
) {
1978 result
= isc_mem_create(0, 0, &clientmctx
);
1979 if (result
!= ISC_R_SUCCESS
)
1981 isc_mem_setname(clientmctx
, "client", NULL
);
1983 manager
->mctxpool
[manager
->nextmctx
] = clientmctx
;
1985 manager
->nextmctx
++;
1986 if (manager
->nextmctx
== NMCTXS
)
1987 manager
->nextmctx
= 0;
1989 clientmctx
= manager
->mctx
;
1992 isc_mem_attach(clientmctx
, mctxp
);
1994 return (ISC_R_SUCCESS
);
1998 client_create(ns_clientmgr_t
*manager
, ns_client_t
**clientp
) {
1999 ns_client_t
*client
;
2000 isc_result_t result
;
2001 isc_mem_t
*mctx
= NULL
;
2004 * Caller must be holding the manager lock.
2006 * Note: creating a client does not add the client to the
2007 * manager's client list or set the client's manager pointer.
2008 * The caller is responsible for that.
2011 REQUIRE(clientp
!= NULL
&& *clientp
== NULL
);
2013 result
= get_clientmctx(manager
, &mctx
);
2014 if (result
!= ISC_R_SUCCESS
)
2017 client
= isc_mem_get(mctx
, sizeof(*client
));
2018 if (client
== NULL
) {
2019 isc_mem_detach(&mctx
);
2020 return (ISC_R_NOMEMORY
);
2022 client
->mctx
= mctx
;
2024 client
->task
= NULL
;
2025 result
= isc_task_create(manager
->taskmgr
, 0, &client
->task
);
2026 if (result
!= ISC_R_SUCCESS
)
2027 goto cleanup_client
;
2028 isc_task_setname(client
->task
, "client", client
);
2030 client
->timer
= NULL
;
2031 result
= isc_timer_create(manager
->timermgr
, isc_timertype_inactive
,
2032 NULL
, NULL
, client
->task
, client_timeout
,
2033 client
, &client
->timer
);
2034 if (result
!= ISC_R_SUCCESS
)
2036 client
->timerset
= ISC_FALSE
;
2038 client
->message
= NULL
;
2039 result
= dns_message_create(client
->mctx
, DNS_MESSAGE_INTENTPARSE
,
2041 if (result
!= ISC_R_SUCCESS
)
2044 /* XXXRTH Hardwired constants */
2046 client
->sendevent
= (isc_socketevent_t
*)
2047 isc_event_allocate(client
->mctx
, client
,
2048 ISC_SOCKEVENT_SENDDONE
,
2049 client_senddone
, client
,
2050 sizeof(isc_socketevent_t
));
2051 if (client
->sendevent
== NULL
) {
2052 result
= ISC_R_NOMEMORY
;
2053 goto cleanup_message
;
2056 client
->recvbuf
= isc_mem_get(client
->mctx
, RECV_BUFFER_SIZE
);
2057 if (client
->recvbuf
== NULL
) {
2058 result
= ISC_R_NOMEMORY
;
2059 goto cleanup_sendevent
;
2062 client
->recvevent
= (isc_socketevent_t
*)
2063 isc_event_allocate(client
->mctx
, client
,
2064 ISC_SOCKEVENT_RECVDONE
,
2065 client_request
, client
,
2066 sizeof(isc_socketevent_t
));
2067 if (client
->recvevent
== NULL
) {
2068 result
= ISC_R_NOMEMORY
;
2069 goto cleanup_recvbuf
;
2072 client
->magic
= NS_CLIENT_MAGIC
;
2073 client
->manager
= NULL
;
2074 client
->state
= NS_CLIENTSTATE_INACTIVE
;
2075 client
->newstate
= NS_CLIENTSTATE_MAX
;
2076 client
->naccepts
= 0;
2080 client
->nupdates
= 0;
2082 client
->references
= 0;
2083 client
->attributes
= 0;
2084 client
->view
= NULL
;
2085 client
->dispatch
= NULL
;
2086 client
->udpsocket
= NULL
;
2087 client
->tcplistener
= NULL
;
2088 client
->tcpsocket
= NULL
;
2089 client
->tcpmsg_valid
= ISC_FALSE
;
2090 client
->tcpbuf
= NULL
;
2092 client
->udpsize
= 512;
2093 client
->extflags
= 0;
2094 client
->ednsversion
= -1;
2095 client
->next
= NULL
;
2096 client
->shutdown
= NULL
;
2097 client
->shutdown_arg
= NULL
;
2098 dns_name_init(&client
->signername
, NULL
);
2099 client
->mortal
= ISC_FALSE
;
2100 client
->tcpquota
= NULL
;
2101 client
->recursionquota
= NULL
;
2102 client
->interface
= NULL
;
2103 client
->peeraddr_valid
= ISC_FALSE
;
2104 ISC_EVENT_INIT(&client
->ctlevent
, sizeof(client
->ctlevent
), 0, NULL
,
2105 NS_EVENT_CLIENTCONTROL
, client_start
, client
, client
,
2108 * Initialize FORMERR cache to sentinel value that will not match
2109 * any actual FORMERR response.
2111 isc_sockaddr_any(&client
->formerrcache
.addr
);
2112 client
->formerrcache
.time
= 0;
2113 client
->formerrcache
.id
= 0;
2114 ISC_LINK_INIT(client
, link
);
2115 client
->list
= NULL
;
2118 * We call the init routines for the various kinds of client here,
2119 * after we have created an otherwise valid client, because some
2120 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2122 result
= ns_query_init(client
);
2123 if (result
!= ISC_R_SUCCESS
)
2124 goto cleanup_recvevent
;
2126 result
= isc_task_onshutdown(client
->task
, client_shutdown
, client
);
2127 if (result
!= ISC_R_SUCCESS
)
2130 client
->needshutdown
= ns_g_clienttest
;
2136 return (ISC_R_SUCCESS
);
2139 ns_query_free(client
);
2142 isc_event_free((isc_event_t
**)&client
->recvevent
);
2145 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
2148 isc_event_free((isc_event_t
**)&client
->sendevent
);
2153 dns_message_destroy(&client
->message
);
2156 isc_timer_detach(&client
->timer
);
2159 isc_task_detach(&client
->task
);
2162 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
2168 client_read(ns_client_t
*client
) {
2169 isc_result_t result
;
2173 result
= dns_tcpmsg_readmessage(&client
->tcpmsg
, client
->task
,
2174 client_request
, client
);
2175 if (result
!= ISC_R_SUCCESS
)
2179 * Set a timeout to limit the amount of time we will wait
2180 * for a request on this TCP connection.
2182 ns_client_settimeout(client
, 30);
2184 client
->state
= client
->newstate
= NS_CLIENTSTATE_READING
;
2185 INSIST(client
->nreads
== 0);
2186 INSIST(client
->recursionquota
== NULL
);
2191 ns_client_next(client
, result
);
2195 client_newconn(isc_task_t
*task
, isc_event_t
*event
) {
2196 ns_client_t
*client
= event
->ev_arg
;
2197 isc_socket_newconnev_t
*nevent
= (isc_socket_newconnev_t
*)event
;
2198 isc_result_t result
;
2200 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_NEWCONN
);
2201 REQUIRE(NS_CLIENT_VALID(client
));
2202 REQUIRE(client
->task
== task
);
2206 INSIST(client
->state
== NS_CLIENTSTATE_READY
);
2208 INSIST(client
->naccepts
== 1);
2211 LOCK(&client
->interface
->lock
);
2212 INSIST(client
->interface
->ntcpcurrent
> 0);
2213 client
->interface
->ntcpcurrent
--;
2214 UNLOCK(&client
->interface
->lock
);
2217 * We must take ownership of the new socket before the exit
2218 * check to make sure it gets destroyed if we decide to exit.
2220 if (nevent
->result
== ISC_R_SUCCESS
) {
2221 client
->tcpsocket
= nevent
->newsocket
;
2222 isc_socket_setname(client
->tcpsocket
, "client-tcp", NULL
);
2223 client
->state
= NS_CLIENTSTATE_READING
;
2224 INSIST(client
->recursionquota
== NULL
);
2226 (void)isc_socket_getpeername(client
->tcpsocket
,
2228 client
->peeraddr_valid
= ISC_TRUE
;
2229 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2230 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2231 "new TCP connection");
2234 * XXXRTH What should we do? We're trying to accept but
2235 * it didn't work. If we just give up, then TCP
2236 * service may eventually stop.
2238 * For now, we just go idle.
2240 * Going idle is probably the right thing if the
2243 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2244 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2245 "accept failed: %s",
2246 isc_result_totext(nevent
->result
));
2249 if (exit_check(client
))
2252 if (nevent
->result
== ISC_R_SUCCESS
) {
2254 isc_netaddr_t netaddr
;
2256 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2258 if (ns_g_server
->blackholeacl
!= NULL
&&
2259 dns_acl_match(&netaddr
, NULL
,
2260 ns_g_server
->blackholeacl
,
2261 &ns_g_server
->aclenv
,
2262 &match
, NULL
) == ISC_R_SUCCESS
&&
2265 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2266 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2267 "blackholed connection attempt");
2268 client
->newstate
= NS_CLIENTSTATE_READY
;
2269 (void)exit_check(client
);
2273 INSIST(client
->tcpmsg_valid
== ISC_FALSE
);
2274 dns_tcpmsg_init(client
->mctx
, client
->tcpsocket
,
2276 client
->tcpmsg_valid
= ISC_TRUE
;
2279 * Let a new client take our place immediately, before
2280 * we wait for a request packet. If we don't,
2281 * telnetting to port 53 (once per CPU) will
2282 * deny service to legitimate TCP clients.
2284 result
= isc_quota_attach(&ns_g_server
->tcpquota
,
2286 if (result
== ISC_R_SUCCESS
)
2287 result
= ns_client_replace(client
);
2288 if (result
!= ISC_R_SUCCESS
) {
2289 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2290 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
2291 "no more TCP clients: %s",
2292 isc_result_totext(result
));
2295 client_read(client
);
2299 isc_event_free(&event
);
2303 client_accept(ns_client_t
*client
) {
2304 isc_result_t result
;
2308 result
= isc_socket_accept(client
->tcplistener
, client
->task
,
2309 client_newconn
, client
);
2310 if (result
!= ISC_R_SUCCESS
) {
2311 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2312 "isc_socket_accept() failed: %s",
2313 isc_result_totext(result
));
2315 * XXXRTH What should we do? We're trying to accept but
2316 * it didn't work. If we just give up, then TCP
2317 * service may eventually stop.
2319 * For now, we just go idle.
2323 INSIST(client
->naccepts
== 0);
2325 LOCK(&client
->interface
->lock
);
2326 client
->interface
->ntcpcurrent
++;
2327 UNLOCK(&client
->interface
->lock
);
2331 client_udprecv(ns_client_t
*client
) {
2332 isc_result_t result
;
2337 r
.base
= client
->recvbuf
;
2338 r
.length
= RECV_BUFFER_SIZE
;
2339 result
= isc_socket_recv2(client
->udpsocket
, &r
, 1,
2340 client
->task
, client
->recvevent
, 0);
2341 if (result
!= ISC_R_SUCCESS
) {
2342 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2343 "isc_socket_recv2() failed: %s",
2344 isc_result_totext(result
));
2346 * This cannot happen in the current implementation, since
2347 * isc_socket_recv2() cannot fail if flags == 0.
2349 * If this does fail, we just go idle.
2353 INSIST(client
->nrecvs
== 0);
2358 ns_client_attach(ns_client_t
*source
, ns_client_t
**targetp
) {
2359 REQUIRE(NS_CLIENT_VALID(source
));
2360 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
2362 source
->references
++;
2363 ns_client_log(source
, NS_LOGCATEGORY_CLIENT
,
2364 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2365 "ns_client_attach: ref = %d", source
->references
);
2370 ns_client_detach(ns_client_t
**clientp
) {
2371 ns_client_t
*client
= *clientp
;
2373 client
->references
--;
2374 INSIST(client
->references
>= 0);
2376 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2377 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2378 "ns_client_detach: ref = %d", client
->references
);
2379 (void)exit_check(client
);
2383 ns_client_shuttingdown(ns_client_t
*client
) {
2384 return (ISC_TF(client
->newstate
== NS_CLIENTSTATE_FREED
));
2388 ns_client_replace(ns_client_t
*client
) {
2389 isc_result_t result
;
2393 result
= ns_clientmgr_createclients(client
->manager
,
2394 1, client
->interface
,
2395 (TCP_CLIENT(client
) ?
2396 ISC_TRUE
: ISC_FALSE
));
2397 if (result
!= ISC_R_SUCCESS
)
2401 * The responsibility for listening for new requests is hereby
2402 * transferred to the new client. Therefore, the old client
2403 * should refrain from listening for any more requests.
2405 client
->mortal
= ISC_TRUE
;
2407 return (ISC_R_SUCCESS
);
2415 clientmgr_destroy(ns_clientmgr_t
*manager
) {
2420 REQUIRE(ISC_LIST_EMPTY(manager
->active
));
2421 REQUIRE(ISC_LIST_EMPTY(manager
->inactive
));
2422 REQUIRE(ISC_LIST_EMPTY(manager
->recursing
));
2424 MTRACE("clientmgr_destroy");
2427 for (i
= 0; i
< NMCTXS
; i
++) {
2428 if (manager
->mctxpool
[i
] != NULL
)
2429 isc_mem_detach(&manager
->mctxpool
[i
]);
2433 DESTROYLOCK(&manager
->lock
);
2435 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2439 ns_clientmgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
2440 isc_timermgr_t
*timermgr
, ns_clientmgr_t
**managerp
)
2442 ns_clientmgr_t
*manager
;
2443 isc_result_t result
;
2448 manager
= isc_mem_get(mctx
, sizeof(*manager
));
2449 if (manager
== NULL
)
2450 return (ISC_R_NOMEMORY
);
2452 result
= isc_mutex_init(&manager
->lock
);
2453 if (result
!= ISC_R_SUCCESS
)
2454 goto cleanup_manager
;
2456 manager
->mctx
= mctx
;
2457 manager
->taskmgr
= taskmgr
;
2458 manager
->timermgr
= timermgr
;
2459 manager
->exiting
= ISC_FALSE
;
2460 ISC_LIST_INIT(manager
->active
);
2461 ISC_LIST_INIT(manager
->inactive
);
2462 ISC_LIST_INIT(manager
->recursing
);
2464 manager
->nextmctx
= 0;
2465 for (i
= 0; i
< NMCTXS
; i
++)
2466 manager
->mctxpool
[i
] = NULL
; /* will be created on-demand */
2468 manager
->magic
= MANAGER_MAGIC
;
2472 *managerp
= manager
;
2474 return (ISC_R_SUCCESS
);
2477 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2483 ns_clientmgr_destroy(ns_clientmgr_t
**managerp
) {
2484 ns_clientmgr_t
*manager
;
2485 ns_client_t
*client
;
2486 isc_boolean_t need_destroy
= ISC_FALSE
;
2488 REQUIRE(managerp
!= NULL
);
2489 manager
= *managerp
;
2490 REQUIRE(VALID_MANAGER(manager
));
2494 LOCK(&manager
->lock
);
2496 manager
->exiting
= ISC_TRUE
;
2498 for (client
= ISC_LIST_HEAD(manager
->recursing
);
2500 client
= ISC_LIST_NEXT(client
, link
))
2501 isc_task_shutdown(client
->task
);
2503 for (client
= ISC_LIST_HEAD(manager
->active
);
2505 client
= ISC_LIST_NEXT(client
, link
))
2506 isc_task_shutdown(client
->task
);
2508 for (client
= ISC_LIST_HEAD(manager
->inactive
);
2510 client
= ISC_LIST_NEXT(client
, link
))
2511 isc_task_shutdown(client
->task
);
2513 if (ISC_LIST_EMPTY(manager
->active
) &&
2514 ISC_LIST_EMPTY(manager
->inactive
) &&
2515 ISC_LIST_EMPTY(manager
->recursing
))
2516 need_destroy
= ISC_TRUE
;
2518 UNLOCK(&manager
->lock
);
2521 clientmgr_destroy(manager
);
2527 ns_clientmgr_createclients(ns_clientmgr_t
*manager
, unsigned int n
,
2528 ns_interface_t
*ifp
, isc_boolean_t tcp
)
2530 isc_result_t result
= ISC_R_SUCCESS
;
2532 ns_client_t
*client
;
2534 REQUIRE(VALID_MANAGER(manager
));
2537 MTRACE("createclients");
2540 * We MUST lock the manager lock for the entire client creation
2541 * process. If we didn't do this, then a client could get a
2542 * shutdown event and disappear out from under us.
2545 LOCK(&manager
->lock
);
2547 for (i
= 0; i
< n
; i
++) {
2550 * Allocate a client. First try to get a recycled one;
2551 * if that fails, make a new one.
2554 if (!ns_g_clienttest
)
2555 client
= ISC_LIST_HEAD(manager
->inactive
);
2556 if (client
!= NULL
) {
2558 ISC_LIST_UNLINK(manager
->inactive
, client
, link
);
2559 client
->list
= NULL
;
2561 MTRACE("create new");
2562 result
= client_create(manager
, &client
);
2563 if (result
!= ISC_R_SUCCESS
)
2567 ns_interface_attach(ifp
, &client
->interface
);
2568 client
->state
= NS_CLIENTSTATE_READY
;
2569 INSIST(client
->recursionquota
== NULL
);
2572 client
->attributes
|= NS_CLIENTATTR_TCP
;
2573 isc_socket_attach(ifp
->tcpsocket
,
2574 &client
->tcplistener
);
2578 dns_dispatch_attach(ifp
->udpdispatch
,
2580 sock
= dns_dispatch_getsocket(client
->dispatch
);
2581 isc_socket_attach(sock
, &client
->udpsocket
);
2583 client
->manager
= manager
;
2584 ISC_LIST_APPEND(manager
->active
, client
, link
);
2585 client
->list
= &manager
->active
;
2587 INSIST(client
->nctls
== 0);
2589 ev
= &client
->ctlevent
;
2590 isc_task_send(client
->task
, &ev
);
2594 * We managed to create at least one client, so we
2597 result
= ISC_R_SUCCESS
;
2600 UNLOCK(&manager
->lock
);
2606 ns_client_getsockaddr(ns_client_t
*client
) {
2607 return (&client
->peeraddr
);
2611 ns_client_checkaclsilent(ns_client_t
*client
, isc_netaddr_t
*netaddr
,
2612 dns_acl_t
*acl
, isc_boolean_t default_allow
)
2614 isc_result_t result
;
2615 isc_netaddr_t tmpnetaddr
;
2625 if (netaddr
== NULL
) {
2626 isc_netaddr_fromsockaddr(&tmpnetaddr
, &client
->peeraddr
);
2627 netaddr
= &tmpnetaddr
;
2630 result
= dns_acl_match(netaddr
, client
->signer
, acl
,
2631 &ns_g_server
->aclenv
, &match
, NULL
);
2633 if (result
!= ISC_R_SUCCESS
)
2634 goto deny
; /* Internal error, already logged. */
2637 goto deny
; /* Negative match or no match. */
2640 return (ISC_R_SUCCESS
);
2643 return (DNS_R_REFUSED
);
2647 ns_client_checkacl(ns_client_t
*client
, isc_sockaddr_t
*sockaddr
,
2648 const char *opname
, dns_acl_t
*acl
,
2649 isc_boolean_t default_allow
, int log_level
)
2651 isc_result_t result
;
2652 isc_netaddr_t netaddr
;
2654 if (sockaddr
!= NULL
)
2655 isc_netaddr_fromsockaddr(&netaddr
, sockaddr
);
2657 result
= ns_client_checkaclsilent(client
, sockaddr
? &netaddr
: NULL
,
2658 acl
, default_allow
);
2660 if (result
== ISC_R_SUCCESS
)
2661 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2662 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2663 "%s approved", opname
);
2665 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2666 NS_LOGMODULE_CLIENT
,
2667 log_level
, "%s denied", opname
);
2672 ns_client_name(ns_client_t
*client
, char *peerbuf
, size_t len
) {
2673 if (client
->peeraddr_valid
)
2674 isc_sockaddr_format(&client
->peeraddr
, peerbuf
, len
);
2676 snprintf(peerbuf
, len
, "@%p", client
);
2680 ns_client_logv(ns_client_t
*client
, isc_logcategory_t
*category
,
2681 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
2684 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2685 const char *name
= "";
2686 const char *sep
= "";
2688 vsnprintf(msgbuf
, sizeof(msgbuf
), fmt
, ap
);
2689 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
2690 if (client
->view
!= NULL
&& strcmp(client
->view
->name
, "_bind") != 0 &&
2691 strcmp(client
->view
->name
, "_default") != 0) {
2692 name
= client
->view
->name
;
2696 isc_log_write(ns_g_lctx
, category
, module
, level
,
2697 "client %s%s%s: %s", peerbuf
, sep
, name
, msgbuf
);
2701 ns_client_log(ns_client_t
*client
, isc_logcategory_t
*category
,
2702 isc_logmodule_t
*module
, int level
, const char *fmt
, ...)
2706 if (! isc_log_wouldlog(ns_g_lctx
, level
))
2710 ns_client_logv(client
, category
, module
, level
, fmt
, ap
);
2715 ns_client_aclmsg(const char *msg
, dns_name_t
*name
, dns_rdatatype_t type
,
2716 dns_rdataclass_t rdclass
, char *buf
, size_t len
)
2718 char namebuf
[DNS_NAME_FORMATSIZE
];
2719 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
2720 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
2722 dns_name_format(name
, namebuf
, sizeof(namebuf
));
2723 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
2724 dns_rdataclass_format(rdclass
, classbuf
, sizeof(classbuf
));
2725 (void)snprintf(buf
, len
, "%s '%s/%s/%s'", msg
, namebuf
, typebuf
,
2730 ns_client_dumpmessage(ns_client_t
*client
, const char *reason
) {
2731 isc_buffer_t buffer
;
2734 isc_result_t result
;
2737 * Note that these are multiline debug messages. We want a newline
2738 * to appear in the log after each message.
2742 buf
= isc_mem_get(client
->mctx
, len
);
2745 isc_buffer_init(&buffer
, buf
, len
);
2746 result
= dns_message_totext(client
->message
,
2747 &dns_master_style_debug
,
2749 if (result
== ISC_R_NOSPACE
) {
2750 isc_mem_put(client
->mctx
, buf
, len
);
2752 } else if (result
== ISC_R_SUCCESS
)
2753 ns_client_log(client
, NS_LOGCATEGORY_UNMATCHED
,
2754 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
2756 (int)isc_buffer_usedlength(&buffer
),
2758 } while (result
== ISC_R_NOSPACE
);
2761 isc_mem_put(client
->mctx
, buf
, len
);
2765 ns_client_dumprecursing(FILE *f
, ns_clientmgr_t
*manager
) {
2766 ns_client_t
*client
;
2767 char namebuf
[DNS_NAME_FORMATSIZE
];
2768 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2772 REQUIRE(VALID_MANAGER(manager
));
2774 LOCK(&manager
->lock
);
2775 client
= ISC_LIST_HEAD(manager
->recursing
);
2776 while (client
!= NULL
) {
2777 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
2778 if (client
->view
!= NULL
&&
2779 strcmp(client
->view
->name
, "_bind") != 0 &&
2780 strcmp(client
->view
->name
, "_default") != 0) {
2781 name
= client
->view
->name
;
2787 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
2788 fprintf(f
, "; client %s%s%s: '%s' requesttime %d\n",
2789 peerbuf
, sep
, name
, namebuf
, client
->requesttime
);
2790 client
= ISC_LIST_NEXT(client
, link
);
2792 UNLOCK(&manager
->lock
);
2796 ns_client_qnamereplace(ns_client_t
*client
, dns_name_t
*name
) {
2798 if (client
->manager
!= NULL
)
2799 LOCK(&client
->manager
->lock
);
2800 if (client
->query
.restarts
> 0) {
2802 * client->query.qname was dynamically allocated.
2804 dns_message_puttempname(client
->message
,
2805 &client
->query
.qname
);
2807 client
->query
.qname
= name
;
2808 if (client
->manager
!= NULL
)
2809 UNLOCK(&client
->manager
->lock
);