2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: client.c,v 1.176.2.13.4.31.6.1 2007/06/26 04:14:55 marka Exp $ */
22 #include <isc/formatcheck.h>
23 #include <isc/mutex.h>
25 #include <isc/print.h>
26 #include <isc/stdio.h>
27 #include <isc/string.h>
29 #include <isc/timer.h>
33 #include <dns/dispatch.h>
34 #include <dns/events.h>
35 #include <dns/message.h>
36 #include <dns/rcode.h>
37 #include <dns/resolver.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
46 #include <named/interfacemgr.h>
47 #include <named/log.h>
48 #include <named/notify.h>
49 #include <named/server.h>
50 #include <named/update.h>
59 * All client state changes, other than that from idle to listening, occur
60 * as a result of events. This guarantees serialization and avoids the
63 * If a routine is ever created that allows someone other than the client's
64 * task to change the client, then the client will have to be locked.
67 #define NS_CLIENT_TRACE
68 #ifdef NS_CLIENT_TRACE
69 #define CTRACE(m) ns_client_log(client, \
70 NS_LOGCATEGORY_CLIENT, \
71 NS_LOGMODULE_CLIENT, \
74 #define MTRACE(m) isc_log_write(ns_g_lctx, \
75 NS_LOGCATEGORY_GENERAL, \
76 NS_LOGMODULE_CLIENT, \
78 "clientmgr @%p: %s", manager, (m))
80 #define CTRACE(m) ((void)(m))
81 #define MTRACE(m) ((void)(m))
84 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
86 #define TCP_BUFFER_SIZE (65535 + 2)
87 #define SEND_BUFFER_SIZE 4096
88 #define RECV_BUFFER_SIZE 4096
94 isc_taskmgr_t
* taskmgr
;
95 isc_timermgr_t
* timermgr
;
98 isc_boolean_t exiting
;
99 client_list_t active
; /* Active clients */
100 client_list_t recursing
; /* Recursing clients */
101 client_list_t inactive
; /* To be recycled */
104 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
105 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
108 * Client object states. Ordering is significant: higher-numbered
109 * states are generally "more active", meaning that the client can
110 * have more dynamically allocated data, outstanding events, etc.
111 * In the list below, any such properties listed for state N
112 * also apply to any state > N.
114 * To force the client into a less active state, set client->newstate
115 * to that state and call exit_check(). This will cause any
116 * activities defined for higher-numbered states to be aborted.
119 #define NS_CLIENTSTATE_FREED 0
121 * The client object no longer exists.
124 #define NS_CLIENTSTATE_INACTIVE 1
126 * The client object exists and has a task and timer.
127 * Its "query" struct and sendbuf are initialized.
128 * It is on the client manager's list of inactive clients.
129 * It has a message and OPT, both in the reset state.
132 #define NS_CLIENTSTATE_READY 2
134 * The client object is either a TCP or a UDP one, and
135 * it is associated with a network interface. It is on the
136 * client manager's list of active clients.
138 * If it is a TCP client object, it has a TCP listener socket
139 * and an outstanding TCP listen request.
141 * If it is a UDP client object, it has a UDP listener socket
142 * and an outstanding UDP receive request.
145 #define NS_CLIENTSTATE_READING 3
147 * The client object is a TCP client object that has received
148 * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
149 * outstanding TCP read request. This state is not used for
150 * UDP client objects.
153 #define NS_CLIENTSTATE_WORKING 4
155 * The client object has received a request and is working
156 * on it. It has a view, and it may have any of a non-reset OPT,
157 * recursion quota, and an outstanding write request.
160 #define NS_CLIENTSTATE_MAX 9
162 * Sentinel value used to indicate "no state". When client->newstate
163 * has this value, we are not attempting to exit the current state.
164 * Must be greater than any valid state.
168 * Enable ns_client_dropport() by default.
170 #ifndef NS_CLIENT_DROPPORT
171 #define NS_CLIENT_DROPPORT 1
174 static void client_read(ns_client_t
*client
);
175 static void client_accept(ns_client_t
*client
);
176 static void client_udprecv(ns_client_t
*client
);
177 static void clientmgr_destroy(ns_clientmgr_t
*manager
);
178 static isc_boolean_t
exit_check(ns_client_t
*client
);
179 static void ns_client_endrequest(ns_client_t
*client
);
180 static void ns_client_checkactive(ns_client_t
*client
);
181 static void client_start(isc_task_t
*task
, isc_event_t
*event
);
182 static void client_request(isc_task_t
*task
, isc_event_t
*event
);
183 static void ns_client_dumpmessage(ns_client_t
*client
, const char *reason
);
186 ns_client_recursing(ns_client_t
*client
) {
187 REQUIRE(NS_CLIENT_VALID(client
));
189 LOCK(&client
->manager
->lock
);
190 ISC_LIST_UNLINK(*client
->list
, client
, link
);
191 ISC_LIST_APPEND(client
->manager
->recursing
, client
, link
);
192 client
->list
= &client
->manager
->recursing
;
193 UNLOCK(&client
->manager
->lock
);
197 ns_client_killoldestquery(ns_client_t
*client
) {
199 REQUIRE(NS_CLIENT_VALID(client
));
201 LOCK(&client
->manager
->lock
);
202 oldest
= ISC_LIST_HEAD(client
->manager
->recursing
);
203 if (oldest
!= NULL
) {
204 ns_query_cancel(oldest
);
205 ISC_LIST_UNLINK(*oldest
->list
, oldest
, link
);
206 ISC_LIST_APPEND(client
->manager
->active
, oldest
, link
);
207 oldest
->list
= &client
->manager
->active
;
209 UNLOCK(&client
->manager
->lock
);
213 ns_client_settimeout(ns_client_t
*client
, unsigned int seconds
) {
215 isc_interval_t interval
;
217 isc_interval_set(&interval
, seconds
, 0);
218 result
= isc_timer_reset(client
->timer
, isc_timertype_once
, NULL
,
219 &interval
, ISC_FALSE
);
220 client
->timerset
= ISC_TRUE
;
221 if (result
!= ISC_R_SUCCESS
) {
222 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
223 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
224 "setting timeout: %s",
225 isc_result_totext(result
));
226 /* Continue anyway. */
231 * Check for a deactivation or shutdown request and take appropriate
232 * action. Returns ISC_TRUE if either is in progress; in this case
233 * the caller must no longer use the client object as it may have been
237 exit_check(ns_client_t
*client
) {
238 ns_clientmgr_t
*locked_manager
= NULL
;
239 ns_clientmgr_t
*destroy_manager
= NULL
;
241 REQUIRE(NS_CLIENT_VALID(client
));
243 if (client
->state
<= client
->newstate
)
244 return (ISC_FALSE
); /* Business as usual. */
246 INSIST(client
->newstate
< NS_CLIENTSTATE_WORKING
);
249 * We need to detach from the view early when shutting down
250 * the server to break the following vicious circle:
252 * - The resolver will not shut down until the view refcount is zero
253 * - The view refcount does not go to zero until all clients detach
254 * - The client does not detach from the view until references is zero
255 * - references does not go to zero until the resolver has shut down
257 * Keep the view attached until any outstanding updates complete.
259 if (client
->nupdates
== 0 &&
260 client
->newstate
== NS_CLIENTSTATE_FREED
&& client
->view
!= NULL
)
261 dns_view_detach(&client
->view
);
263 if (client
->state
== NS_CLIENTSTATE_WORKING
) {
264 INSIST(client
->newstate
<= NS_CLIENTSTATE_READING
);
266 * Let the update processing complete.
268 if (client
->nupdates
> 0)
271 * We are trying to abort request processing.
273 if (client
->nsends
> 0) {
274 isc_socket_t
*socket
;
275 if (TCP_CLIENT(client
))
276 socket
= client
->tcpsocket
;
278 socket
= client
->udpsocket
;
279 isc_socket_cancel(socket
, client
->task
,
280 ISC_SOCKCANCEL_SEND
);
283 if (! (client
->nsends
== 0 && client
->nrecvs
== 0 &&
284 client
->references
== 0))
287 * Still waiting for I/O cancel completion.
288 * or lingering references.
293 * I/O cancel is complete. Burn down all state
294 * related to the current request. Ensure that
295 * the client is on the active list and not the
298 LOCK(&client
->manager
->lock
);
299 if (client
->list
== &client
->manager
->recursing
) {
300 ISC_LIST_UNLINK(*client
->list
, client
, link
);
301 ISC_LIST_APPEND(client
->manager
->active
, client
, link
);
302 client
->list
= &client
->manager
->active
;
304 UNLOCK(&client
->manager
->lock
);
305 ns_client_endrequest(client
);
307 client
->state
= NS_CLIENTSTATE_READING
;
308 INSIST(client
->recursionquota
== NULL
);
309 if (NS_CLIENTSTATE_READING
== client
->newstate
) {
311 client
->newstate
= NS_CLIENTSTATE_MAX
;
312 return (ISC_TRUE
); /* We're done. */
316 if (client
->state
== NS_CLIENTSTATE_READING
) {
318 * We are trying to abort the current TCP connection,
321 INSIST(client
->recursionquota
== NULL
);
322 INSIST(client
->newstate
<= NS_CLIENTSTATE_READY
);
323 if (client
->nreads
> 0)
324 dns_tcpmsg_cancelread(&client
->tcpmsg
);
325 if (! client
->nreads
== 0) {
326 /* Still waiting for read cancel completion. */
330 if (client
->tcpmsg_valid
) {
331 dns_tcpmsg_invalidate(&client
->tcpmsg
);
332 client
->tcpmsg_valid
= ISC_FALSE
;
334 if (client
->tcpsocket
!= NULL
) {
336 isc_socket_detach(&client
->tcpsocket
);
339 if (client
->tcpquota
!= NULL
)
340 isc_quota_detach(&client
->tcpquota
);
342 if (client
->timerset
) {
343 (void)isc_timer_reset(client
->timer
,
344 isc_timertype_inactive
,
345 NULL
, NULL
, ISC_TRUE
);
346 client
->timerset
= ISC_FALSE
;
349 client
->peeraddr_valid
= ISC_FALSE
;
351 client
->state
= NS_CLIENTSTATE_READY
;
352 INSIST(client
->recursionquota
== NULL
);
355 * Now the client is ready to accept a new TCP connection
356 * or UDP request, but we may have enough clients doing
357 * that already. Check whether this client needs to remain
358 * active and force it to go inactive if not.
360 ns_client_checkactive(client
);
362 if (NS_CLIENTSTATE_READY
== client
->newstate
) {
363 if (TCP_CLIENT(client
)) {
364 client_accept(client
);
366 client_udprecv(client
);
367 client
->newstate
= NS_CLIENTSTATE_MAX
;
372 if (client
->state
== NS_CLIENTSTATE_READY
) {
373 INSIST(client
->newstate
<= NS_CLIENTSTATE_INACTIVE
);
375 * We are trying to enter the inactive state.
377 if (client
->naccepts
> 0)
378 isc_socket_cancel(client
->tcplistener
, client
->task
,
379 ISC_SOCKCANCEL_ACCEPT
);
381 if (! (client
->naccepts
== 0)) {
382 /* Still waiting for accept cancel completion. */
385 /* Accept cancel is complete. */
387 if (client
->nrecvs
> 0)
388 isc_socket_cancel(client
->udpsocket
, client
->task
,
389 ISC_SOCKCANCEL_RECV
);
390 if (! (client
->nrecvs
== 0)) {
391 /* Still waiting for recv cancel completion. */
394 /* Recv cancel is complete. */
396 if (client
->nctls
> 0) {
397 /* Still waiting for control event to be delivered */
401 /* Deactivate the client. */
402 if (client
->interface
)
403 ns_interface_detach(&client
->interface
);
405 INSIST(client
->naccepts
== 0);
406 INSIST(client
->recursionquota
== NULL
);
407 if (client
->tcplistener
!= NULL
)
408 isc_socket_detach(&client
->tcplistener
);
410 if (client
->udpsocket
!= NULL
)
411 isc_socket_detach(&client
->udpsocket
);
413 if (client
->dispatch
!= NULL
)
414 dns_dispatch_detach(&client
->dispatch
);
416 client
->attributes
= 0;
417 client
->mortal
= ISC_FALSE
;
419 LOCK(&client
->manager
->lock
);
421 * Put the client on the inactive list. If we are aiming for
422 * the "freed" state, it will be removed from the inactive
423 * list shortly, and we need to keep the manager locked until
424 * that has been done, lest the manager decide to reactivate
425 * the dying client inbetween.
427 locked_manager
= client
->manager
;
428 ISC_LIST_UNLINK(*client
->list
, client
, link
);
429 ISC_LIST_APPEND(client
->manager
->inactive
, client
, link
);
430 client
->list
= &client
->manager
->inactive
;
431 client
->state
= NS_CLIENTSTATE_INACTIVE
;
432 INSIST(client
->recursionquota
== NULL
);
434 if (client
->state
== client
->newstate
) {
435 client
->newstate
= NS_CLIENTSTATE_MAX
;
440 if (client
->state
== NS_CLIENTSTATE_INACTIVE
) {
441 INSIST(client
->newstate
== NS_CLIENTSTATE_FREED
);
443 * We are trying to free the client.
445 * When "shuttingdown" is true, either the task has received
446 * its shutdown event or no shutdown event has ever been
447 * set up. Thus, we have no outstanding shutdown
448 * event at this point.
450 REQUIRE(client
->state
== NS_CLIENTSTATE_INACTIVE
);
452 INSIST(client
->recursionquota
== NULL
);
454 ns_query_free(client
);
455 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
456 isc_event_free((isc_event_t
**)&client
->sendevent
);
457 isc_event_free((isc_event_t
**)&client
->recvevent
);
458 isc_timer_detach(&client
->timer
);
460 if (client
->tcpbuf
!= NULL
)
461 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
462 if (client
->opt
!= NULL
) {
463 INSIST(dns_rdataset_isassociated(client
->opt
));
464 dns_rdataset_disassociate(client
->opt
);
465 dns_message_puttemprdataset(client
->message
, &client
->opt
);
467 dns_message_destroy(&client
->message
);
468 if (client
->manager
!= NULL
) {
469 ns_clientmgr_t
*manager
= client
->manager
;
470 if (locked_manager
== NULL
) {
471 LOCK(&manager
->lock
);
472 locked_manager
= manager
;
474 ISC_LIST_UNLINK(*client
->list
, client
, link
);
476 if (manager
->exiting
&&
477 ISC_LIST_EMPTY(manager
->active
) &&
478 ISC_LIST_EMPTY(manager
->inactive
) &&
479 ISC_LIST_EMPTY(manager
->recursing
))
480 destroy_manager
= manager
;
483 * Detaching the task must be done after unlinking from
484 * the manager's lists because the manager accesses
487 if (client
->task
!= NULL
)
488 isc_task_detach(&client
->task
);
492 isc_mem_put(client
->mctx
, client
, sizeof(*client
));
498 if (locked_manager
!= NULL
) {
499 UNLOCK(&locked_manager
->lock
);
500 locked_manager
= NULL
;
504 * Only now is it safe to destroy the client manager (if needed),
505 * because we have accessed its lock for the last time.
507 if (destroy_manager
!= NULL
)
508 clientmgr_destroy(destroy_manager
);
514 * The client's task has received the client's control event
515 * as part of the startup process.
518 client_start(isc_task_t
*task
, isc_event_t
*event
) {
519 ns_client_t
*client
= (ns_client_t
*) event
->ev_arg
;
521 INSIST(task
== client
->task
);
525 INSIST(client
->nctls
== 1);
528 if (exit_check(client
))
531 if (TCP_CLIENT(client
)) {
532 client_accept(client
);
534 client_udprecv(client
);
540 * The client's task has received a shutdown event.
543 client_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
546 REQUIRE(event
!= NULL
);
547 REQUIRE(event
->ev_type
== ISC_TASKEVENT_SHUTDOWN
);
548 client
= event
->ev_arg
;
549 REQUIRE(NS_CLIENT_VALID(client
));
550 REQUIRE(task
== client
->task
);
556 isc_event_free(&event
);
558 if (client
->shutdown
!= NULL
) {
559 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_SHUTTINGDOWN
);
560 client
->shutdown
= NULL
;
561 client
->shutdown_arg
= NULL
;
564 client
->newstate
= NS_CLIENTSTATE_FREED
;
565 (void)exit_check(client
);
569 ns_client_endrequest(ns_client_t
*client
) {
570 INSIST(client
->naccepts
== 0);
571 INSIST(client
->nreads
== 0);
572 INSIST(client
->nsends
== 0);
573 INSIST(client
->nrecvs
== 0);
574 INSIST(client
->nupdates
== 0);
575 INSIST(client
->state
== NS_CLIENTSTATE_WORKING
);
577 CTRACE("endrequest");
579 if (client
->next
!= NULL
) {
580 (client
->next
)(client
);
584 if (client
->view
!= NULL
)
585 dns_view_detach(&client
->view
);
586 if (client
->opt
!= NULL
) {
587 INSIST(dns_rdataset_isassociated(client
->opt
));
588 dns_rdataset_disassociate(client
->opt
);
589 dns_message_puttemprdataset(client
->message
, &client
->opt
);
592 client
->udpsize
= 512;
593 client
->extflags
= 0;
594 dns_message_reset(client
->message
, DNS_MESSAGE_INTENTPARSE
);
596 if (client
->recursionquota
!= NULL
)
597 isc_quota_detach(&client
->recursionquota
);
600 * Clear all client attributes that are specific to
601 * the request; that's all except the TCP flag.
603 client
->attributes
&= NS_CLIENTATTR_TCP
;
607 ns_client_checkactive(ns_client_t
*client
) {
608 if (client
->mortal
) {
610 * This client object should normally go inactive
611 * at this point, but if we have fewer active client
612 * objects than desired due to earlier quota exhaustion,
613 * keep it active to make up for the shortage.
615 isc_boolean_t need_another_client
= ISC_FALSE
;
616 if (TCP_CLIENT(client
)) {
617 LOCK(&client
->interface
->lock
);
618 if (client
->interface
->ntcpcurrent
<
619 client
->interface
->ntcptarget
)
620 need_another_client
= ISC_TRUE
;
621 UNLOCK(&client
->interface
->lock
);
624 * The UDP client quota is enforced by making
625 * requests fail rather than by not listening
626 * for new ones. Therefore, there is always a
627 * full set of UDP clients listening.
630 if (! need_another_client
) {
632 * We don't need this client object. Recycle it.
634 if (client
->newstate
>= NS_CLIENTSTATE_INACTIVE
)
635 client
->newstate
= NS_CLIENTSTATE_INACTIVE
;
641 ns_client_next(ns_client_t
*client
, isc_result_t result
) {
644 REQUIRE(NS_CLIENT_VALID(client
));
645 REQUIRE(client
->state
== NS_CLIENTSTATE_WORKING
||
646 client
->state
== NS_CLIENTSTATE_READING
);
650 if (result
!= ISC_R_SUCCESS
)
651 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
652 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
653 "request failed: %s", isc_result_totext(result
));
656 * An error processing a TCP request may have left
657 * the connection out of sync. To be safe, we always
658 * sever the connection when result != ISC_R_SUCCESS.
660 if (result
== ISC_R_SUCCESS
&& TCP_CLIENT(client
))
661 newstate
= NS_CLIENTSTATE_READING
;
663 newstate
= NS_CLIENTSTATE_READY
;
665 if (client
->newstate
> newstate
)
666 client
->newstate
= newstate
;
667 (void)exit_check(client
);
672 client_senddone(isc_task_t
*task
, isc_event_t
*event
) {
674 isc_socketevent_t
*sevent
= (isc_socketevent_t
*) event
;
676 REQUIRE(sevent
!= NULL
);
677 REQUIRE(sevent
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
678 client
= sevent
->ev_arg
;
679 REQUIRE(NS_CLIENT_VALID(client
));
680 REQUIRE(task
== client
->task
);
681 REQUIRE(sevent
== client
->sendevent
);
687 if (sevent
->result
!= ISC_R_SUCCESS
)
688 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
689 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
690 "error sending response: %s",
691 isc_result_totext(sevent
->result
));
693 INSIST(client
->nsends
> 0);
696 if (client
->tcpbuf
!= NULL
) {
697 INSIST(TCP_CLIENT(client
));
698 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
699 client
->tcpbuf
= NULL
;
702 if (exit_check(client
))
705 ns_client_next(client
, ISC_R_SUCCESS
);
709 * We only want to fail with ISC_R_NOSPACE when called from
710 * ns_client_sendraw() and not when called from ns_client_send(),
711 * tcpbuffer is NULL when called from ns_client_sendraw() and
712 * length != 0. tcpbuffer != NULL when called from ns_client_send()
717 client_allocsendbuf(ns_client_t
*client
, isc_buffer_t
*buffer
,
718 isc_buffer_t
*tcpbuffer
, isc_uint32_t length
,
719 unsigned char *sendbuf
, unsigned char **datap
)
722 isc_uint32_t bufsize
;
725 INSIST(datap
!= NULL
);
726 INSIST((tcpbuffer
== NULL
&& length
!= 0) ||
727 (tcpbuffer
!= NULL
&& length
== 0));
729 if (TCP_CLIENT(client
)) {
730 INSIST(client
->tcpbuf
== NULL
);
731 if (length
+ 2 > TCP_BUFFER_SIZE
) {
732 result
= ISC_R_NOSPACE
;
735 client
->tcpbuf
= isc_mem_get(client
->mctx
, TCP_BUFFER_SIZE
);
736 if (client
->tcpbuf
== NULL
) {
737 result
= ISC_R_NOMEMORY
;
740 data
= client
->tcpbuf
;
741 if (tcpbuffer
!= NULL
) {
742 isc_buffer_init(tcpbuffer
, data
, TCP_BUFFER_SIZE
);
743 isc_buffer_init(buffer
, data
+ 2, TCP_BUFFER_SIZE
- 2);
745 isc_buffer_init(buffer
, data
, TCP_BUFFER_SIZE
);
746 INSIST(length
<= 0xffff);
747 isc_buffer_putuint16(buffer
, (isc_uint16_t
)length
);
751 if (client
->udpsize
< SEND_BUFFER_SIZE
)
752 bufsize
= client
->udpsize
;
754 bufsize
= SEND_BUFFER_SIZE
;
755 if (length
> bufsize
) {
756 result
= ISC_R_NOSPACE
;
759 isc_buffer_init(buffer
, data
, bufsize
);
762 result
= ISC_R_SUCCESS
;
769 client_sendpkg(ns_client_t
*client
, isc_buffer_t
*buffer
) {
770 struct in6_pktinfo
*pktinfo
;
773 isc_sockaddr_t
*address
;
774 isc_socket_t
*socket
;
775 isc_netaddr_t netaddr
;
777 unsigned int sockflags
= ISC_SOCKFLAG_IMMEDIATE
;
779 if (TCP_CLIENT(client
)) {
780 socket
= client
->tcpsocket
;
783 socket
= client
->udpsocket
;
784 address
= &client
->peeraddr
;
786 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
787 if (ns_g_server
->blackholeacl
!= NULL
&&
788 dns_acl_match(&netaddr
, NULL
,
789 ns_g_server
->blackholeacl
,
790 &ns_g_server
->aclenv
,
791 &match
, NULL
) == ISC_R_SUCCESS
&&
793 return (DNS_R_BLACKHOLED
);
794 sockflags
|= ISC_SOCKFLAG_NORETRY
;
797 if ((client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0 &&
798 (client
->attributes
& NS_CLIENTATTR_MULTICAST
) == 0)
799 pktinfo
= &client
->pktinfo
;
803 isc_buffer_usedregion(buffer
, &r
);
807 result
= isc_socket_sendto2(socket
, &r
, client
->task
,
809 client
->sendevent
, sockflags
);
810 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_INPROGRESS
) {
812 if (result
== ISC_R_SUCCESS
)
813 client_senddone(client
->task
,
814 (isc_event_t
*)client
->sendevent
);
815 result
= ISC_R_SUCCESS
;
821 ns_client_sendraw(ns_client_t
*client
, dns_message_t
*message
) {
827 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
829 REQUIRE(NS_CLIENT_VALID(client
));
833 mr
= dns_message_getrawmessage(message
);
835 result
= ISC_R_UNEXPECTEDEND
;
839 result
= client_allocsendbuf(client
, &buffer
, NULL
, mr
->length
,
841 if (result
!= ISC_R_SUCCESS
)
845 * Copy message to buffer and fixup id.
847 isc_buffer_availableregion(&buffer
, &r
);
848 result
= isc_buffer_copyregion(&buffer
, mr
);
849 if (result
!= ISC_R_SUCCESS
)
851 r
.base
[0] = (client
->message
->id
>> 8) & 0xff;
852 r
.base
[1] = client
->message
->id
& 0xff;
854 result
= client_sendpkg(client
, &buffer
);
855 if (result
== ISC_R_SUCCESS
)
859 if (client
->tcpbuf
!= NULL
) {
860 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
861 client
->tcpbuf
= NULL
;
863 ns_client_next(client
, result
);
867 ns_client_send(ns_client_t
*client
) {
871 isc_buffer_t tcpbuffer
;
874 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
875 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
876 unsigned int dnssec_opts
;
877 unsigned int preferred_glue
;
879 REQUIRE(NS_CLIENT_VALID(client
));
883 if ((client
->attributes
& NS_CLIENTATTR_RA
) != 0)
884 client
->message
->flags
|= DNS_MESSAGEFLAG_RA
;
886 if ((client
->attributes
& NS_CLIENTATTR_WANTDNSSEC
) != 0)
889 dnssec_opts
= DNS_MESSAGERENDER_OMITDNSSEC
;
892 if (client
->view
!= NULL
) {
893 if (client
->view
->preferred_glue
== dns_rdatatype_a
)
894 preferred_glue
= DNS_MESSAGERENDER_PREFER_A
;
895 else if (client
->view
->preferred_glue
== dns_rdatatype_aaaa
)
896 preferred_glue
= DNS_MESSAGERENDER_PREFER_AAAA
;
900 * XXXRTH The following doesn't deal with TCP buffer resizing.
902 result
= client_allocsendbuf(client
, &buffer
, &tcpbuffer
, 0,
904 if (result
!= ISC_R_SUCCESS
)
907 result
= dns_compress_init(&cctx
, -1, client
->mctx
);
908 if (result
!= ISC_R_SUCCESS
)
910 cleanup_cctx
= ISC_TRUE
;
912 result
= dns_message_renderbegin(client
->message
, &cctx
, &buffer
);
913 if (result
!= ISC_R_SUCCESS
)
915 if (client
->opt
!= NULL
) {
916 result
= dns_message_setopt(client
->message
, client
->opt
);
918 * XXXRTH dns_message_setopt() should probably do this...
921 if (result
!= ISC_R_SUCCESS
)
924 result
= dns_message_rendersection(client
->message
,
925 DNS_SECTION_QUESTION
, 0);
926 if (result
== ISC_R_NOSPACE
) {
927 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
930 if (result
!= ISC_R_SUCCESS
)
932 result
= dns_message_rendersection(client
->message
,
934 DNS_MESSAGERENDER_PARTIAL
|
936 if (result
== ISC_R_NOSPACE
) {
937 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
940 if (result
!= ISC_R_SUCCESS
)
942 result
= dns_message_rendersection(client
->message
,
943 DNS_SECTION_AUTHORITY
,
944 DNS_MESSAGERENDER_PARTIAL
|
946 if (result
== ISC_R_NOSPACE
) {
947 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
950 if (result
!= ISC_R_SUCCESS
)
952 result
= dns_message_rendersection(client
->message
,
953 DNS_SECTION_ADDITIONAL
,
954 preferred_glue
| dnssec_opts
);
955 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
958 result
= dns_message_renderend(client
->message
);
960 if (result
!= ISC_R_SUCCESS
)
964 dns_compress_invalidate(&cctx
);
965 cleanup_cctx
= ISC_FALSE
;
968 if (TCP_CLIENT(client
)) {
969 isc_buffer_usedregion(&buffer
, &r
);
970 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
) r
.length
);
971 isc_buffer_add(&tcpbuffer
, r
.length
);
972 result
= client_sendpkg(client
, &tcpbuffer
);
974 result
= client_sendpkg(client
, &buffer
);
975 if (result
== ISC_R_SUCCESS
)
979 if (client
->tcpbuf
!= NULL
) {
980 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
981 client
->tcpbuf
= NULL
;
985 dns_compress_invalidate(&cctx
);
987 ns_client_next(client
, result
);
990 #if NS_CLIENT_DROPPORT
991 #define DROPPORT_NO 0
992 #define DROPPORT_REQUEST 1
993 #define DROPPORT_RESPONSE 2
995 * ns_client_dropport determines if certain requests / responses
996 * should be dropped based on the port number.
1000 * \li 1: Drop request.
1001 * \li 2: Drop (error) response.
1004 ns_client_dropport(in_port_t port
) {
1007 case 13: /* daytime */
1008 case 19: /* chargen */
1010 return (DROPPORT_REQUEST
);
1011 case 464: /* kpasswd */
1012 return (DROPPORT_RESPONSE
);
1014 return (DROPPORT_NO
);
1019 ns_client_error(ns_client_t
*client
, isc_result_t result
) {
1021 dns_message_t
*message
;
1023 REQUIRE(NS_CLIENT_VALID(client
));
1027 message
= client
->message
;
1028 rcode
= dns_result_torcode(result
);
1030 #if NS_CLIENT_DROPPORT
1032 * Don't send FORMERR to ports on the drop port list.
1034 if (rcode
== dns_rcode_formerr
&&
1035 ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) !=
1040 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
1041 if (dns_rcode_totext(rcode
, &b
) != ISC_R_SUCCESS
)
1042 isc_buffer_putstr(&b
, "UNKNOWN RCODE");
1043 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1044 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1045 "dropped error (%.*s) response: suspicious port",
1046 (int)isc_buffer_usedlength(&b
), buf
);
1047 ns_client_next(client
, ISC_R_SUCCESS
);
1053 * Message may be an in-progress reply that we had trouble
1054 * with, in which case QR will be set. We need to clear QR before
1055 * calling dns_message_reply() to avoid triggering an assertion.
1057 message
->flags
&= ~DNS_MESSAGEFLAG_QR
;
1059 * AA and AD shouldn't be set.
1061 message
->flags
&= ~(DNS_MESSAGEFLAG_AA
| DNS_MESSAGEFLAG_AD
);
1062 result
= dns_message_reply(message
, ISC_TRUE
);
1063 if (result
!= ISC_R_SUCCESS
) {
1065 * It could be that we've got a query with a good header,
1066 * but a bad question section, so we try again with
1067 * want_question_section set to ISC_FALSE.
1069 result
= dns_message_reply(message
, ISC_FALSE
);
1070 if (result
!= ISC_R_SUCCESS
) {
1071 ns_client_next(client
, result
);
1075 message
->rcode
= rcode
;
1078 * FORMERR loop avoidance: If we sent a FORMERR message
1079 * with the same ID to the same client less than two
1080 * seconds ago, assume that we are in an infinite error
1081 * packet dialog with a server for some protocol whose
1082 * error responses look enough like DNS queries to
1083 * elicit a FORMERR response. Drop a packet to break
1086 if (rcode
== dns_rcode_formerr
) {
1087 if (isc_sockaddr_equal(&client
->peeraddr
,
1088 &client
->formerrcache
.addr
) &&
1089 message
->id
== client
->formerrcache
.id
&&
1090 client
->requesttime
- client
->formerrcache
.time
< 2) {
1092 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1093 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1094 "possible error packet loop, "
1096 ns_client_next(client
, result
);
1099 client
->formerrcache
.addr
= client
->peeraddr
;
1100 client
->formerrcache
.time
= client
->requesttime
;
1101 client
->formerrcache
.id
= message
->id
;
1103 ns_client_send(client
);
1106 static inline isc_result_t
1107 client_addopt(ns_client_t
*client
) {
1108 dns_rdataset_t
*rdataset
;
1109 dns_rdatalist_t
*rdatalist
;
1111 isc_result_t result
;
1113 dns_resolver_t
*resolver
;
1114 isc_uint16_t udpsize
;
1116 REQUIRE(client
->opt
== NULL
); /* XXXRTH free old. */
1119 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
1120 if (result
!= ISC_R_SUCCESS
)
1123 result
= dns_message_gettemprdata(client
->message
, &rdata
);
1124 if (result
!= ISC_R_SUCCESS
)
1127 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
1128 if (result
!= ISC_R_SUCCESS
)
1130 dns_rdataset_init(rdataset
);
1132 rdatalist
->type
= dns_rdatatype_opt
;
1133 rdatalist
->covers
= 0;
1136 * Set the maximum UDP buffer size.
1138 view
= client
->view
;
1139 resolver
= (view
!= NULL
) ? view
->resolver
: NULL
;
1140 if (resolver
!= NULL
)
1141 udpsize
= dns_resolver_getudpsize(resolver
);
1143 udpsize
= ns_g_udpsize
;
1144 rdatalist
->rdclass
= udpsize
;
1147 * Set EXTENDED-RCODE, VERSION and Z to 0.
1149 rdatalist
->ttl
= (client
->extflags
& DNS_MESSAGEEXTFLAG_REPLYPRESERVE
);
1152 * No ENDS options in the default case.
1156 rdata
->rdclass
= rdatalist
->rdclass
;
1157 rdata
->type
= rdatalist
->type
;
1160 ISC_LIST_INIT(rdatalist
->rdata
);
1161 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1162 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
)
1165 client
->opt
= rdataset
;
1167 return (ISC_R_SUCCESS
);
1170 static inline isc_boolean_t
1171 allowed(isc_netaddr_t
*addr
, dns_name_t
*signer
, dns_acl_t
*acl
) {
1173 isc_result_t result
;
1177 result
= dns_acl_match(addr
, signer
, acl
, &ns_g_server
->aclenv
,
1179 if (result
== ISC_R_SUCCESS
&& match
> 0)
1185 * Handle an incoming request event from the socket (UDP case)
1186 * or tcpmsg (TCP case).
1189 client_request(isc_task_t
*task
, isc_event_t
*event
) {
1190 ns_client_t
*client
;
1191 isc_socketevent_t
*sevent
;
1192 isc_result_t result
;
1193 isc_result_t sigresult
= ISC_R_SUCCESS
;
1194 isc_buffer_t
*buffer
;
1195 isc_buffer_t tbuffer
;
1197 dns_rdataset_t
*opt
;
1198 isc_boolean_t ra
; /* Recursion available. */
1199 isc_netaddr_t netaddr
;
1200 isc_netaddr_t destaddr
;
1204 isc_boolean_t notimp
;
1206 REQUIRE(event
!= NULL
);
1207 client
= event
->ev_arg
;
1208 REQUIRE(NS_CLIENT_VALID(client
));
1209 REQUIRE(task
== client
->task
);
1211 INSIST(client
->recursionquota
== NULL
);
1213 INSIST(client
->state
==
1214 TCP_CLIENT(client
) ?
1215 NS_CLIENTSTATE_READING
:
1216 NS_CLIENTSTATE_READY
);
1218 if (event
->ev_type
== ISC_SOCKEVENT_RECVDONE
) {
1219 INSIST(!TCP_CLIENT(client
));
1220 sevent
= (isc_socketevent_t
*)event
;
1221 REQUIRE(sevent
== client
->recvevent
);
1222 isc_buffer_init(&tbuffer
, sevent
->region
.base
, sevent
->n
);
1223 isc_buffer_add(&tbuffer
, sevent
->n
);
1225 result
= sevent
->result
;
1226 if (result
== ISC_R_SUCCESS
) {
1227 client
->peeraddr
= sevent
->address
;
1228 client
->peeraddr_valid
= ISC_TRUE
;
1230 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_PKTINFO
) != 0) {
1231 client
->attributes
|= NS_CLIENTATTR_PKTINFO
;
1232 client
->pktinfo
= sevent
->pktinfo
;
1234 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_MULTICAST
) != 0)
1235 client
->attributes
|= NS_CLIENTATTR_MULTICAST
;
1238 INSIST(TCP_CLIENT(client
));
1239 REQUIRE(event
->ev_type
== DNS_EVENT_TCPMSG
);
1240 REQUIRE(event
->ev_sender
== &client
->tcpmsg
);
1241 buffer
= &client
->tcpmsg
.buffer
;
1242 result
= client
->tcpmsg
.result
;
1243 INSIST(client
->nreads
== 1);
1245 * client->peeraddr was set when the connection was accepted.
1250 if (exit_check(client
))
1252 client
->state
= client
->newstate
= NS_CLIENTSTATE_WORKING
;
1254 isc_task_getcurrenttime(task
, &client
->requesttime
);
1255 client
->now
= client
->requesttime
;
1257 if (result
!= ISC_R_SUCCESS
) {
1258 if (TCP_CLIENT(client
)) {
1259 ns_client_next(client
, result
);
1261 if (result
!= ISC_R_CANCELED
)
1262 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_CLIENT
,
1263 NS_LOGMODULE_CLIENT
,
1265 "UDP client handler shutting "
1266 "down due to fatal receive "
1268 isc_result_totext(result
));
1269 isc_task_shutdown(client
->task
);
1274 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1276 #if NS_CLIENT_DROPPORT
1277 if (ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) ==
1279 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1280 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1281 "dropped request: suspicious port");
1282 ns_client_next(client
, ISC_R_SUCCESS
);
1287 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1288 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1290 TCP_CLIENT(client
) ? "TCP" : "UDP");
1293 * Check the blackhole ACL for UDP only, since TCP is done in
1296 if (!TCP_CLIENT(client
)) {
1298 if (ns_g_server
->blackholeacl
!= NULL
&&
1299 dns_acl_match(&netaddr
, NULL
, ns_g_server
->blackholeacl
,
1300 &ns_g_server
->aclenv
,
1301 &match
, NULL
) == ISC_R_SUCCESS
&&
1304 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1305 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1306 "blackholed UDP datagram");
1307 ns_client_next(client
, ISC_R_SUCCESS
);
1313 * Silently drop multicast requests for the present.
1314 * XXXMPA look at when/if mDNS spec stabilizes.
1316 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0) {
1317 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1318 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(2),
1319 "dropping multicast request");
1320 ns_client_next(client
, DNS_R_REFUSED
);
1324 result
= dns_message_peekheader(buffer
, &id
, &flags
);
1325 if (result
!= ISC_R_SUCCESS
) {
1327 * There isn't enough header to determine whether
1328 * this was a request or a response. Drop it.
1330 ns_client_next(client
, result
);
1335 * The client object handles requests, not responses.
1336 * If this is a UDP response, forward it to the dispatcher.
1337 * If it's a TCP response, discard it here.
1339 if ((flags
& DNS_MESSAGEFLAG_QR
) != 0) {
1340 if (TCP_CLIENT(client
)) {
1341 CTRACE("unexpected response");
1342 ns_client_next(client
, DNS_R_FORMERR
);
1345 dns_dispatch_importrecv(client
->dispatch
, event
);
1346 ns_client_next(client
, ISC_R_SUCCESS
);
1352 * It's a request. Parse it.
1354 result
= dns_message_parse(client
->message
, buffer
, 0);
1355 if (result
!= ISC_R_SUCCESS
) {
1357 * Parsing the request failed. Send a response
1358 * (typically FORMERR or SERVFAIL).
1360 ns_client_error(client
, result
);
1364 switch (client
->message
->opcode
) {
1365 case dns_opcode_query
:
1366 case dns_opcode_update
:
1367 case dns_opcode_notify
:
1370 case dns_opcode_iquery
:
1376 client
->message
->rcode
= dns_rcode_noerror
;
1378 /* RFC1123 section 6.1.3.2 */
1379 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0)
1380 client
->message
->flags
&= ~DNS_MESSAGEFLAG_RD
;
1385 opt
= dns_message_getopt(client
->message
);
1387 unsigned int version
;
1390 * Set the client's UDP buffer size.
1392 client
->udpsize
= opt
->rdclass
;
1395 * If the requested UDP buffer size is less than 512,
1396 * ignore it and use 512.
1398 if (client
->udpsize
< 512)
1399 client
->udpsize
= 512;
1402 * Get the flags out of the OPT record.
1404 client
->extflags
= (isc_uint16_t
)(opt
->ttl
& 0xFFFF);
1407 * Create an OPT for our reply.
1409 result
= client_addopt(client
);
1410 if (result
!= ISC_R_SUCCESS
) {
1411 ns_client_error(client
, result
);
1416 * Do we understand this version of ENDS?
1418 * XXXRTH need library support for this!
1420 version
= (opt
->ttl
& 0x00FF0000) >> 16;
1422 ns_client_error(client
, DNS_R_BADVERS
);
1427 if (client
->message
->rdclass
== 0) {
1428 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1429 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1430 "message class could not be determined");
1431 ns_client_dumpmessage(client
,
1432 "message class could not be determined");
1433 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_FORMERR
);
1438 * Determine the destination address. If the receiving interface is
1439 * bound to a specific address, we simply use it regardless of the
1440 * address family. All IPv4 queries should fall into this case.
1441 * Otherwise, if this is a TCP query, get the address from the
1442 * receiving socket (this needs a system call and can be heavy).
1443 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1445 * If all the attempts fail (this can happen due to memory shortage,
1446 * etc), we regard this as an error for safety.
1448 if ((client
->interface
->flags
& NS_INTERFACEFLAG_ANYADDR
) == 0)
1449 isc_netaddr_fromsockaddr(&destaddr
, &client
->interface
->addr
);
1451 result
= ISC_R_FAILURE
;
1453 if (TCP_CLIENT(client
)) {
1454 isc_sockaddr_t destsockaddr
;
1456 result
= isc_socket_getsockname(client
->tcpsocket
,
1458 if (result
== ISC_R_SUCCESS
)
1459 isc_netaddr_fromsockaddr(&destaddr
,
1462 if (result
!= ISC_R_SUCCESS
&&
1463 client
->interface
->addr
.type
.sa
.sa_family
== AF_INET6
&&
1464 (client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0) {
1465 isc_uint32_t zone
= 0;
1468 * XXXJT technically, we should convert the receiving
1469 * interface ID to a proper scope zone ID. However,
1470 * due to the fact there is no standard API for this,
1471 * we only handle link-local addresses and use the
1472 * interface index as link ID. Despite the assumption,
1473 * it should cover most typical cases.
1475 if (IN6_IS_ADDR_LINKLOCAL(&client
->pktinfo
.ipi6_addr
))
1476 zone
= (isc_uint32_t
)client
->pktinfo
.ipi6_ifindex
;
1478 isc_netaddr_fromin6(&destaddr
,
1479 &client
->pktinfo
.ipi6_addr
);
1480 isc_netaddr_setzone(&destaddr
, zone
);
1481 result
= ISC_R_SUCCESS
;
1483 if (result
!= ISC_R_SUCCESS
) {
1484 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1485 "failed to get request's "
1487 isc_result_totext(result
));
1493 * Find a view that matches the client's source address.
1495 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1497 view
= ISC_LIST_NEXT(view
, link
)) {
1498 if (client
->message
->rdclass
== view
->rdclass
||
1499 client
->message
->rdclass
== dns_rdataclass_any
)
1501 dns_name_t
*tsig
= NULL
;
1502 sigresult
= dns_message_rechecksig(client
->message
,
1504 if (sigresult
== ISC_R_SUCCESS
)
1505 tsig
= client
->message
->tsigname
;
1507 if (allowed(&netaddr
, tsig
, view
->matchclients
) &&
1508 allowed(&destaddr
, tsig
, view
->matchdestinations
) &&
1509 !((client
->message
->flags
& DNS_MESSAGEFLAG_RD
)
1510 == 0 && view
->matchrecursiveonly
))
1512 dns_view_attach(view
, &client
->view
);
1519 char classname
[DNS_RDATACLASS_FORMATSIZE
];
1522 * Do a dummy TSIG verification attempt so that the
1523 * response will have a TSIG if the query did, as
1524 * required by RFC2845.
1529 dns_message_resetsig(client
->message
);
1531 r
= dns_message_getrawmessage(client
->message
);
1532 isc_buffer_init(&b
, r
->base
, r
->length
);
1533 isc_buffer_add(&b
, r
->length
);
1534 (void)dns_tsig_verify(&b
, client
->message
, NULL
, NULL
);
1536 dns_rdataclass_format(client
->message
->rdclass
, classname
,
1538 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1539 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1540 "no matching view in class '%s'", classname
);
1541 ns_client_dumpmessage(client
, "no matching view in class");
1542 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_REFUSED
);
1546 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1547 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(5),
1548 "using view '%s'", view
->name
);
1551 * Check for a signature. We log bad signatures regardless of
1552 * whether they ultimately cause the request to be rejected or
1553 * not. We do not log the lack of a signature unless we are
1556 client
->signer
= NULL
;
1557 dns_name_init(&client
->signername
, NULL
);
1558 result
= dns_message_signer(client
->message
, &client
->signername
);
1559 if (result
== ISC_R_SUCCESS
) {
1560 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1561 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1562 "request has valid signature");
1563 client
->signer
= &client
->signername
;
1564 } else if (result
== ISC_R_NOTFOUND
) {
1565 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1566 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1567 "request is not signed");
1568 } else if (result
== DNS_R_NOIDENTITY
) {
1569 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1570 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1571 "request is signed by a nonauthoritative key");
1575 dns_name_t
*name
= NULL
;
1577 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
1578 RUNTIME_CHECK(dns_tsigrcode_totext(client
->message
->tsigstatus
,
1579 &b
) == ISC_R_SUCCESS
);
1580 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
1581 /* There is a signature, but it is bad. */
1582 if (dns_message_gettsig(client
->message
, &name
) != NULL
) {
1583 char namebuf
[DNS_NAME_FORMATSIZE
];
1584 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1585 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1586 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
1587 "request has invalid signature: "
1588 "TSIG %s: %s (%s)", namebuf
,
1589 isc_result_totext(result
), tsigrcode
);
1591 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1592 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
1593 "request has invalid signature: %s (%s)",
1594 isc_result_totext(result
), tsigrcode
);
1597 * Accept update messages signed by unknown keys so that
1598 * update forwarding works transparently through slaves
1599 * that don't have all the same keys as the master.
1601 if (!(client
->message
->tsigstatus
== dns_tsigerror_badkey
&&
1602 client
->message
->opcode
== dns_opcode_update
)) {
1603 ns_client_error(client
, sigresult
);
1609 * Decide whether recursive service is available to this client.
1610 * We do this here rather than in the query code so that we can
1611 * set the RA bit correctly on all kinds of responses, not just
1612 * responses to ordinary queries. Note if you can't query the
1613 * cache there is no point in setting RA.
1616 if (client
->view
->resolver
!= NULL
&&
1617 client
->view
->recursion
== ISC_TRUE
&&
1618 ns_client_checkaclsilent(client
, client
->view
->recursionacl
,
1619 ISC_TRUE
) == ISC_R_SUCCESS
&&
1620 ns_client_checkaclsilent(client
, client
->view
->queryacl
,
1621 ISC_TRUE
) == ISC_R_SUCCESS
)
1625 client
->attributes
|= NS_CLIENTATTR_RA
;
1627 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
, NS_LOGMODULE_CLIENT
,
1628 ISC_LOG_DEBUG(3), ra
? "recursion available" :
1629 "recursion not available");
1632 * Dispatch the request.
1634 switch (client
->message
->opcode
) {
1635 case dns_opcode_query
:
1637 ns_query_start(client
);
1639 case dns_opcode_update
:
1641 ns_client_settimeout(client
, 60);
1642 ns_update_start(client
, sigresult
);
1644 case dns_opcode_notify
:
1646 ns_client_settimeout(client
, 60);
1647 ns_notify_start(client
);
1649 case dns_opcode_iquery
:
1651 ns_client_error(client
, DNS_R_NOTIMP
);
1654 CTRACE("unknown opcode");
1655 ns_client_error(client
, DNS_R_NOTIMP
);
1663 client_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1664 ns_client_t
*client
;
1666 REQUIRE(event
!= NULL
);
1667 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_LIFE
||
1668 event
->ev_type
== ISC_TIMEREVENT_IDLE
);
1669 client
= event
->ev_arg
;
1670 REQUIRE(NS_CLIENT_VALID(client
));
1671 REQUIRE(task
== client
->task
);
1672 REQUIRE(client
->timer
!= NULL
);
1678 isc_event_free(&event
);
1680 if (client
->shutdown
!= NULL
) {
1681 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_TIMEDOUT
);
1682 client
->shutdown
= NULL
;
1683 client
->shutdown_arg
= NULL
;
1686 if (client
->newstate
> NS_CLIENTSTATE_READY
)
1687 client
->newstate
= NS_CLIENTSTATE_READY
;
1688 (void)exit_check(client
);
1692 client_create(ns_clientmgr_t
*manager
, ns_client_t
**clientp
) {
1693 ns_client_t
*client
;
1694 isc_result_t result
;
1697 * Caller must be holding the manager lock.
1699 * Note: creating a client does not add the client to the
1700 * manager's client list or set the client's manager pointer.
1701 * The caller is responsible for that.
1704 REQUIRE(clientp
!= NULL
&& *clientp
== NULL
);
1706 client
= isc_mem_get(manager
->mctx
, sizeof(*client
));
1708 return (ISC_R_NOMEMORY
);
1710 client
->task
= NULL
;
1711 result
= isc_task_create(manager
->taskmgr
, 0, &client
->task
);
1712 if (result
!= ISC_R_SUCCESS
)
1713 goto cleanup_client
;
1714 isc_task_setname(client
->task
, "client", client
);
1716 client
->timer
= NULL
;
1717 result
= isc_timer_create(manager
->timermgr
, isc_timertype_inactive
,
1718 NULL
, NULL
, client
->task
, client_timeout
,
1719 client
, &client
->timer
);
1720 if (result
!= ISC_R_SUCCESS
)
1722 client
->timerset
= ISC_FALSE
;
1724 client
->message
= NULL
;
1725 result
= dns_message_create(manager
->mctx
, DNS_MESSAGE_INTENTPARSE
,
1727 if (result
!= ISC_R_SUCCESS
)
1730 /* XXXRTH Hardwired constants */
1732 client
->sendevent
= (isc_socketevent_t
*)
1733 isc_event_allocate(manager
->mctx
, client
,
1734 ISC_SOCKEVENT_SENDDONE
,
1735 client_senddone
, client
,
1736 sizeof(isc_socketevent_t
));
1737 if (client
->sendevent
== NULL
) {
1738 result
= ISC_R_NOMEMORY
;
1739 goto cleanup_message
;
1742 client
->recvbuf
= isc_mem_get(manager
->mctx
, RECV_BUFFER_SIZE
);
1743 if (client
->recvbuf
== NULL
) {
1744 result
= ISC_R_NOMEMORY
;
1745 goto cleanup_sendevent
;
1748 client
->recvevent
= (isc_socketevent_t
*)
1749 isc_event_allocate(manager
->mctx
, client
,
1750 ISC_SOCKEVENT_RECVDONE
,
1751 client_request
, client
,
1752 sizeof(isc_socketevent_t
));
1753 if (client
->recvevent
== NULL
) {
1754 result
= ISC_R_NOMEMORY
;
1755 goto cleanup_recvbuf
;
1758 client
->magic
= NS_CLIENT_MAGIC
;
1759 client
->mctx
= manager
->mctx
;
1760 client
->manager
= NULL
;
1761 client
->state
= NS_CLIENTSTATE_INACTIVE
;
1762 client
->newstate
= NS_CLIENTSTATE_MAX
;
1763 client
->naccepts
= 0;
1767 client
->nupdates
= 0;
1769 client
->references
= 0;
1770 client
->attributes
= 0;
1771 client
->view
= NULL
;
1772 client
->dispatch
= NULL
;
1773 client
->udpsocket
= NULL
;
1774 client
->tcplistener
= NULL
;
1775 client
->tcpsocket
= NULL
;
1776 client
->tcpmsg_valid
= ISC_FALSE
;
1777 client
->tcpbuf
= NULL
;
1779 client
->udpsize
= 512;
1780 client
->extflags
= 0;
1781 client
->next
= NULL
;
1782 client
->shutdown
= NULL
;
1783 client
->shutdown_arg
= NULL
;
1784 dns_name_init(&client
->signername
, NULL
);
1785 client
->mortal
= ISC_FALSE
;
1786 client
->tcpquota
= NULL
;
1787 client
->recursionquota
= NULL
;
1788 client
->interface
= NULL
;
1789 client
->peeraddr_valid
= ISC_FALSE
;
1790 ISC_EVENT_INIT(&client
->ctlevent
, sizeof(client
->ctlevent
), 0, NULL
,
1791 NS_EVENT_CLIENTCONTROL
, client_start
, client
, client
,
1794 * Initialize FORMERR cache to sentinel value that will not match
1795 * any actual FORMERR response.
1797 isc_sockaddr_any(&client
->formerrcache
.addr
);
1798 client
->formerrcache
.time
= 0;
1799 client
->formerrcache
.id
= 0;
1800 ISC_LINK_INIT(client
, link
);
1801 client
->list
= NULL
;
1804 * We call the init routines for the various kinds of client here,
1805 * after we have created an otherwise valid client, because some
1806 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
1808 result
= ns_query_init(client
);
1809 if (result
!= ISC_R_SUCCESS
)
1810 goto cleanup_recvevent
;
1812 result
= isc_task_onshutdown(client
->task
, client_shutdown
, client
);
1813 if (result
!= ISC_R_SUCCESS
)
1820 return (ISC_R_SUCCESS
);
1823 ns_query_free(client
);
1826 isc_event_free((isc_event_t
**)&client
->recvevent
);
1829 isc_mem_put(manager
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
1832 isc_event_free((isc_event_t
**)&client
->sendevent
);
1837 dns_message_destroy(&client
->message
);
1840 isc_timer_detach(&client
->timer
);
1843 isc_task_detach(&client
->task
);
1846 isc_mem_put(manager
->mctx
, client
, sizeof(*client
));
1852 client_read(ns_client_t
*client
) {
1853 isc_result_t result
;
1857 result
= dns_tcpmsg_readmessage(&client
->tcpmsg
, client
->task
,
1858 client_request
, client
);
1859 if (result
!= ISC_R_SUCCESS
)
1863 * Set a timeout to limit the amount of time we will wait
1864 * for a request on this TCP connection.
1866 ns_client_settimeout(client
, 30);
1868 client
->state
= client
->newstate
= NS_CLIENTSTATE_READING
;
1869 INSIST(client
->nreads
== 0);
1870 INSIST(client
->recursionquota
== NULL
);
1875 ns_client_next(client
, result
);
1879 client_newconn(isc_task_t
*task
, isc_event_t
*event
) {
1880 ns_client_t
*client
= event
->ev_arg
;
1881 isc_socket_newconnev_t
*nevent
= (isc_socket_newconnev_t
*)event
;
1882 isc_result_t result
;
1884 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_NEWCONN
);
1885 REQUIRE(NS_CLIENT_VALID(client
));
1886 REQUIRE(client
->task
== task
);
1890 INSIST(client
->state
== NS_CLIENTSTATE_READY
);
1892 INSIST(client
->naccepts
== 1);
1895 LOCK(&client
->interface
->lock
);
1896 INSIST(client
->interface
->ntcpcurrent
> 0);
1897 client
->interface
->ntcpcurrent
--;
1898 UNLOCK(&client
->interface
->lock
);
1901 * We must take ownership of the new socket before the exit
1902 * check to make sure it gets destroyed if we decide to exit.
1904 if (nevent
->result
== ISC_R_SUCCESS
) {
1905 client
->tcpsocket
= nevent
->newsocket
;
1906 client
->state
= NS_CLIENTSTATE_READING
;
1907 INSIST(client
->recursionquota
== NULL
);
1909 (void)isc_socket_getpeername(client
->tcpsocket
,
1911 client
->peeraddr_valid
= ISC_TRUE
;
1912 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1913 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1914 "new TCP connection");
1917 * XXXRTH What should we do? We're trying to accept but
1918 * it didn't work. If we just give up, then TCP
1919 * service may eventually stop.
1921 * For now, we just go idle.
1923 * Going idle is probably the right thing if the
1926 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1927 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1928 "accept failed: %s",
1929 isc_result_totext(nevent
->result
));
1932 if (exit_check(client
))
1935 if (nevent
->result
== ISC_R_SUCCESS
) {
1937 isc_netaddr_t netaddr
;
1939 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1941 if (ns_g_server
->blackholeacl
!= NULL
&&
1942 dns_acl_match(&netaddr
, NULL
,
1943 ns_g_server
->blackholeacl
,
1944 &ns_g_server
->aclenv
,
1945 &match
, NULL
) == ISC_R_SUCCESS
&&
1948 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1949 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1950 "blackholed connection attempt");
1951 client
->newstate
= NS_CLIENTSTATE_READY
;
1952 (void)exit_check(client
);
1956 INSIST(client
->tcpmsg_valid
== ISC_FALSE
);
1957 dns_tcpmsg_init(client
->mctx
, client
->tcpsocket
,
1959 client
->tcpmsg_valid
= ISC_TRUE
;
1962 * Let a new client take our place immediately, before
1963 * we wait for a request packet. If we don't,
1964 * telnetting to port 53 (once per CPU) will
1965 * deny service to legititmate TCP clients.
1967 result
= isc_quota_attach(&ns_g_server
->tcpquota
,
1969 if (result
== ISC_R_SUCCESS
)
1970 result
= ns_client_replace(client
);
1971 if (result
!= ISC_R_SUCCESS
) {
1972 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1973 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
1974 "no more TCP clients: %s",
1975 isc_result_totext(result
));
1978 client_read(client
);
1982 isc_event_free(&event
);
1986 client_accept(ns_client_t
*client
) {
1987 isc_result_t result
;
1991 result
= isc_socket_accept(client
->tcplistener
, client
->task
,
1992 client_newconn
, client
);
1993 if (result
!= ISC_R_SUCCESS
) {
1994 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1995 "isc_socket_accept() failed: %s",
1996 isc_result_totext(result
));
1998 * XXXRTH What should we do? We're trying to accept but
1999 * it didn't work. If we just give up, then TCP
2000 * service may eventually stop.
2002 * For now, we just go idle.
2006 INSIST(client
->naccepts
== 0);
2008 LOCK(&client
->interface
->lock
);
2009 client
->interface
->ntcpcurrent
++;
2010 UNLOCK(&client
->interface
->lock
);
2014 client_udprecv(ns_client_t
*client
) {
2015 isc_result_t result
;
2020 r
.base
= client
->recvbuf
;
2021 r
.length
= RECV_BUFFER_SIZE
;
2022 result
= isc_socket_recv2(client
->udpsocket
, &r
, 1,
2023 client
->task
, client
->recvevent
, 0);
2024 if (result
!= ISC_R_SUCCESS
) {
2025 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2026 "isc_socket_recv2() failed: %s",
2027 isc_result_totext(result
));
2029 * This cannot happen in the current implementation, since
2030 * isc_socket_recv2() cannot fail if flags == 0.
2032 * If this does fail, we just go idle.
2036 INSIST(client
->nrecvs
== 0);
2041 ns_client_attach(ns_client_t
*source
, ns_client_t
**targetp
) {
2042 REQUIRE(NS_CLIENT_VALID(source
));
2043 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
2045 source
->references
++;
2046 ns_client_log(source
, NS_LOGCATEGORY_CLIENT
,
2047 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2048 "ns_client_attach: ref = %d", source
->references
);
2053 ns_client_detach(ns_client_t
**clientp
) {
2054 ns_client_t
*client
= *clientp
;
2056 client
->references
--;
2057 INSIST(client
->references
>= 0);
2059 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2060 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2061 "ns_client_detach: ref = %d", client
->references
);
2062 (void)exit_check(client
);
2066 ns_client_shuttingdown(ns_client_t
*client
) {
2067 return (ISC_TF(client
->newstate
== NS_CLIENTSTATE_FREED
));
2071 ns_client_replace(ns_client_t
*client
) {
2072 isc_result_t result
;
2076 result
= ns_clientmgr_createclients(client
->manager
,
2077 1, client
->interface
,
2078 (TCP_CLIENT(client
) ?
2079 ISC_TRUE
: ISC_FALSE
));
2080 if (result
!= ISC_R_SUCCESS
)
2084 * The responsibility for listening for new requests is hereby
2085 * transferred to the new client. Therefore, the old client
2086 * should refrain from listening for any more requests.
2088 client
->mortal
= ISC_TRUE
;
2090 return (ISC_R_SUCCESS
);
2098 clientmgr_destroy(ns_clientmgr_t
*manager
) {
2099 REQUIRE(ISC_LIST_EMPTY(manager
->active
));
2100 REQUIRE(ISC_LIST_EMPTY(manager
->inactive
));
2101 REQUIRE(ISC_LIST_EMPTY(manager
->recursing
));
2103 MTRACE("clientmgr_destroy");
2105 DESTROYLOCK(&manager
->lock
);
2107 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2111 ns_clientmgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
2112 isc_timermgr_t
*timermgr
, ns_clientmgr_t
**managerp
)
2114 ns_clientmgr_t
*manager
;
2115 isc_result_t result
;
2117 manager
= isc_mem_get(mctx
, sizeof(*manager
));
2118 if (manager
== NULL
)
2119 return (ISC_R_NOMEMORY
);
2121 result
= isc_mutex_init(&manager
->lock
);
2122 if (result
!= ISC_R_SUCCESS
)
2123 goto cleanup_manager
;
2125 manager
->mctx
= mctx
;
2126 manager
->taskmgr
= taskmgr
;
2127 manager
->timermgr
= timermgr
;
2128 manager
->exiting
= ISC_FALSE
;
2129 ISC_LIST_INIT(manager
->active
);
2130 ISC_LIST_INIT(manager
->inactive
);
2131 ISC_LIST_INIT(manager
->recursing
);
2132 manager
->magic
= MANAGER_MAGIC
;
2136 *managerp
= manager
;
2138 return (ISC_R_SUCCESS
);
2141 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2147 ns_clientmgr_destroy(ns_clientmgr_t
**managerp
) {
2148 ns_clientmgr_t
*manager
;
2149 ns_client_t
*client
;
2150 isc_boolean_t need_destroy
= ISC_FALSE
;
2152 REQUIRE(managerp
!= NULL
);
2153 manager
= *managerp
;
2154 REQUIRE(VALID_MANAGER(manager
));
2158 LOCK(&manager
->lock
);
2160 manager
->exiting
= ISC_TRUE
;
2162 for (client
= ISC_LIST_HEAD(manager
->recursing
);
2164 client
= ISC_LIST_NEXT(client
, link
))
2165 isc_task_shutdown(client
->task
);
2167 for (client
= ISC_LIST_HEAD(manager
->active
);
2169 client
= ISC_LIST_NEXT(client
, link
))
2170 isc_task_shutdown(client
->task
);
2172 for (client
= ISC_LIST_HEAD(manager
->inactive
);
2174 client
= ISC_LIST_NEXT(client
, link
))
2175 isc_task_shutdown(client
->task
);
2177 if (ISC_LIST_EMPTY(manager
->active
) &&
2178 ISC_LIST_EMPTY(manager
->inactive
) &&
2179 ISC_LIST_EMPTY(manager
->recursing
))
2180 need_destroy
= ISC_TRUE
;
2182 UNLOCK(&manager
->lock
);
2185 clientmgr_destroy(manager
);
2191 ns_clientmgr_createclients(ns_clientmgr_t
*manager
, unsigned int n
,
2192 ns_interface_t
*ifp
, isc_boolean_t tcp
)
2194 isc_result_t result
= ISC_R_SUCCESS
;
2196 ns_client_t
*client
;
2198 REQUIRE(VALID_MANAGER(manager
));
2201 MTRACE("createclients");
2204 * We MUST lock the manager lock for the entire client creation
2205 * process. If we didn't do this, then a client could get a
2206 * shutdown event and disappear out from under us.
2209 LOCK(&manager
->lock
);
2211 for (i
= 0; i
< n
; i
++) {
2214 * Allocate a client. First try to get a recycled one;
2215 * if that fails, make a new one.
2217 client
= ISC_LIST_HEAD(manager
->inactive
);
2218 if (client
!= NULL
) {
2220 ISC_LIST_UNLINK(manager
->inactive
, client
, link
);
2221 client
->list
= NULL
;
2223 MTRACE("create new");
2224 result
= client_create(manager
, &client
);
2225 if (result
!= ISC_R_SUCCESS
)
2229 ns_interface_attach(ifp
, &client
->interface
);
2230 client
->state
= NS_CLIENTSTATE_READY
;
2231 INSIST(client
->recursionquota
== NULL
);
2234 client
->attributes
|= NS_CLIENTATTR_TCP
;
2235 isc_socket_attach(ifp
->tcpsocket
,
2236 &client
->tcplistener
);
2240 dns_dispatch_attach(ifp
->udpdispatch
,
2242 sock
= dns_dispatch_getsocket(client
->dispatch
);
2243 isc_socket_attach(sock
, &client
->udpsocket
);
2245 client
->manager
= manager
;
2246 ISC_LIST_APPEND(manager
->active
, client
, link
);
2247 client
->list
= &manager
->active
;
2249 INSIST(client
->nctls
== 0);
2251 ev
= &client
->ctlevent
;
2252 isc_task_send(client
->task
, &ev
);
2256 * We managed to create at least one client, so we
2259 result
= ISC_R_SUCCESS
;
2262 UNLOCK(&manager
->lock
);
2268 ns_client_getsockaddr(ns_client_t
*client
) {
2269 return (&client
->peeraddr
);
2273 ns_client_checkaclsilent(ns_client_t
*client
, dns_acl_t
*acl
,
2274 isc_boolean_t default_allow
)
2276 isc_result_t result
;
2278 isc_netaddr_t netaddr
;
2287 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2289 result
= dns_acl_match(&netaddr
, client
->signer
, acl
,
2290 &ns_g_server
->aclenv
,
2292 if (result
!= ISC_R_SUCCESS
)
2293 goto deny
; /* Internal error, already logged. */
2296 goto deny
; /* Negative match or no match. */
2299 return (ISC_R_SUCCESS
);
2302 return (DNS_R_REFUSED
);
2306 ns_client_checkacl(ns_client_t
*client
,
2307 const char *opname
, dns_acl_t
*acl
,
2308 isc_boolean_t default_allow
, int log_level
)
2310 isc_result_t result
=
2311 ns_client_checkaclsilent(client
, acl
, default_allow
);
2313 if (result
== ISC_R_SUCCESS
)
2314 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2315 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2316 "%s approved", opname
);
2318 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2319 NS_LOGMODULE_CLIENT
,
2320 log_level
, "%s denied", opname
);
2325 ns_client_name(ns_client_t
*client
, char *peerbuf
, size_t len
) {
2326 if (client
->peeraddr_valid
)
2327 isc_sockaddr_format(&client
->peeraddr
, peerbuf
, len
);
2329 snprintf(peerbuf
, len
, "@%p", client
);
2333 ns_client_logv(ns_client_t
*client
, isc_logcategory_t
*category
,
2334 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
2337 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2338 const char *name
= "";
2339 const char *sep
= "";
2341 vsnprintf(msgbuf
, sizeof(msgbuf
), fmt
, ap
);
2342 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
2343 if (client
->view
!= NULL
&& strcmp(client
->view
->name
, "_bind") != 0 &&
2344 strcmp(client
->view
->name
, "_default") != 0) {
2345 name
= client
->view
->name
;
2349 isc_log_write(ns_g_lctx
, category
, module
, level
,
2350 "client %s%s%s: %s", peerbuf
, sep
, name
, msgbuf
);
2354 ns_client_log(ns_client_t
*client
, isc_logcategory_t
*category
,
2355 isc_logmodule_t
*module
, int level
, const char *fmt
, ...)
2359 if (! isc_log_wouldlog(ns_g_lctx
, level
))
2363 ns_client_logv(client
, category
, module
, level
, fmt
, ap
);
2368 ns_client_aclmsg(const char *msg
, dns_name_t
*name
, dns_rdatatype_t type
,
2369 dns_rdataclass_t rdclass
, char *buf
, size_t len
)
2371 char namebuf
[DNS_NAME_FORMATSIZE
];
2372 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
2373 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
2375 dns_name_format(name
, namebuf
, sizeof(namebuf
));
2376 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
2377 dns_rdataclass_format(rdclass
, classbuf
, sizeof(classbuf
));
2378 (void)snprintf(buf
, len
, "%s '%s/%s/%s'", msg
, namebuf
, typebuf
,
2383 ns_client_dumpmessage(ns_client_t
*client
, const char *reason
) {
2384 isc_buffer_t buffer
;
2387 isc_result_t result
;
2390 * Note that these are multiline debug messages. We want a newline
2391 * to appear in the log after each message.
2395 buf
= isc_mem_get(client
->mctx
, len
);
2398 isc_buffer_init(&buffer
, buf
, len
);
2399 result
= dns_message_totext(client
->message
,
2400 &dns_master_style_debug
,
2402 if (result
== ISC_R_NOSPACE
) {
2403 isc_mem_put(client
->mctx
, buf
, len
);
2405 } else if (result
== ISC_R_SUCCESS
)
2406 ns_client_log(client
, NS_LOGCATEGORY_UNMATCHED
,
2407 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
2409 (int)isc_buffer_usedlength(&buffer
),
2411 } while (result
== ISC_R_NOSPACE
);
2414 isc_mem_put(client
->mctx
, buf
, len
);
2418 ns_client_dumprecursing(FILE *f
, ns_clientmgr_t
*manager
) {
2419 ns_client_t
*client
;
2420 char namebuf
[DNS_NAME_FORMATSIZE
];
2421 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2425 REQUIRE(VALID_MANAGER(manager
));
2427 LOCK(&manager
->lock
);
2428 client
= ISC_LIST_HEAD(manager
->recursing
);
2429 while (client
!= NULL
) {
2430 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
2431 if (client
->view
!= NULL
&&
2432 strcmp(client
->view
->name
, "_bind") != 0 &&
2433 strcmp(client
->view
->name
, "_default") != 0) {
2434 name
= client
->view
->name
;
2440 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
2441 fprintf(f
, "; client %s%s%s: '%s' requesttime %d\n",
2442 peerbuf
, sep
, name
, namebuf
, client
->requesttime
);
2443 client
= ISC_LIST_NEXT(client
, link
);
2445 UNLOCK(&manager
->lock
);
2449 ns_client_qnamereplace(ns_client_t
*client
, dns_name_t
*name
) {
2451 if (client
->manager
!= NULL
)
2452 LOCK(&client
->manager
->lock
);
2453 if (client
->query
.restarts
> 0) {
2455 * client->query.qname was dynamically allocated.
2457 dns_message_puttempname(client
->message
,
2458 &client
->query
.qname
);
2460 client
->query
.qname
= name
;
2461 if (client
->manager
!= NULL
)
2462 UNLOCK(&client
->manager
->lock
);