2 * Copyright (C) 2004 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.16 2004/07/23 02:56:59 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/rdata.h>
37 #include <dns/rdataclass.h>
38 #include <dns/rdatalist.h>
39 #include <dns/rdataset.h>
44 #include <named/interfacemgr.h>
45 #include <named/log.h>
46 #include <named/notify.h>
47 #include <named/server.h>
48 #include <named/update.h>
57 * All client state changes, other than that from idle to listening, occur
58 * as a result of events. This guarantees serialization and avoids the
61 * If a routine is ever created that allows someone other than the client's
62 * task to change the client, then the client will have to be locked.
65 #define NS_CLIENT_TRACE
66 #ifdef NS_CLIENT_TRACE
67 #define CTRACE(m) ns_client_log(client, \
68 NS_LOGCATEGORY_CLIENT, \
69 NS_LOGMODULE_CLIENT, \
72 #define MTRACE(m) isc_log_write(ns_g_lctx, \
73 NS_LOGCATEGORY_GENERAL, \
74 NS_LOGMODULE_CLIENT, \
76 "clientmgr @%p: %s", manager, (m))
78 #define CTRACE(m) ((void)(m))
79 #define MTRACE(m) ((void)(m))
82 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
84 #define TCP_BUFFER_SIZE (65535 + 2)
85 #define SEND_BUFFER_SIZE 4096
86 #define RECV_BUFFER_SIZE 4096
92 isc_taskmgr_t
* taskmgr
;
93 isc_timermgr_t
* timermgr
;
96 isc_boolean_t exiting
;
97 client_list_t active
; /* Active clients */
98 client_list_t inactive
; /* To be recycled */
101 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
102 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
105 * Client object states. Ordering is significant: higher-numbered
106 * states are generally "more active", meaning that the client can
107 * have more dynamically allocated data, outstanding events, etc.
108 * In the list below, any such properties listed for state N
109 * also apply to any state > N.
111 * To force the client into a less active state, set client->newstate
112 * to that state and call exit_check(). This will cause any
113 * activities defined for higher-numbered states to be aborted.
116 #define NS_CLIENTSTATE_FREED 0
118 * The client object no longer exists.
121 #define NS_CLIENTSTATE_INACTIVE 1
123 * The client object exists and has a task and timer.
124 * Its "query" struct and sendbuf are initialized.
125 * It is on the client manager's list of inactive clients.
126 * It has a message and OPT, both in the reset state.
129 #define NS_CLIENTSTATE_READY 2
131 * The client object is either a TCP or a UDP one, and
132 * it is associated with a network interface. It is on the
133 * client manager's list of active clients.
135 * If it is a TCP client object, it has a TCP listener socket
136 * and an outstanding TCP listen request.
138 * If it is a UDP client object, it has a UDP listener socket
139 * and an outstanding UDP receive request.
142 #define NS_CLIENTSTATE_READING 3
144 * The client object is a TCP client object that has received
145 * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
146 * outstanding TCP read request. This state is not used for
147 * UDP client objects.
150 #define NS_CLIENTSTATE_WORKING 4
152 * The client object has received a request and is working
153 * on it. It has a view, and it may have any of a non-reset OPT,
154 * recursion quota, and an outstanding write request.
157 #define NS_CLIENTSTATE_MAX 9
159 * Sentinel value used to indicate "no state". When client->newstate
160 * has this value, we are not attempting to exit the current state.
161 * Must be greater than any valid state.
165 static void client_read(ns_client_t
*client
);
166 static void client_accept(ns_client_t
*client
);
167 static void client_udprecv(ns_client_t
*client
);
168 static void clientmgr_destroy(ns_clientmgr_t
*manager
);
169 static isc_boolean_t
exit_check(ns_client_t
*client
);
170 static void ns_client_endrequest(ns_client_t
*client
);
171 static void ns_client_checkactive(ns_client_t
*client
);
172 static void client_start(isc_task_t
*task
, isc_event_t
*event
);
173 static void client_request(isc_task_t
*task
, isc_event_t
*event
);
174 static void ns_client_dumpmessage(ns_client_t
*client
, const char *reason
);
177 ns_client_settimeout(ns_client_t
*client
, unsigned int seconds
) {
179 isc_interval_t interval
;
181 isc_interval_set(&interval
, seconds
, 0);
182 result
= isc_timer_reset(client
->timer
, isc_timertype_once
, NULL
,
183 &interval
, ISC_FALSE
);
184 client
->timerset
= ISC_TRUE
;
185 if (result
!= ISC_R_SUCCESS
) {
186 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
187 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
188 "setting timeout: %s",
189 isc_result_totext(result
));
190 /* Continue anyway. */
195 * Check for a deactivation or shutdown request and take appropriate
196 * action. Returns ISC_TRUE if either is in progress; in this case
197 * the caller must no longer use the client object as it may have been
201 exit_check(ns_client_t
*client
) {
202 ns_clientmgr_t
*locked_manager
= NULL
;
203 ns_clientmgr_t
*destroy_manager
= NULL
;
205 REQUIRE(NS_CLIENT_VALID(client
));
207 if (client
->state
<= client
->newstate
)
208 return (ISC_FALSE
); /* Business as usual. */
210 INSIST(client
->newstate
< NS_CLIENTSTATE_WORKING
);
213 * We need to detach from the view early when shutting down
214 * the server to break the following vicious circle:
216 * - The resolver will not shut down until the view refcount is zero
217 * - The view refcount does not go to zero until all clients detach
218 * - The client does not detach from the view until references is zero
219 * - references does not go to zero until the resolver has shut down
221 * Keep the view attached until any outstanding updates complete.
223 if (client
->nupdates
== 0 &&
224 client
->newstate
== NS_CLIENTSTATE_FREED
&& client
->view
!= NULL
)
225 dns_view_detach(&client
->view
);
227 if (client
->state
== NS_CLIENTSTATE_WORKING
) {
228 INSIST(client
->newstate
<= NS_CLIENTSTATE_READING
);
230 * Let the update processing complete.
232 if (client
->nupdates
> 0)
235 * We are trying to abort request processing.
237 if (client
->nsends
> 0) {
238 isc_socket_t
*socket
;
239 if (TCP_CLIENT(client
))
240 socket
= client
->tcpsocket
;
242 socket
= client
->udpsocket
;
243 isc_socket_cancel(socket
, client
->task
,
244 ISC_SOCKCANCEL_SEND
);
247 if (! (client
->nsends
== 0 && client
->nrecvs
== 0 &&
248 client
->references
== 0))
251 * Still waiting for I/O cancel completion.
252 * or lingering references.
257 * I/O cancel is complete. Burn down all state
258 * related to the current request.
260 ns_client_endrequest(client
);
262 client
->state
= NS_CLIENTSTATE_READING
;
263 INSIST(client
->recursionquota
== NULL
);
264 if (NS_CLIENTSTATE_READING
== client
->newstate
) {
266 client
->newstate
= NS_CLIENTSTATE_MAX
;
267 return (ISC_TRUE
); /* We're done. */
271 if (client
->state
== NS_CLIENTSTATE_READING
) {
273 * We are trying to abort the current TCP connection,
276 INSIST(client
->recursionquota
== NULL
);
277 INSIST(client
->newstate
<= NS_CLIENTSTATE_READY
);
278 if (client
->nreads
> 0)
279 dns_tcpmsg_cancelread(&client
->tcpmsg
);
280 if (! client
->nreads
== 0) {
281 /* Still waiting for read cancel completion. */
285 if (client
->tcpmsg_valid
) {
286 dns_tcpmsg_invalidate(&client
->tcpmsg
);
287 client
->tcpmsg_valid
= ISC_FALSE
;
289 if (client
->tcpsocket
!= NULL
) {
291 isc_socket_detach(&client
->tcpsocket
);
294 if (client
->tcpquota
!= NULL
)
295 isc_quota_detach(&client
->tcpquota
);
297 if (client
->timerset
) {
298 (void) isc_timer_reset(client
->timer
,
299 isc_timertype_inactive
,
300 NULL
, NULL
, ISC_TRUE
);
301 client
->timerset
= ISC_FALSE
;
304 client
->peeraddr_valid
= ISC_FALSE
;
306 client
->state
= NS_CLIENTSTATE_READY
;
307 INSIST(client
->recursionquota
== NULL
);
310 * Now the client is ready to accept a new TCP connection
311 * or UDP request, but we may have enough clients doing
312 * that already. Check whether this client needs to remain
313 * active and force it to go inactive if not.
315 ns_client_checkactive(client
);
317 if (NS_CLIENTSTATE_READY
== client
->newstate
) {
318 if (TCP_CLIENT(client
)) {
319 client_accept(client
);
321 client_udprecv(client
);
322 client
->newstate
= NS_CLIENTSTATE_MAX
;
327 if (client
->state
== NS_CLIENTSTATE_READY
) {
328 INSIST(client
->newstate
<= NS_CLIENTSTATE_INACTIVE
);
330 * We are trying to enter the inactive state.
332 if (client
->naccepts
> 0)
333 isc_socket_cancel(client
->tcplistener
, client
->task
,
334 ISC_SOCKCANCEL_ACCEPT
);
336 if (! (client
->naccepts
== 0)) {
337 /* Still waiting for accept cancel completion. */
340 /* Accept cancel is complete. */
342 if (client
->nrecvs
> 0)
343 isc_socket_cancel(client
->udpsocket
, client
->task
,
344 ISC_SOCKCANCEL_RECV
);
345 if (! (client
->nrecvs
== 0)) {
346 /* Still waiting for recv cancel completion. */
349 /* Recv cancel is complete. */
351 if (client
->nctls
> 0) {
352 /* Still waiting for control event to be delivered */
356 /* Deactivate the client. */
357 if (client
->interface
)
358 ns_interface_detach(&client
->interface
);
360 INSIST(client
->naccepts
== 0);
361 INSIST(client
->recursionquota
== NULL
);
362 if (client
->tcplistener
!= NULL
)
363 isc_socket_detach(&client
->tcplistener
);
365 if (client
->udpsocket
!= NULL
)
366 isc_socket_detach(&client
->udpsocket
);
368 if (client
->dispatch
!= NULL
)
369 dns_dispatch_detach(&client
->dispatch
);
371 client
->attributes
= 0;
372 client
->mortal
= ISC_FALSE
;
374 LOCK(&client
->manager
->lock
);
376 * Put the client on the inactive list. If we are aiming for
377 * the "freed" state, it will be removed from the inactive
378 * list shortly, and we need to keep the manager locked until
379 * that has been done, lest the manager decide to reactivate
380 * the dying client inbetween.
382 locked_manager
= client
->manager
;
383 ISC_LIST_UNLINK(*client
->list
, client
, link
);
384 ISC_LIST_APPEND(client
->manager
->inactive
, client
, link
);
385 client
->list
= &client
->manager
->inactive
;
386 client
->state
= NS_CLIENTSTATE_INACTIVE
;
387 INSIST(client
->recursionquota
== NULL
);
389 if (client
->state
== client
->newstate
) {
390 client
->newstate
= NS_CLIENTSTATE_MAX
;
395 if (client
->state
== NS_CLIENTSTATE_INACTIVE
) {
396 INSIST(client
->newstate
== NS_CLIENTSTATE_FREED
);
398 * We are trying to free the client.
400 * When "shuttingdown" is true, either the task has received
401 * its shutdown event or no shutdown event has ever been
402 * set up. Thus, we have no outstanding shutdown
403 * event at this point.
405 REQUIRE(client
->state
== NS_CLIENTSTATE_INACTIVE
);
407 INSIST(client
->recursionquota
== NULL
);
409 ns_query_free(client
);
410 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
411 isc_event_free((isc_event_t
**)&client
->sendevent
);
412 isc_event_free((isc_event_t
**)&client
->recvevent
);
413 isc_timer_detach(&client
->timer
);
415 if (client
->tcpbuf
!= NULL
)
416 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
417 if (client
->opt
!= NULL
) {
418 INSIST(dns_rdataset_isassociated(client
->opt
));
419 dns_rdataset_disassociate(client
->opt
);
420 dns_message_puttemprdataset(client
->message
, &client
->opt
);
422 dns_message_destroy(&client
->message
);
423 if (client
->manager
!= NULL
) {
424 ns_clientmgr_t
*manager
= client
->manager
;
425 if (locked_manager
== NULL
) {
426 LOCK(&manager
->lock
);
427 locked_manager
= manager
;
429 ISC_LIST_UNLINK(*client
->list
, client
, link
);
431 if (manager
->exiting
&&
432 ISC_LIST_EMPTY(manager
->active
) &&
433 ISC_LIST_EMPTY(manager
->inactive
))
434 destroy_manager
= manager
;
437 * Detaching the task must be done after unlinking from
438 * the manager's lists because the manager accesses
441 if (client
->task
!= NULL
)
442 isc_task_detach(&client
->task
);
446 isc_mem_put(client
->mctx
, client
, sizeof(*client
));
452 if (locked_manager
!= NULL
) {
453 UNLOCK(&locked_manager
->lock
);
454 locked_manager
= NULL
;
458 * Only now is it safe to destroy the client manager (if needed),
459 * because we have accessed its lock for the last time.
461 if (destroy_manager
!= NULL
)
462 clientmgr_destroy(destroy_manager
);
468 * The client's task has received the client's control event
469 * as part of the startup process.
472 client_start(isc_task_t
*task
, isc_event_t
*event
) {
473 ns_client_t
*client
= (ns_client_t
*) event
->ev_arg
;
475 INSIST(task
== client
->task
);
479 INSIST(client
->nctls
== 1);
482 if (exit_check(client
))
485 if (TCP_CLIENT(client
)) {
486 client_accept(client
);
488 client_udprecv(client
);
494 * The client's task has received a shutdown event.
497 client_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
500 REQUIRE(event
!= NULL
);
501 REQUIRE(event
->ev_type
== ISC_TASKEVENT_SHUTDOWN
);
502 client
= event
->ev_arg
;
503 REQUIRE(NS_CLIENT_VALID(client
));
504 REQUIRE(task
== client
->task
);
510 isc_event_free(&event
);
512 if (client
->shutdown
!= NULL
) {
513 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_SHUTTINGDOWN
);
514 client
->shutdown
= NULL
;
515 client
->shutdown_arg
= NULL
;
518 client
->newstate
= NS_CLIENTSTATE_FREED
;
519 (void)exit_check(client
);
524 ns_client_endrequest(ns_client_t
*client
) {
525 INSIST(client
->naccepts
== 0);
526 INSIST(client
->nreads
== 0);
527 INSIST(client
->nsends
== 0);
528 INSIST(client
->nrecvs
== 0);
529 INSIST(client
->nupdates
== 0);
530 INSIST(client
->state
== NS_CLIENTSTATE_WORKING
);
532 CTRACE("endrequest");
534 if (client
->next
!= NULL
) {
535 (client
->next
)(client
);
539 if (client
->view
!= NULL
)
540 dns_view_detach(&client
->view
);
541 if (client
->opt
!= NULL
) {
542 INSIST(dns_rdataset_isassociated(client
->opt
));
543 dns_rdataset_disassociate(client
->opt
);
544 dns_message_puttemprdataset(client
->message
, &client
->opt
);
547 client
->udpsize
= 512;
548 client
->extflags
= 0;
549 dns_message_reset(client
->message
, DNS_MESSAGE_INTENTPARSE
);
551 if (client
->recursionquota
!= NULL
)
552 isc_quota_detach(&client
->recursionquota
);
555 * Clear all client attributes that are specific to
556 * the request; that's all except the TCP flag.
558 client
->attributes
&= NS_CLIENTATTR_TCP
;
562 ns_client_checkactive(ns_client_t
*client
) {
563 if (client
->mortal
) {
565 * This client object should normally go inactive
566 * at this point, but if we have fewer active client
567 * objects than desired due to earlier quota exhaustion,
568 * keep it active to make up for the shortage.
570 isc_boolean_t need_another_client
= ISC_FALSE
;
571 if (TCP_CLIENT(client
)) {
572 LOCK(&client
->interface
->lock
);
573 if (client
->interface
->ntcpcurrent
<
574 client
->interface
->ntcptarget
)
575 need_another_client
= ISC_TRUE
;
576 UNLOCK(&client
->interface
->lock
);
579 * The UDP client quota is enforced by making
580 * requests fail rather than by not listening
581 * for new ones. Therefore, there is always a
582 * full set of UDP clients listening.
585 if (! need_another_client
) {
587 * We don't need this client object. Recycle it.
589 if (client
->newstate
>= NS_CLIENTSTATE_INACTIVE
)
590 client
->newstate
= NS_CLIENTSTATE_INACTIVE
;
596 ns_client_next(ns_client_t
*client
, isc_result_t result
) {
599 REQUIRE(NS_CLIENT_VALID(client
));
600 REQUIRE(client
->state
== NS_CLIENTSTATE_WORKING
||
601 client
->state
== NS_CLIENTSTATE_READING
);
605 if (result
!= ISC_R_SUCCESS
)
606 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
607 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
608 "request failed: %s", isc_result_totext(result
));
611 * An error processing a TCP request may have left
612 * the connection out of sync. To be safe, we always
613 * sever the connection when result != ISC_R_SUCCESS.
615 if (result
== ISC_R_SUCCESS
&& TCP_CLIENT(client
))
616 newstate
= NS_CLIENTSTATE_READING
;
618 newstate
= NS_CLIENTSTATE_READY
;
620 if (client
->newstate
> newstate
)
621 client
->newstate
= newstate
;
622 (void) exit_check(client
);
627 client_senddone(isc_task_t
*task
, isc_event_t
*event
) {
629 isc_socketevent_t
*sevent
= (isc_socketevent_t
*) event
;
631 REQUIRE(sevent
!= NULL
);
632 REQUIRE(sevent
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
633 client
= sevent
->ev_arg
;
634 REQUIRE(NS_CLIENT_VALID(client
));
635 REQUIRE(task
== client
->task
);
636 REQUIRE(sevent
== client
->sendevent
);
642 if (sevent
->result
!= ISC_R_SUCCESS
)
643 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
644 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
645 "error sending response: %s",
646 isc_result_totext(sevent
->result
));
648 INSIST(client
->nsends
> 0);
651 if (client
->tcpbuf
!= NULL
) {
652 INSIST(TCP_CLIENT(client
));
653 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
654 client
->tcpbuf
= NULL
;
657 if (exit_check(client
))
660 ns_client_next(client
, ISC_R_SUCCESS
);
664 * We only want to fail with ISC_R_NOSPACE when called from
665 * ns_client_sendraw() and not when called from ns_client_send(),
666 * tcpbuffer is NULL when called from ns_client_sendraw() and
667 * length != 0. tcpbuffer != NULL when called from ns_client_send()
672 client_allocsendbuf(ns_client_t
*client
, isc_buffer_t
*buffer
,
673 isc_buffer_t
*tcpbuffer
, isc_uint32_t length
,
674 unsigned char *sendbuf
, unsigned char **datap
)
677 isc_uint32_t bufsize
;
680 INSIST(datap
!= NULL
);
681 INSIST((tcpbuffer
== NULL
&& length
!= 0) ||
682 (tcpbuffer
!= NULL
&& length
== 0));
684 if (TCP_CLIENT(client
)) {
685 INSIST(client
->tcpbuf
== NULL
);
686 if (length
+ 2 > TCP_BUFFER_SIZE
) {
687 result
= ISC_R_NOSPACE
;
690 client
->tcpbuf
= isc_mem_get(client
->mctx
, TCP_BUFFER_SIZE
);
691 if (client
->tcpbuf
== NULL
) {
692 result
= ISC_R_NOMEMORY
;
695 data
= client
->tcpbuf
;
696 if (tcpbuffer
!= NULL
) {
697 isc_buffer_init(tcpbuffer
, data
, TCP_BUFFER_SIZE
);
698 isc_buffer_init(buffer
, data
+ 2, TCP_BUFFER_SIZE
- 2);
700 isc_buffer_init(buffer
, data
, TCP_BUFFER_SIZE
);
701 INSIST(length
<= 0xffff);
702 isc_buffer_putuint16(buffer
, (isc_uint16_t
)length
);
706 if (client
->udpsize
< SEND_BUFFER_SIZE
)
707 bufsize
= client
->udpsize
;
709 bufsize
= SEND_BUFFER_SIZE
;
710 if (length
> bufsize
) {
711 result
= ISC_R_NOSPACE
;
714 isc_buffer_init(buffer
, data
, bufsize
);
717 result
= ISC_R_SUCCESS
;
724 client_sendpkg(ns_client_t
*client
, isc_buffer_t
*buffer
) {
725 struct in6_pktinfo
*pktinfo
;
728 isc_sockaddr_t
*address
;
729 isc_socket_t
*socket
;
730 isc_netaddr_t netaddr
;
732 unsigned int sockflags
= ISC_SOCKFLAG_IMMEDIATE
;
734 if (TCP_CLIENT(client
)) {
735 socket
= client
->tcpsocket
;
738 socket
= client
->udpsocket
;
739 address
= &client
->peeraddr
;
741 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
742 if (ns_g_server
->blackholeacl
!= NULL
&&
743 dns_acl_match(&netaddr
, NULL
,
744 ns_g_server
->blackholeacl
,
745 &ns_g_server
->aclenv
,
746 &match
, NULL
) == ISC_R_SUCCESS
&&
748 return (DNS_R_BLACKHOLED
);
749 sockflags
|= ISC_SOCKFLAG_NORETRY
;
752 if ((client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0)
753 pktinfo
= &client
->pktinfo
;
757 isc_buffer_usedregion(buffer
, &r
);
761 result
= isc_socket_sendto2(socket
, &r
, client
->task
,
763 client
->sendevent
, sockflags
);
764 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_INPROGRESS
) {
766 if (result
== ISC_R_SUCCESS
)
767 client_senddone(client
->task
,
768 (isc_event_t
*)client
->sendevent
);
769 result
= ISC_R_SUCCESS
;
775 ns_client_sendraw(ns_client_t
*client
, dns_message_t
*message
) {
781 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
783 REQUIRE(NS_CLIENT_VALID(client
));
787 mr
= dns_message_getrawmessage(message
);
789 result
= ISC_R_UNEXPECTEDEND
;
793 result
= client_allocsendbuf(client
, &buffer
, NULL
, mr
->length
,
795 if (result
!= ISC_R_SUCCESS
)
799 * Copy message to buffer and fixup id.
801 isc_buffer_availableregion(&buffer
, &r
);
802 result
= isc_buffer_copyregion(&buffer
, mr
);
803 if (result
!= ISC_R_SUCCESS
)
805 r
.base
[0] = (client
->message
->id
>> 8) & 0xff;
806 r
.base
[1] = client
->message
->id
& 0xff;
808 result
= client_sendpkg(client
, &buffer
);
809 if (result
== ISC_R_SUCCESS
)
813 if (client
->tcpbuf
!= NULL
) {
814 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
815 client
->tcpbuf
= NULL
;
817 ns_client_next(client
, result
);
821 ns_client_send(ns_client_t
*client
) {
825 isc_buffer_t tcpbuffer
;
828 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
829 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
831 REQUIRE(NS_CLIENT_VALID(client
));
835 if ((client
->attributes
& NS_CLIENTATTR_RA
) != 0)
836 client
->message
->flags
|= DNS_MESSAGEFLAG_RA
;
839 * XXXRTH The following doesn't deal with TCP buffer resizing.
841 result
= client_allocsendbuf(client
, &buffer
, &tcpbuffer
, 0,
843 if (result
!= ISC_R_SUCCESS
)
846 result
= dns_compress_init(&cctx
, -1, client
->mctx
);
847 if (result
!= ISC_R_SUCCESS
)
849 cleanup_cctx
= ISC_TRUE
;
851 result
= dns_message_renderbegin(client
->message
, &cctx
, &buffer
);
852 if (result
!= ISC_R_SUCCESS
)
854 if (client
->opt
!= NULL
) {
855 result
= dns_message_setopt(client
->message
, client
->opt
);
857 * XXXRTH dns_message_setopt() should probably do this...
860 if (result
!= ISC_R_SUCCESS
)
863 result
= dns_message_rendersection(client
->message
,
864 DNS_SECTION_QUESTION
, 0);
865 if (result
== ISC_R_NOSPACE
) {
866 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
869 if (result
!= ISC_R_SUCCESS
)
871 result
= dns_message_rendersection(client
->message
,
873 DNS_MESSAGERENDER_PARTIAL
);
874 if (result
== ISC_R_NOSPACE
) {
875 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
878 if (result
!= ISC_R_SUCCESS
)
880 result
= dns_message_rendersection(client
->message
,
881 DNS_SECTION_AUTHORITY
,
882 DNS_MESSAGERENDER_PARTIAL
);
883 if (result
== ISC_R_NOSPACE
) {
884 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
887 if (result
!= ISC_R_SUCCESS
)
889 result
= dns_message_rendersection(client
->message
,
890 DNS_SECTION_ADDITIONAL
, 0);
891 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
894 result
= dns_message_renderend(client
->message
);
896 if (result
!= ISC_R_SUCCESS
)
900 dns_compress_invalidate(&cctx
);
901 cleanup_cctx
= ISC_FALSE
;
904 if (TCP_CLIENT(client
)) {
905 isc_buffer_usedregion(&buffer
, &r
);
906 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
) r
.length
);
907 isc_buffer_add(&tcpbuffer
, r
.length
);
908 result
= client_sendpkg(client
, &tcpbuffer
);
910 result
= client_sendpkg(client
, &buffer
);
911 if (result
== ISC_R_SUCCESS
)
915 if (client
->tcpbuf
!= NULL
) {
916 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
917 client
->tcpbuf
= NULL
;
921 dns_compress_invalidate(&cctx
);
923 ns_client_next(client
, result
);
927 ns_client_error(ns_client_t
*client
, isc_result_t result
) {
929 dns_message_t
*message
;
931 REQUIRE(NS_CLIENT_VALID(client
));
935 message
= client
->message
;
936 rcode
= dns_result_torcode(result
);
939 * Message may be an in-progress reply that we had trouble
940 * with, in which case QR will be set. We need to clear QR before
941 * calling dns_message_reply() to avoid triggering an assertion.
943 message
->flags
&= ~DNS_MESSAGEFLAG_QR
;
945 * AA and AD shouldn't be set.
947 message
->flags
&= ~(DNS_MESSAGEFLAG_AA
| DNS_MESSAGEFLAG_AD
);
948 result
= dns_message_reply(message
, ISC_TRUE
);
949 if (result
!= ISC_R_SUCCESS
) {
951 * It could be that we've got a query with a good header,
952 * but a bad question section, so we try again with
953 * want_question_section set to ISC_FALSE.
955 result
= dns_message_reply(message
, ISC_FALSE
);
956 if (result
!= ISC_R_SUCCESS
) {
957 ns_client_next(client
, result
);
961 message
->rcode
= rcode
;
964 * FORMERR loop avoidance: If we sent a FORMERR message
965 * with the same ID to the same client less than two
966 * seconds ago, assume that we are in an infinite error
967 * packet dialog with a server for some protocol whose
968 * error responses look enough like DNS queries to
969 * elicit a FORMERR response. Drop a packet to break
972 if (rcode
== dns_rcode_formerr
) {
973 if (isc_sockaddr_equal(&client
->peeraddr
,
974 &client
->formerrcache
.addr
) &&
975 message
->id
== client
->formerrcache
.id
&&
976 client
->requesttime
- client
->formerrcache
.time
< 2) {
978 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
979 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
980 "possible error packet loop, "
982 ns_client_next(client
, result
);
985 client
->formerrcache
.addr
= client
->peeraddr
;
986 client
->formerrcache
.time
= client
->requesttime
;
987 client
->formerrcache
.id
= message
->id
;
989 ns_client_send(client
);
992 static inline isc_result_t
993 client_addopt(ns_client_t
*client
) {
994 dns_rdataset_t
*rdataset
;
995 dns_rdatalist_t
*rdatalist
;
999 REQUIRE(client
->opt
== NULL
); /* XXXRTH free old. */
1002 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
1003 if (result
!= ISC_R_SUCCESS
)
1006 result
= dns_message_gettemprdata(client
->message
, &rdata
);
1007 if (result
!= ISC_R_SUCCESS
)
1010 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
1011 if (result
!= ISC_R_SUCCESS
)
1013 dns_rdataset_init(rdataset
);
1015 rdatalist
->type
= dns_rdatatype_opt
;
1016 rdatalist
->covers
= 0;
1019 * Set the maximum UDP buffer size.
1021 rdatalist
->rdclass
= RECV_BUFFER_SIZE
;
1024 * Set EXTENDED-RCODE, VERSION, and Z to 0.
1027 rdatalist
->ttl
= (client
->extflags
& DNS_MESSAGEEXTFLAG_REPLYPRESERVE
);
1033 * No ENDS options in the default case.
1037 rdata
->rdclass
= rdatalist
->rdclass
;
1038 rdata
->type
= rdatalist
->type
;
1041 ISC_LIST_INIT(rdatalist
->rdata
);
1042 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1043 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1045 client
->opt
= rdataset
;
1047 return (ISC_R_SUCCESS
);
1050 static inline isc_boolean_t
1051 allowed(isc_netaddr_t
*addr
, dns_acl_t
*acl
) {
1053 isc_result_t result
;
1057 result
= dns_acl_match(addr
, NULL
, acl
, &ns_g_server
->aclenv
,
1059 if (result
== ISC_R_SUCCESS
&& match
> 0)
1065 * Handle an incoming request event from the socket (UDP case)
1066 * or tcpmsg (TCP case).
1069 client_request(isc_task_t
*task
, isc_event_t
*event
) {
1070 ns_client_t
*client
;
1071 isc_socketevent_t
*sevent
;
1072 isc_result_t result
;
1073 isc_result_t sigresult
;
1074 isc_buffer_t
*buffer
;
1075 isc_buffer_t tbuffer
;
1077 dns_rdataset_t
*opt
;
1078 isc_boolean_t ra
; /* Recursion available. */
1079 isc_netaddr_t netaddr
;
1080 isc_netaddr_t destaddr
;
1084 isc_boolean_t notimp
;
1086 REQUIRE(event
!= NULL
);
1087 client
= event
->ev_arg
;
1088 REQUIRE(NS_CLIENT_VALID(client
));
1089 REQUIRE(task
== client
->task
);
1093 INSIST(client
->recursionquota
== NULL
);
1095 INSIST(client
->state
==
1096 TCP_CLIENT(client
) ?
1097 NS_CLIENTSTATE_READING
:
1098 NS_CLIENTSTATE_READY
);
1100 if (event
->ev_type
== ISC_SOCKEVENT_RECVDONE
) {
1101 INSIST(!TCP_CLIENT(client
));
1102 sevent
= (isc_socketevent_t
*)event
;
1103 REQUIRE(sevent
== client
->recvevent
);
1104 isc_buffer_init(&tbuffer
, sevent
->region
.base
, sevent
->n
);
1105 isc_buffer_add(&tbuffer
, sevent
->n
);
1107 result
= sevent
->result
;
1108 if (result
== ISC_R_SUCCESS
) {
1109 client
->peeraddr
= sevent
->address
;
1110 client
->peeraddr_valid
= ISC_TRUE
;
1112 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_PKTINFO
) != 0) {
1113 client
->attributes
|= NS_CLIENTATTR_PKTINFO
;
1114 client
->pktinfo
= sevent
->pktinfo
;
1116 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_MULTICAST
) != 0)
1117 client
->attributes
|= NS_CLIENTATTR_MULTICAST
;
1120 INSIST(TCP_CLIENT(client
));
1121 REQUIRE(event
->ev_type
== DNS_EVENT_TCPMSG
);
1122 REQUIRE(event
->ev_sender
== &client
->tcpmsg
);
1123 buffer
= &client
->tcpmsg
.buffer
;
1124 result
= client
->tcpmsg
.result
;
1125 INSIST(client
->nreads
== 1);
1127 * client->peeraddr was set when the connection was accepted.
1132 if (exit_check(client
))
1134 client
->state
= client
->newstate
= NS_CLIENTSTATE_WORKING
;
1136 isc_stdtime_get(&client
->requesttime
);
1137 client
->now
= client
->requesttime
;
1139 if (result
!= ISC_R_SUCCESS
) {
1140 if (TCP_CLIENT(client
)) {
1141 ns_client_next(client
, result
);
1143 if (result
!= ISC_R_CANCELED
)
1144 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_CLIENT
,
1145 NS_LOGMODULE_CLIENT
,
1147 "UDP client handler shutting "
1148 "down due to fatal receive "
1150 isc_result_totext(result
));
1151 isc_task_shutdown(client
->task
);
1156 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1158 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1159 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1161 TCP_CLIENT(client
) ? "TCP" : "UDP");
1164 * Check the blackhole ACL for UDP only, since TCP is done in
1167 if (!TCP_CLIENT(client
)) {
1169 if (ns_g_server
->blackholeacl
!= NULL
&&
1170 dns_acl_match(&netaddr
, NULL
, ns_g_server
->blackholeacl
,
1171 &ns_g_server
->aclenv
,
1172 &match
, NULL
) == ISC_R_SUCCESS
&&
1175 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1176 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1177 "blackholed UDP datagram");
1178 ns_client_next(client
, ISC_R_SUCCESS
);
1183 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0) {
1184 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1185 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(2),
1186 "multicast request");
1188 ns_client_error(client
, DNS_R_REFUSED
);
1192 result
= dns_message_peekheader(buffer
, &id
, &flags
);
1193 if (result
!= ISC_R_SUCCESS
) {
1195 * There isn't enough header to determine whether
1196 * this was a request or a response. Drop it.
1198 ns_client_next(client
, result
);
1203 * The client object handles requests, not responses.
1204 * If this is a UDP response, forward it to the dispatcher.
1205 * If it's a TCP response, discard it here.
1207 if ((flags
& DNS_MESSAGEFLAG_QR
) != 0) {
1208 if (TCP_CLIENT(client
)) {
1209 CTRACE("unexpected response");
1210 ns_client_next(client
, DNS_R_FORMERR
);
1213 dns_dispatch_importrecv(client
->dispatch
, event
);
1214 ns_client_next(client
, ISC_R_SUCCESS
);
1220 * It's a request. Parse it.
1222 result
= dns_message_parse(client
->message
, buffer
, 0);
1223 if (result
!= ISC_R_SUCCESS
) {
1225 * Parsing the request failed. Send a response
1226 * (typically FORMERR or SERVFAIL).
1228 ns_client_error(client
, result
);
1232 switch (client
->message
->opcode
) {
1233 case dns_opcode_query
:
1234 case dns_opcode_update
:
1235 case dns_opcode_notify
:
1238 case dns_opcode_iquery
:
1244 client
->message
->rcode
= dns_rcode_noerror
;
1249 opt
= dns_message_getopt(client
->message
);
1251 unsigned int version
;
1254 * Set the client's UDP buffer size.
1256 client
->udpsize
= opt
->rdclass
;
1259 * If the requested UDP buffer size is less than 512,
1260 * ignore it and use 512.
1262 if (client
->udpsize
< 512)
1263 client
->udpsize
= 512;
1266 * Get the flags out of the OPT record.
1268 client
->extflags
= (isc_uint16_t
)(opt
->ttl
& 0xFFFF);
1271 * Create an OPT for our reply.
1273 result
= client_addopt(client
);
1274 if (result
!= ISC_R_SUCCESS
) {
1275 ns_client_error(client
, result
);
1280 * Do we understand this version of ENDS?
1282 * XXXRTH need library support for this!
1284 version
= (opt
->ttl
& 0x00FF0000) >> 16;
1286 ns_client_error(client
, DNS_R_BADVERS
);
1291 if (client
->message
->rdclass
== 0) {
1292 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1293 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1294 "message class could not be determined");
1295 ns_client_dumpmessage(client
,
1296 "message class could not be determined");
1297 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_FORMERR
);
1302 * Determine the destination address. For TCP/IPv6, we get this from
1303 * the receiving socket. For UDP/IPv6, we get it from the pktinfo
1304 * structure (if supported). For IPv4, we have to do with
1305 * the address of the interface where the request was received.
1307 if (client
->interface
->addr
.type
.sa
.sa_family
== AF_INET6
) {
1308 result
= ISC_R_FAILURE
;
1310 if (TCP_CLIENT(client
)) {
1311 isc_sockaddr_t destsockaddr
;
1313 result
= isc_socket_getsockname(client
->tcpsocket
,
1315 if (result
== ISC_R_SUCCESS
)
1316 isc_netaddr_fromsockaddr(&destaddr
,
1319 if (result
!= ISC_R_SUCCESS
&&
1320 (client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0) {
1321 isc_netaddr_fromin6(&destaddr
, &client
->pktinfo
.ipi6_addr
);
1322 result
= ISC_R_SUCCESS
;
1324 if (result
!= ISC_R_SUCCESS
) {
1325 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1326 "failed to get request's "
1328 isc_result_totext(result
));
1332 isc_netaddr_fromsockaddr(&destaddr
, &client
->interface
->addr
);
1336 * Find a view that matches the client's source address.
1338 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1340 view
= ISC_LIST_NEXT(view
, link
)) {
1341 if (client
->message
->rdclass
== view
->rdclass
||
1342 client
->message
->rdclass
== dns_rdataclass_any
)
1344 if (allowed(&netaddr
, view
->matchclients
) &&
1345 allowed(&destaddr
, view
->matchdestinations
) &&
1346 !((flags
& DNS_MESSAGEFLAG_RD
) == 0 &&
1347 view
->matchrecursiveonly
))
1349 dns_view_attach(view
, &client
->view
);
1356 char classname
[DNS_RDATACLASS_FORMATSIZE
];
1359 * Do a dummy TSIG verification attempt so that the
1360 * response will have a TSIG if the query did, as
1361 * required by RFC2845.
1365 r
= dns_message_getrawmessage(client
->message
);
1366 isc_buffer_init(&b
, r
->base
, r
->length
);
1367 isc_buffer_add(&b
, r
->length
);
1368 (void)dns_tsig_verify(&b
, client
->message
, NULL
, NULL
);
1370 dns_rdataclass_format(client
->message
->rdclass
, classname
,
1372 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1373 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1374 "no matching view in class '%s'", classname
);
1375 ns_client_dumpmessage(client
, "no matching view in class");
1376 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_REFUSED
);
1380 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1381 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(5),
1382 "using view '%s'", view
->name
);
1385 * Check for a signature. We log bad signatures regardless of
1386 * whether they ultimately cause the request to be rejected or
1387 * not. We do not log the lack of a signature unless we are
1390 sigresult
= dns_message_checksig(client
->message
, client
->view
);
1391 client
->signer
= NULL
;
1392 dns_name_init(&client
->signername
, NULL
);
1393 result
= dns_message_signer(client
->message
, &client
->signername
);
1394 if (result
== ISC_R_SUCCESS
) {
1395 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1396 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1397 "request has valid signature");
1398 client
->signer
= &client
->signername
;
1399 } else if (result
== ISC_R_NOTFOUND
) {
1400 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1401 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1402 "request is not signed");
1403 } else if (result
== DNS_R_NOIDENTITY
) {
1404 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1405 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1406 "request is signed by a nonauthoritative key");
1408 /* There is a signature, but it is bad. */
1409 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1410 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
1411 "request has invalid signature: %s",
1412 isc_result_totext(result
));
1414 * Accept update messages signed by unknown keys so that
1415 * update forwarding works transparently through slaves
1416 * that don't have all the same keys as the master.
1418 if (!(client
->message
->tsigstatus
== dns_tsigerror_badkey
&&
1419 client
->message
->opcode
== dns_opcode_update
)) {
1420 ns_client_error(client
, sigresult
);
1426 * Decide whether recursive service is available to this client.
1427 * We do this here rather than in the query code so that we can
1428 * set the RA bit correctly on all kinds of responses, not just
1429 * responses to ordinary queries.
1432 if (client
->view
->resolver
!= NULL
&&
1433 client
->view
->recursion
== ISC_TRUE
&&
1434 /* XXX this will log too much too early */
1435 ns_client_checkacl(client
, "recursion available:",
1436 client
->view
->recursionacl
,
1437 ISC_TRUE
, ISC_LOG_DEBUG(1)) == ISC_R_SUCCESS
)
1441 client
->attributes
|= NS_CLIENTATTR_RA
;
1444 * Dispatch the request.
1446 switch (client
->message
->opcode
) {
1447 case dns_opcode_query
:
1449 ns_query_start(client
);
1451 case dns_opcode_update
:
1453 ns_client_settimeout(client
, 60);
1454 ns_update_start(client
, sigresult
);
1456 case dns_opcode_notify
:
1458 ns_client_settimeout(client
, 60);
1459 ns_notify_start(client
);
1461 case dns_opcode_iquery
:
1463 ns_client_error(client
, DNS_R_NOTIMP
);
1466 CTRACE("unknown opcode");
1467 ns_client_error(client
, DNS_R_NOTIMP
);
1475 client_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1476 ns_client_t
*client
;
1478 REQUIRE(event
!= NULL
);
1479 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_LIFE
||
1480 event
->ev_type
== ISC_TIMEREVENT_IDLE
);
1481 client
= event
->ev_arg
;
1482 REQUIRE(NS_CLIENT_VALID(client
));
1483 REQUIRE(task
== client
->task
);
1484 REQUIRE(client
->timer
!= NULL
);
1490 isc_event_free(&event
);
1492 if (client
->shutdown
!= NULL
) {
1493 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_TIMEDOUT
);
1494 client
->shutdown
= NULL
;
1495 client
->shutdown_arg
= NULL
;
1498 if (client
->newstate
> NS_CLIENTSTATE_READY
)
1499 client
->newstate
= NS_CLIENTSTATE_READY
;
1500 (void) exit_check(client
);
1504 client_create(ns_clientmgr_t
*manager
, ns_client_t
**clientp
)
1506 ns_client_t
*client
;
1507 isc_result_t result
;
1510 * Caller must be holding the manager lock.
1512 * Note: creating a client does not add the client to the
1513 * manager's client list or set the client's manager pointer.
1514 * The caller is responsible for that.
1517 REQUIRE(clientp
!= NULL
&& *clientp
== NULL
);
1519 client
= isc_mem_get(manager
->mctx
, sizeof *client
);
1521 return (ISC_R_NOMEMORY
);
1523 client
->task
= NULL
;
1524 result
= isc_task_create(manager
->taskmgr
, 0, &client
->task
);
1525 if (result
!= ISC_R_SUCCESS
)
1526 goto cleanup_client
;
1527 isc_task_setname(client
->task
, "client", client
);
1529 client
->timer
= NULL
;
1530 result
= isc_timer_create(manager
->timermgr
, isc_timertype_inactive
,
1531 NULL
, NULL
, client
->task
, client_timeout
,
1532 client
, &client
->timer
);
1533 if (result
!= ISC_R_SUCCESS
)
1535 client
->timerset
= ISC_FALSE
;
1537 client
->message
= NULL
;
1538 result
= dns_message_create(manager
->mctx
, DNS_MESSAGE_INTENTPARSE
,
1540 if (result
!= ISC_R_SUCCESS
)
1543 /* XXXRTH Hardwired constants */
1545 client
->sendevent
= (isc_socketevent_t
*)
1546 isc_event_allocate(manager
->mctx
, client
,
1547 ISC_SOCKEVENT_SENDDONE
,
1548 client_senddone
, client
,
1549 sizeof(isc_socketevent_t
));
1550 if (client
->sendevent
== NULL
) {
1551 result
= ISC_R_NOMEMORY
;
1552 goto cleanup_message
;
1555 client
->recvbuf
= isc_mem_get(manager
->mctx
, RECV_BUFFER_SIZE
);
1556 if (client
->recvbuf
== NULL
) {
1557 result
= ISC_R_NOMEMORY
;
1558 goto cleanup_sendevent
;
1561 client
->recvevent
= (isc_socketevent_t
*)
1562 isc_event_allocate(manager
->mctx
, client
,
1563 ISC_SOCKEVENT_RECVDONE
,
1564 client_request
, client
,
1565 sizeof(isc_socketevent_t
));
1566 if (client
->recvevent
== NULL
) {
1567 result
= ISC_R_NOMEMORY
;
1568 goto cleanup_recvbuf
;
1571 client
->magic
= NS_CLIENT_MAGIC
;
1572 client
->mctx
= manager
->mctx
;
1573 client
->manager
= NULL
;
1574 client
->state
= NS_CLIENTSTATE_INACTIVE
;
1575 client
->newstate
= NS_CLIENTSTATE_MAX
;
1576 client
->naccepts
= 0;
1580 client
->nupdates
= 0;
1582 client
->references
= 0;
1583 client
->attributes
= 0;
1584 client
->view
= NULL
;
1585 client
->dispatch
= NULL
;
1586 client
->udpsocket
= NULL
;
1587 client
->tcplistener
= NULL
;
1588 client
->tcpsocket
= NULL
;
1589 client
->tcpmsg_valid
= ISC_FALSE
;
1590 client
->tcpbuf
= NULL
;
1592 client
->udpsize
= 512;
1593 client
->extflags
= 0;
1594 client
->next
= NULL
;
1595 client
->shutdown
= NULL
;
1596 client
->shutdown_arg
= NULL
;
1597 dns_name_init(&client
->signername
, NULL
);
1598 client
->mortal
= ISC_FALSE
;
1599 client
->tcpquota
= NULL
;
1600 client
->recursionquota
= NULL
;
1601 client
->interface
= NULL
;
1602 client
->peeraddr_valid
= ISC_FALSE
;
1603 ISC_EVENT_INIT(&client
->ctlevent
, sizeof(client
->ctlevent
), 0, NULL
,
1604 NS_EVENT_CLIENTCONTROL
, client_start
, client
, client
,
1607 * Initialize FORMERR cache to sentinel value that will not match
1608 * any actual FORMERR response.
1610 isc_sockaddr_any(&client
->formerrcache
.addr
);
1611 client
->formerrcache
.time
= 0;
1612 client
->formerrcache
.id
= 0;
1613 ISC_LINK_INIT(client
, link
);
1614 client
->list
= NULL
;
1617 * We call the init routines for the various kinds of client here,
1618 * after we have created an otherwise valid client, because some
1619 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
1621 result
= ns_query_init(client
);
1622 if (result
!= ISC_R_SUCCESS
)
1623 goto cleanup_recvevent
;
1625 result
= isc_task_onshutdown(client
->task
, client_shutdown
, client
);
1626 if (result
!= ISC_R_SUCCESS
)
1633 return (ISC_R_SUCCESS
);
1636 ns_query_free(client
);
1639 isc_event_free((isc_event_t
**)&client
->recvevent
);
1642 isc_mem_put(manager
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
1645 isc_event_free((isc_event_t
**)&client
->sendevent
);
1650 dns_message_destroy(&client
->message
);
1653 isc_timer_detach(&client
->timer
);
1656 isc_task_detach(&client
->task
);
1659 isc_mem_put(manager
->mctx
, client
, sizeof *client
);
1665 client_read(ns_client_t
*client
) {
1666 isc_result_t result
;
1670 result
= dns_tcpmsg_readmessage(&client
->tcpmsg
, client
->task
,
1671 client_request
, client
);
1672 if (result
!= ISC_R_SUCCESS
)
1676 * Set a timeout to limit the amount of time we will wait
1677 * for a request on this TCP connection.
1679 ns_client_settimeout(client
, 30);
1681 client
->state
= client
->newstate
= NS_CLIENTSTATE_READING
;
1682 INSIST(client
->nreads
== 0);
1683 INSIST(client
->recursionquota
== NULL
);
1688 ns_client_next(client
, result
);
1692 client_newconn(isc_task_t
*task
, isc_event_t
*event
) {
1693 ns_client_t
*client
= event
->ev_arg
;
1694 isc_socket_newconnev_t
*nevent
= (isc_socket_newconnev_t
*)event
;
1695 isc_result_t result
;
1697 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_NEWCONN
);
1698 REQUIRE(NS_CLIENT_VALID(client
));
1699 REQUIRE(client
->task
== task
);
1703 INSIST(client
->state
== NS_CLIENTSTATE_READY
);
1705 INSIST(client
->naccepts
== 1);
1708 LOCK(&client
->interface
->lock
);
1709 INSIST(client
->interface
->ntcpcurrent
> 0);
1710 client
->interface
->ntcpcurrent
--;
1711 UNLOCK(&client
->interface
->lock
);
1714 * We must take ownership of the new socket before the exit
1715 * check to make sure it gets destroyed if we decide to exit.
1717 if (nevent
->result
== ISC_R_SUCCESS
) {
1718 client
->tcpsocket
= nevent
->newsocket
;
1719 client
->state
= NS_CLIENTSTATE_READING
;
1720 INSIST(client
->recursionquota
== NULL
);
1722 (void) isc_socket_getpeername(client
->tcpsocket
,
1724 client
->peeraddr_valid
= ISC_TRUE
;
1725 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1726 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1727 "new TCP connection");
1730 * XXXRTH What should we do? We're trying to accept but
1731 * it didn't work. If we just give up, then TCP
1732 * service may eventually stop.
1734 * For now, we just go idle.
1736 * Going idle is probably the right thing if the
1739 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1740 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1741 "accept failed: %s",
1742 isc_result_totext(nevent
->result
));
1745 if (exit_check(client
))
1748 if (nevent
->result
== ISC_R_SUCCESS
) {
1750 isc_netaddr_t netaddr
;
1752 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1754 if (ns_g_server
->blackholeacl
!= NULL
&&
1755 dns_acl_match(&netaddr
, NULL
,
1756 ns_g_server
->blackholeacl
,
1757 &ns_g_server
->aclenv
,
1758 &match
, NULL
) == ISC_R_SUCCESS
&&
1761 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1762 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1763 "blackholed connection attempt");
1764 client
->newstate
= NS_CLIENTSTATE_READY
;
1765 (void)exit_check(client
);
1769 INSIST(client
->tcpmsg_valid
== ISC_FALSE
);
1770 dns_tcpmsg_init(client
->mctx
, client
->tcpsocket
,
1772 client
->tcpmsg_valid
= ISC_TRUE
;
1775 * Let a new client take our place immediately, before
1776 * we wait for a request packet. If we don't,
1777 * telnetting to port 53 (once per CPU) will
1778 * deny service to legititmate TCP clients.
1780 result
= isc_quota_attach(&ns_g_server
->tcpquota
,
1782 if (result
== ISC_R_SUCCESS
)
1783 result
= ns_client_replace(client
);
1784 if (result
!= ISC_R_SUCCESS
) {
1785 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1786 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
1787 "no more TCP clients: %s",
1788 isc_result_totext(result
));
1791 client_read(client
);
1795 isc_event_free(&event
);
1799 client_accept(ns_client_t
*client
) {
1800 isc_result_t result
;
1804 result
= isc_socket_accept(client
->tcplistener
, client
->task
,
1805 client_newconn
, client
);
1806 if (result
!= ISC_R_SUCCESS
) {
1807 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1808 "isc_socket_accept() failed: %s",
1809 isc_result_totext(result
));
1811 * XXXRTH What should we do? We're trying to accept but
1812 * it didn't work. If we just give up, then TCP
1813 * service may eventually stop.
1815 * For now, we just go idle.
1819 INSIST(client
->naccepts
== 0);
1821 LOCK(&client
->interface
->lock
);
1822 client
->interface
->ntcpcurrent
++;
1823 UNLOCK(&client
->interface
->lock
);
1827 client_udprecv(ns_client_t
*client
) {
1828 isc_result_t result
;
1833 r
.base
= client
->recvbuf
;
1834 r
.length
= RECV_BUFFER_SIZE
;
1835 result
= isc_socket_recv2(client
->udpsocket
, &r
, 1,
1836 client
->task
, client
->recvevent
, 0);
1837 if (result
!= ISC_R_SUCCESS
) {
1838 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1839 "isc_socket_recv() failed: %s",
1840 isc_result_totext(result
));
1842 * This cannot happen in the current implementation, since
1843 * isc_socket_recv2() cannot fail if flags == 0A
1845 * If this does fail, we just go idle.
1849 INSIST(client
->nrecvs
== 0);
1854 ns_client_attach(ns_client_t
*source
, ns_client_t
**targetp
) {
1855 REQUIRE(NS_CLIENT_VALID(source
));
1856 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
1858 source
->references
++;
1859 ns_client_log(source
, NS_LOGCATEGORY_CLIENT
,
1860 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1861 "ns_client_attach: ref = %d", source
->references
);
1866 ns_client_detach(ns_client_t
**clientp
) {
1867 ns_client_t
*client
= *clientp
;
1869 client
->references
--;
1870 INSIST(client
->references
>= 0);
1872 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1873 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1874 "ns_client_detach: ref = %d", client
->references
);
1875 (void) exit_check(client
);
1879 ns_client_shuttingdown(ns_client_t
*client
) {
1880 return (ISC_TF(client
->newstate
== NS_CLIENTSTATE_FREED
));
1884 ns_client_replace(ns_client_t
*client
) {
1885 isc_result_t result
;
1889 result
= ns_clientmgr_createclients(client
->manager
,
1890 1, client
->interface
,
1891 (TCP_CLIENT(client
) ?
1892 ISC_TRUE
: ISC_FALSE
));
1893 if (result
!= ISC_R_SUCCESS
)
1897 * The responsibility for listening for new requests is hereby
1898 * transferred to the new client. Therefore, the old client
1899 * should refrain from listening for any more requests.
1901 client
->mortal
= ISC_TRUE
;
1903 return (ISC_R_SUCCESS
);
1911 clientmgr_destroy(ns_clientmgr_t
*manager
) {
1912 REQUIRE(ISC_LIST_EMPTY(manager
->active
));
1913 REQUIRE(ISC_LIST_EMPTY(manager
->inactive
));
1915 MTRACE("clientmgr_destroy");
1917 DESTROYLOCK(&manager
->lock
);
1919 isc_mem_put(manager
->mctx
, manager
, sizeof *manager
);
1923 ns_clientmgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
1924 isc_timermgr_t
*timermgr
, ns_clientmgr_t
**managerp
)
1926 ns_clientmgr_t
*manager
;
1927 isc_result_t result
;
1929 manager
= isc_mem_get(mctx
, sizeof *manager
);
1930 if (manager
== NULL
)
1931 return (ISC_R_NOMEMORY
);
1933 result
= isc_mutex_init(&manager
->lock
);
1934 if (result
!= ISC_R_SUCCESS
)
1935 goto cleanup_manager
;
1937 manager
->mctx
= mctx
;
1938 manager
->taskmgr
= taskmgr
;
1939 manager
->timermgr
= timermgr
;
1940 manager
->exiting
= ISC_FALSE
;
1941 ISC_LIST_INIT(manager
->active
);
1942 ISC_LIST_INIT(manager
->inactive
);
1943 manager
->magic
= MANAGER_MAGIC
;
1947 *managerp
= manager
;
1949 return (ISC_R_SUCCESS
);
1952 isc_mem_put(manager
->mctx
, manager
, sizeof *manager
);
1958 ns_clientmgr_destroy(ns_clientmgr_t
**managerp
) {
1959 ns_clientmgr_t
*manager
;
1960 ns_client_t
*client
;
1961 isc_boolean_t need_destroy
= ISC_FALSE
;
1963 REQUIRE(managerp
!= NULL
);
1964 manager
= *managerp
;
1965 REQUIRE(VALID_MANAGER(manager
));
1969 LOCK(&manager
->lock
);
1971 manager
->exiting
= ISC_TRUE
;
1973 for (client
= ISC_LIST_HEAD(manager
->active
);
1975 client
= ISC_LIST_NEXT(client
, link
))
1976 isc_task_shutdown(client
->task
);
1978 for (client
= ISC_LIST_HEAD(manager
->inactive
);
1980 client
= ISC_LIST_NEXT(client
, link
))
1981 isc_task_shutdown(client
->task
);
1983 if (ISC_LIST_EMPTY(manager
->active
) &&
1984 ISC_LIST_EMPTY(manager
->inactive
))
1985 need_destroy
= ISC_TRUE
;
1987 UNLOCK(&manager
->lock
);
1990 clientmgr_destroy(manager
);
1996 ns_clientmgr_createclients(ns_clientmgr_t
*manager
, unsigned int n
,
1997 ns_interface_t
*ifp
, isc_boolean_t tcp
)
1999 isc_result_t result
= ISC_R_SUCCESS
;
2001 ns_client_t
*client
;
2003 REQUIRE(VALID_MANAGER(manager
));
2006 MTRACE("createclients");
2009 * We MUST lock the manager lock for the entire client creation
2010 * process. If we didn't do this, then a client could get a
2011 * shutdown event and disappear out from under us.
2014 LOCK(&manager
->lock
);
2016 for (i
= 0; i
< n
; i
++) {
2019 * Allocate a client. First try to get a recycled one;
2020 * if that fails, make a new one.
2022 client
= ISC_LIST_HEAD(manager
->inactive
);
2023 if (client
!= NULL
) {
2025 ISC_LIST_UNLINK(manager
->inactive
, client
, link
);
2026 client
->list
= NULL
;
2028 MTRACE("create new");
2029 result
= client_create(manager
, &client
);
2030 if (result
!= ISC_R_SUCCESS
)
2034 ns_interface_attach(ifp
, &client
->interface
);
2035 client
->state
= NS_CLIENTSTATE_READY
;
2036 INSIST(client
->recursionquota
== NULL
);
2039 client
->attributes
|= NS_CLIENTATTR_TCP
;
2040 isc_socket_attach(ifp
->tcpsocket
,
2041 &client
->tcplistener
);
2045 dns_dispatch_attach(ifp
->udpdispatch
,
2047 sock
= dns_dispatch_getsocket(client
->dispatch
);
2048 isc_socket_attach(sock
, &client
->udpsocket
);
2050 client
->manager
= manager
;
2051 ISC_LIST_APPEND(manager
->active
, client
, link
);
2052 client
->list
= &manager
->active
;
2054 INSIST(client
->nctls
== 0);
2056 ev
= &client
->ctlevent
;
2057 isc_task_send(client
->task
, &ev
);
2061 * We managed to create at least one client, so we
2064 result
= ISC_R_SUCCESS
;
2067 UNLOCK(&manager
->lock
);
2073 ns_client_getsockaddr(ns_client_t
*client
) {
2074 return (&client
->peeraddr
);
2078 ns_client_checkaclsilent(ns_client_t
*client
, dns_acl_t
*acl
,
2079 isc_boolean_t default_allow
)
2081 isc_result_t result
;
2083 isc_netaddr_t netaddr
;
2092 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2094 result
= dns_acl_match(&netaddr
, client
->signer
, acl
,
2095 &ns_g_server
->aclenv
,
2097 if (result
!= ISC_R_SUCCESS
)
2098 goto deny
; /* Internal error, already logged. */
2101 goto deny
; /* Negative match or no match. */
2104 return (ISC_R_SUCCESS
);
2107 return (DNS_R_REFUSED
);
2111 ns_client_checkacl(ns_client_t
*client
,
2112 const char *opname
, dns_acl_t
*acl
,
2113 isc_boolean_t default_allow
, int log_level
)
2115 isc_result_t result
=
2116 ns_client_checkaclsilent(client
, acl
, default_allow
);
2118 if (result
== ISC_R_SUCCESS
)
2119 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2120 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2121 "%s approved", opname
);
2123 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2124 NS_LOGMODULE_CLIENT
,
2125 log_level
, "%s denied", opname
);
2130 ns_client_name(ns_client_t
*client
, char *peerbuf
, size_t len
) {
2131 if (client
->peeraddr_valid
)
2132 isc_sockaddr_format(&client
->peeraddr
, peerbuf
, len
);
2134 snprintf(peerbuf
, len
, "@%p", client
);
2138 ns_client_logv(ns_client_t
*client
, isc_logcategory_t
*category
,
2139 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
2140 ISC_FORMAT_PRINTF(5, 0);
2143 ns_client_logv(ns_client_t
*client
, isc_logcategory_t
*category
,
2144 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
2147 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2149 vsnprintf(msgbuf
, sizeof(msgbuf
), fmt
, ap
);
2150 ns_client_name(client
, peerbuf
, sizeof peerbuf
);
2152 isc_log_write(ns_g_lctx
, category
, module
, level
,
2153 "client %s: %s", peerbuf
, msgbuf
);
2157 ns_client_log(ns_client_t
*client
, isc_logcategory_t
*category
,
2158 isc_logmodule_t
*module
, int level
, const char *fmt
, ...)
2162 if (! isc_log_wouldlog(ns_g_lctx
, level
))
2166 ns_client_logv(client
, category
, module
, level
, fmt
, ap
);
2171 ns_client_aclmsg(const char *msg
, dns_name_t
*name
, dns_rdataclass_t rdclass
,
2172 char *buf
, size_t len
)
2174 char namebuf
[DNS_NAME_FORMATSIZE
];
2175 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
2177 dns_name_format(name
, namebuf
, sizeof(namebuf
));
2178 dns_rdataclass_format(rdclass
, classbuf
, sizeof(classbuf
));
2179 (void)snprintf(buf
, len
, "%s '%s/%s'", msg
, namebuf
, classbuf
);
2183 ns_client_dumpmessage(ns_client_t
*client
, const char *reason
) {
2184 isc_buffer_t buffer
;
2187 isc_result_t result
;
2190 * Note that these are multiline debug messages. We want a newline
2191 * to appear in the log after each message.
2195 buf
= isc_mem_get(client
->mctx
, len
);
2198 isc_buffer_init(&buffer
, buf
, len
);
2199 result
= dns_message_totext(client
->message
,
2200 &dns_master_style_debug
,
2202 if (result
== ISC_R_NOSPACE
) {
2203 isc_mem_put(client
->mctx
, buf
, len
);
2205 } else if (result
== ISC_R_SUCCESS
)
2206 ns_client_log(client
, NS_LOGCATEGORY_UNMATCHED
,
2207 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
2209 (int)isc_buffer_usedlength(&buffer
),
2211 } while (result
== ISC_R_NOSPACE
);
2214 isc_mem_put(client
->mctx
, buf
, len
);