2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
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.250.16.10 2009/01/29 22:41:43 jinmei Exp $ */
22 #include <isc/formatcheck.h>
23 #include <isc/mutex.h>
25 #include <isc/platform.h>
26 #include <isc/print.h>
27 #include <isc/stats.h>
28 #include <isc/stdio.h>
29 #include <isc/string.h>
31 #include <isc/timer.h>
35 #include <dns/dispatch.h>
36 #include <dns/events.h>
37 #include <dns/message.h>
39 #include <dns/rcode.h>
40 #include <dns/rdata.h>
41 #include <dns/rdataclass.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/resolver.h>
45 #include <dns/stats.h>
50 #include <named/interfacemgr.h>
51 #include <named/log.h>
52 #include <named/notify.h>
54 #include <named/server.h>
55 #include <named/update.h>
66 * All client state changes, other than that from idle to listening, occur
67 * as a result of events. This guarantees serialization and avoids the
70 * If a routine is ever created that allows someone other than the client's
71 * task to change the client, then the client will have to be locked.
74 #define NS_CLIENT_TRACE
75 #ifdef NS_CLIENT_TRACE
76 #define CTRACE(m) ns_client_log(client, \
77 NS_LOGCATEGORY_CLIENT, \
78 NS_LOGMODULE_CLIENT, \
81 #define MTRACE(m) isc_log_write(ns_g_lctx, \
82 NS_LOGCATEGORY_GENERAL, \
83 NS_LOGMODULE_CLIENT, \
85 "clientmgr @%p: %s", manager, (m))
87 #define CTRACE(m) ((void)(m))
88 #define MTRACE(m) ((void)(m))
91 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
93 #define TCP_BUFFER_SIZE (65535 + 2)
94 #define SEND_BUFFER_SIZE 4096
95 #define RECV_BUFFER_SIZE 4096
97 #ifdef ISC_PLATFORM_USETHREADS
100 * Number of 'mctx pools' for clients. (Should this be configurable?)
101 * When enabling threads, we use a pool of memory contexts shared by
102 * client objects, since concurrent access to a shared context would cause
103 * heavy contentions. The above constant is expected to be enough for
104 * completely avoiding contentions among threads for an authoritative-only
110 * If named with built without thread, simply share manager's context. Using
111 * a separate context in this case would simply waste memory.
115 /*% nameserver client manager structure */
116 struct ns_clientmgr
{
120 isc_taskmgr_t
* taskmgr
;
121 isc_timermgr_t
* timermgr
;
123 /* Locked by lock. */
124 isc_boolean_t exiting
;
125 client_list_t active
; /*%< Active clients */
126 client_list_t recursing
; /*%< Recursing clients */
127 client_list_t inactive
; /*%< To be recycled */
129 /*%< mctx pool for clients. */
130 unsigned int nextmctx
;
131 isc_mem_t
* mctxpool
[NMCTXS
];
135 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
136 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
139 * Client object states. Ordering is significant: higher-numbered
140 * states are generally "more active", meaning that the client can
141 * have more dynamically allocated data, outstanding events, etc.
142 * In the list below, any such properties listed for state N
143 * also apply to any state > N.
145 * To force the client into a less active state, set client->newstate
146 * to that state and call exit_check(). This will cause any
147 * activities defined for higher-numbered states to be aborted.
150 #define NS_CLIENTSTATE_FREED 0
152 * The client object no longer exists.
155 #define NS_CLIENTSTATE_INACTIVE 1
157 * The client object exists and has a task and timer.
158 * Its "query" struct and sendbuf are initialized.
159 * It is on the client manager's list of inactive clients.
160 * It has a message and OPT, both in the reset state.
163 #define NS_CLIENTSTATE_READY 2
165 * The client object is either a TCP or a UDP one, and
166 * it is associated with a network interface. It is on the
167 * client manager's list of active clients.
169 * If it is a TCP client object, it has a TCP listener socket
170 * and an outstanding TCP listen request.
172 * If it is a UDP client object, it has a UDP listener socket
173 * and an outstanding UDP receive request.
176 #define NS_CLIENTSTATE_READING 3
178 * The client object is a TCP client object that has received
179 * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
180 * outstanding TCP read request. This state is not used for
181 * UDP client objects.
184 #define NS_CLIENTSTATE_WORKING 4
186 * The client object has received a request and is working
187 * on it. It has a view, and it may have any of a non-reset OPT,
188 * recursion quota, and an outstanding write request.
191 #define NS_CLIENTSTATE_MAX 9
193 * Sentinel value used to indicate "no state". When client->newstate
194 * has this value, we are not attempting to exit the current state.
195 * Must be greater than any valid state.
199 * Enable ns_client_dropport() by default.
201 #ifndef NS_CLIENT_DROPPORT
202 #define NS_CLIENT_DROPPORT 1
205 unsigned int ns_client_requests
;
207 static void client_read(ns_client_t
*client
);
208 static void client_accept(ns_client_t
*client
);
209 static void client_udprecv(ns_client_t
*client
);
210 static void clientmgr_destroy(ns_clientmgr_t
*manager
);
211 static isc_boolean_t
exit_check(ns_client_t
*client
);
212 static void ns_client_endrequest(ns_client_t
*client
);
213 static void ns_client_checkactive(ns_client_t
*client
);
214 static void client_start(isc_task_t
*task
, isc_event_t
*event
);
215 static void client_request(isc_task_t
*task
, isc_event_t
*event
);
216 static void ns_client_dumpmessage(ns_client_t
*client
, const char *reason
);
219 ns_client_recursing(ns_client_t
*client
) {
220 REQUIRE(NS_CLIENT_VALID(client
));
222 LOCK(&client
->manager
->lock
);
223 ISC_LIST_UNLINK(*client
->list
, client
, link
);
224 ISC_LIST_APPEND(client
->manager
->recursing
, client
, link
);
225 client
->list
= &client
->manager
->recursing
;
226 UNLOCK(&client
->manager
->lock
);
230 ns_client_killoldestquery(ns_client_t
*client
) {
232 REQUIRE(NS_CLIENT_VALID(client
));
234 LOCK(&client
->manager
->lock
);
235 oldest
= ISC_LIST_HEAD(client
->manager
->recursing
);
236 if (oldest
!= NULL
) {
237 ns_query_cancel(oldest
);
238 ISC_LIST_UNLINK(*oldest
->list
, oldest
, link
);
239 ISC_LIST_APPEND(client
->manager
->active
, oldest
, link
);
240 oldest
->list
= &client
->manager
->active
;
242 UNLOCK(&client
->manager
->lock
);
246 ns_client_settimeout(ns_client_t
*client
, unsigned int seconds
) {
248 isc_interval_t interval
;
250 isc_interval_set(&interval
, seconds
, 0);
251 result
= isc_timer_reset(client
->timer
, isc_timertype_once
, NULL
,
252 &interval
, ISC_FALSE
);
253 client
->timerset
= ISC_TRUE
;
254 if (result
!= ISC_R_SUCCESS
) {
255 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
256 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
257 "setting timeout: %s",
258 isc_result_totext(result
));
259 /* Continue anyway. */
264 * Check for a deactivation or shutdown request and take appropriate
265 * action. Returns ISC_TRUE if either is in progress; in this case
266 * the caller must no longer use the client object as it may have been
270 exit_check(ns_client_t
*client
) {
271 ns_clientmgr_t
*locked_manager
= NULL
;
272 ns_clientmgr_t
*destroy_manager
= NULL
;
274 REQUIRE(NS_CLIENT_VALID(client
));
276 if (client
->state
<= client
->newstate
)
277 return (ISC_FALSE
); /* Business as usual. */
279 INSIST(client
->newstate
< NS_CLIENTSTATE_WORKING
);
282 * We need to detach from the view early when shutting down
283 * the server to break the following vicious circle:
285 * - The resolver will not shut down until the view refcount is zero
286 * - The view refcount does not go to zero until all clients detach
287 * - The client does not detach from the view until references is zero
288 * - references does not go to zero until the resolver has shut down
290 * Keep the view attached until any outstanding updates complete.
292 if (client
->nupdates
== 0 &&
293 client
->newstate
== NS_CLIENTSTATE_FREED
&& client
->view
!= NULL
)
294 dns_view_detach(&client
->view
);
296 if (client
->state
== NS_CLIENTSTATE_WORKING
) {
297 INSIST(client
->newstate
<= NS_CLIENTSTATE_READING
);
299 * Let the update processing complete.
301 if (client
->nupdates
> 0)
304 * We are trying to abort request processing.
306 if (client
->nsends
> 0) {
307 isc_socket_t
*socket
;
308 if (TCP_CLIENT(client
))
309 socket
= client
->tcpsocket
;
311 socket
= client
->udpsocket
;
312 isc_socket_cancel(socket
, client
->task
,
313 ISC_SOCKCANCEL_SEND
);
316 if (! (client
->nsends
== 0 && client
->nrecvs
== 0 &&
317 client
->references
== 0))
320 * Still waiting for I/O cancel completion.
321 * or lingering references.
326 * I/O cancel is complete. Burn down all state
327 * related to the current request. Ensure that
328 * the client is on the active list and not the
331 LOCK(&client
->manager
->lock
);
332 if (client
->list
== &client
->manager
->recursing
) {
333 ISC_LIST_UNLINK(*client
->list
, client
, link
);
334 ISC_LIST_APPEND(client
->manager
->active
, client
, link
);
335 client
->list
= &client
->manager
->active
;
337 UNLOCK(&client
->manager
->lock
);
338 ns_client_endrequest(client
);
340 client
->state
= NS_CLIENTSTATE_READING
;
341 INSIST(client
->recursionquota
== NULL
);
342 if (NS_CLIENTSTATE_READING
== client
->newstate
) {
344 client
->newstate
= NS_CLIENTSTATE_MAX
;
345 return (ISC_TRUE
); /* We're done. */
349 if (client
->state
== NS_CLIENTSTATE_READING
) {
351 * We are trying to abort the current TCP connection,
354 INSIST(client
->recursionquota
== NULL
);
355 INSIST(client
->newstate
<= NS_CLIENTSTATE_READY
);
356 if (client
->nreads
> 0)
357 dns_tcpmsg_cancelread(&client
->tcpmsg
);
358 if (! client
->nreads
== 0) {
359 /* Still waiting for read cancel completion. */
363 if (client
->tcpmsg_valid
) {
364 dns_tcpmsg_invalidate(&client
->tcpmsg
);
365 client
->tcpmsg_valid
= ISC_FALSE
;
367 if (client
->tcpsocket
!= NULL
) {
369 isc_socket_detach(&client
->tcpsocket
);
372 if (client
->tcpquota
!= NULL
)
373 isc_quota_detach(&client
->tcpquota
);
375 if (client
->timerset
) {
376 (void)isc_timer_reset(client
->timer
,
377 isc_timertype_inactive
,
378 NULL
, NULL
, ISC_TRUE
);
379 client
->timerset
= ISC_FALSE
;
382 client
->peeraddr_valid
= ISC_FALSE
;
384 client
->state
= NS_CLIENTSTATE_READY
;
385 INSIST(client
->recursionquota
== NULL
);
388 * Now the client is ready to accept a new TCP connection
389 * or UDP request, but we may have enough clients doing
390 * that already. Check whether this client needs to remain
391 * active and force it to go inactive if not.
393 ns_client_checkactive(client
);
395 if (NS_CLIENTSTATE_READY
== client
->newstate
) {
396 if (TCP_CLIENT(client
)) {
397 client_accept(client
);
399 client_udprecv(client
);
400 client
->newstate
= NS_CLIENTSTATE_MAX
;
405 if (client
->state
== NS_CLIENTSTATE_READY
) {
406 INSIST(client
->newstate
<= NS_CLIENTSTATE_INACTIVE
);
408 * We are trying to enter the inactive state.
410 if (client
->naccepts
> 0)
411 isc_socket_cancel(client
->tcplistener
, client
->task
,
412 ISC_SOCKCANCEL_ACCEPT
);
414 if (! (client
->naccepts
== 0)) {
415 /* Still waiting for accept cancel completion. */
418 /* Accept cancel is complete. */
420 if (client
->nrecvs
> 0)
421 isc_socket_cancel(client
->udpsocket
, client
->task
,
422 ISC_SOCKCANCEL_RECV
);
423 if (! (client
->nrecvs
== 0)) {
424 /* Still waiting for recv cancel completion. */
427 /* Recv cancel is complete. */
429 if (client
->nctls
> 0) {
430 /* Still waiting for control event to be delivered */
434 /* Deactivate the client. */
435 if (client
->interface
)
436 ns_interface_detach(&client
->interface
);
438 INSIST(client
->naccepts
== 0);
439 INSIST(client
->recursionquota
== NULL
);
440 if (client
->tcplistener
!= NULL
)
441 isc_socket_detach(&client
->tcplistener
);
443 if (client
->udpsocket
!= NULL
)
444 isc_socket_detach(&client
->udpsocket
);
446 if (client
->dispatch
!= NULL
)
447 dns_dispatch_detach(&client
->dispatch
);
449 client
->attributes
= 0;
450 client
->mortal
= ISC_FALSE
;
452 LOCK(&client
->manager
->lock
);
454 * Put the client on the inactive list. If we are aiming for
455 * the "freed" state, it will be removed from the inactive
456 * list shortly, and we need to keep the manager locked until
457 * that has been done, lest the manager decide to reactivate
458 * the dying client inbetween.
460 locked_manager
= client
->manager
;
461 ISC_LIST_UNLINK(*client
->list
, client
, link
);
462 ISC_LIST_APPEND(client
->manager
->inactive
, client
, link
);
463 client
->list
= &client
->manager
->inactive
;
464 client
->state
= NS_CLIENTSTATE_INACTIVE
;
465 INSIST(client
->recursionquota
== NULL
);
467 if (client
->state
== client
->newstate
) {
468 client
->newstate
= NS_CLIENTSTATE_MAX
;
473 if (client
->state
== NS_CLIENTSTATE_INACTIVE
) {
474 INSIST(client
->newstate
== NS_CLIENTSTATE_FREED
);
476 * We are trying to free the client.
478 * When "shuttingdown" is true, either the task has received
479 * its shutdown event or no shutdown event has ever been
480 * set up. Thus, we have no outstanding shutdown
481 * event at this point.
483 REQUIRE(client
->state
== NS_CLIENTSTATE_INACTIVE
);
485 INSIST(client
->recursionquota
== NULL
);
487 ns_query_free(client
);
488 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
489 isc_event_free((isc_event_t
**)&client
->sendevent
);
490 isc_event_free((isc_event_t
**)&client
->recvevent
);
491 isc_timer_detach(&client
->timer
);
493 if (client
->tcpbuf
!= NULL
)
494 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
495 if (client
->opt
!= NULL
) {
496 INSIST(dns_rdataset_isassociated(client
->opt
));
497 dns_rdataset_disassociate(client
->opt
);
498 dns_message_puttemprdataset(client
->message
, &client
->opt
);
500 dns_message_destroy(&client
->message
);
501 if (client
->manager
!= NULL
) {
502 ns_clientmgr_t
*manager
= client
->manager
;
503 if (locked_manager
== NULL
) {
504 LOCK(&manager
->lock
);
505 locked_manager
= manager
;
507 ISC_LIST_UNLINK(*client
->list
, client
, link
);
509 if (manager
->exiting
&&
510 ISC_LIST_EMPTY(manager
->active
) &&
511 ISC_LIST_EMPTY(manager
->inactive
) &&
512 ISC_LIST_EMPTY(manager
->recursing
))
513 destroy_manager
= manager
;
516 * Detaching the task must be done after unlinking from
517 * the manager's lists because the manager accesses
520 if (client
->task
!= NULL
)
521 isc_task_detach(&client
->task
);
525 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
531 if (locked_manager
!= NULL
) {
532 UNLOCK(&locked_manager
->lock
);
533 locked_manager
= NULL
;
537 * Only now is it safe to destroy the client manager (if needed),
538 * because we have accessed its lock for the last time.
540 if (destroy_manager
!= NULL
)
541 clientmgr_destroy(destroy_manager
);
547 * The client's task has received the client's control event
548 * as part of the startup process.
551 client_start(isc_task_t
*task
, isc_event_t
*event
) {
552 ns_client_t
*client
= (ns_client_t
*) event
->ev_arg
;
554 INSIST(task
== client
->task
);
558 INSIST(client
->nctls
== 1);
561 if (exit_check(client
))
564 if (TCP_CLIENT(client
)) {
565 client_accept(client
);
567 client_udprecv(client
);
573 * The client's task has received a shutdown event.
576 client_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
579 REQUIRE(event
!= NULL
);
580 REQUIRE(event
->ev_type
== ISC_TASKEVENT_SHUTDOWN
);
581 client
= event
->ev_arg
;
582 REQUIRE(NS_CLIENT_VALID(client
));
583 REQUIRE(task
== client
->task
);
589 isc_event_free(&event
);
591 if (client
->shutdown
!= NULL
) {
592 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_SHUTTINGDOWN
);
593 client
->shutdown
= NULL
;
594 client
->shutdown_arg
= NULL
;
597 client
->newstate
= NS_CLIENTSTATE_FREED
;
598 (void)exit_check(client
);
602 ns_client_endrequest(ns_client_t
*client
) {
603 INSIST(client
->naccepts
== 0);
604 INSIST(client
->nreads
== 0);
605 INSIST(client
->nsends
== 0);
606 INSIST(client
->nrecvs
== 0);
607 INSIST(client
->nupdates
== 0);
608 INSIST(client
->state
== NS_CLIENTSTATE_WORKING
);
610 CTRACE("endrequest");
612 if (client
->next
!= NULL
) {
613 (client
->next
)(client
);
617 if (client
->view
!= NULL
)
618 dns_view_detach(&client
->view
);
619 if (client
->opt
!= NULL
) {
620 INSIST(dns_rdataset_isassociated(client
->opt
));
621 dns_rdataset_disassociate(client
->opt
);
622 dns_message_puttemprdataset(client
->message
, &client
->opt
);
625 client
->udpsize
= 512;
626 client
->extflags
= 0;
627 client
->ednsversion
= -1;
628 dns_message_reset(client
->message
, DNS_MESSAGE_INTENTPARSE
);
630 if (client
->recursionquota
!= NULL
)
631 isc_quota_detach(&client
->recursionquota
);
634 * Clear all client attributes that are specific to
635 * the request; that's all except the TCP flag.
637 client
->attributes
&= NS_CLIENTATTR_TCP
;
641 ns_client_checkactive(ns_client_t
*client
) {
642 if (client
->mortal
) {
644 * This client object should normally go inactive
645 * at this point, but if we have fewer active client
646 * objects than desired due to earlier quota exhaustion,
647 * keep it active to make up for the shortage.
649 isc_boolean_t need_another_client
= ISC_FALSE
;
650 if (TCP_CLIENT(client
)) {
651 LOCK(&client
->interface
->lock
);
652 if (client
->interface
->ntcpcurrent
<
653 client
->interface
->ntcptarget
)
654 need_another_client
= ISC_TRUE
;
655 UNLOCK(&client
->interface
->lock
);
658 * The UDP client quota is enforced by making
659 * requests fail rather than by not listening
660 * for new ones. Therefore, there is always a
661 * full set of UDP clients listening.
664 if (! need_another_client
) {
666 * We don't need this client object. Recycle it.
668 if (client
->newstate
>= NS_CLIENTSTATE_INACTIVE
)
669 client
->newstate
= NS_CLIENTSTATE_INACTIVE
;
675 ns_client_next(ns_client_t
*client
, isc_result_t result
) {
678 REQUIRE(NS_CLIENT_VALID(client
));
679 REQUIRE(client
->state
== NS_CLIENTSTATE_WORKING
||
680 client
->state
== NS_CLIENTSTATE_READING
);
684 if (result
!= ISC_R_SUCCESS
)
685 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
686 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
687 "request failed: %s", isc_result_totext(result
));
690 * An error processing a TCP request may have left
691 * the connection out of sync. To be safe, we always
692 * sever the connection when result != ISC_R_SUCCESS.
694 if (result
== ISC_R_SUCCESS
&& TCP_CLIENT(client
))
695 newstate
= NS_CLIENTSTATE_READING
;
697 newstate
= NS_CLIENTSTATE_READY
;
699 if (client
->newstate
> newstate
)
700 client
->newstate
= newstate
;
701 (void)exit_check(client
);
706 client_senddone(isc_task_t
*task
, isc_event_t
*event
) {
708 isc_socketevent_t
*sevent
= (isc_socketevent_t
*) event
;
710 REQUIRE(sevent
!= NULL
);
711 REQUIRE(sevent
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
712 client
= sevent
->ev_arg
;
713 REQUIRE(NS_CLIENT_VALID(client
));
714 REQUIRE(task
== client
->task
);
715 REQUIRE(sevent
== client
->sendevent
);
721 if (sevent
->result
!= ISC_R_SUCCESS
)
722 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
723 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
724 "error sending response: %s",
725 isc_result_totext(sevent
->result
));
727 INSIST(client
->nsends
> 0);
730 if (client
->tcpbuf
!= NULL
) {
731 INSIST(TCP_CLIENT(client
));
732 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
733 client
->tcpbuf
= NULL
;
736 if (exit_check(client
))
739 ns_client_next(client
, ISC_R_SUCCESS
);
743 * We only want to fail with ISC_R_NOSPACE when called from
744 * ns_client_sendraw() and not when called from ns_client_send(),
745 * tcpbuffer is NULL when called from ns_client_sendraw() and
746 * length != 0. tcpbuffer != NULL when called from ns_client_send()
751 client_allocsendbuf(ns_client_t
*client
, isc_buffer_t
*buffer
,
752 isc_buffer_t
*tcpbuffer
, isc_uint32_t length
,
753 unsigned char *sendbuf
, unsigned char **datap
)
756 isc_uint32_t bufsize
;
759 INSIST(datap
!= NULL
);
760 INSIST((tcpbuffer
== NULL
&& length
!= 0) ||
761 (tcpbuffer
!= NULL
&& length
== 0));
763 if (TCP_CLIENT(client
)) {
764 INSIST(client
->tcpbuf
== NULL
);
765 if (length
+ 2 > TCP_BUFFER_SIZE
) {
766 result
= ISC_R_NOSPACE
;
769 client
->tcpbuf
= isc_mem_get(client
->mctx
, TCP_BUFFER_SIZE
);
770 if (client
->tcpbuf
== NULL
) {
771 result
= ISC_R_NOMEMORY
;
774 data
= client
->tcpbuf
;
775 if (tcpbuffer
!= NULL
) {
776 isc_buffer_init(tcpbuffer
, data
, TCP_BUFFER_SIZE
);
777 isc_buffer_init(buffer
, data
+ 2, TCP_BUFFER_SIZE
- 2);
779 isc_buffer_init(buffer
, data
, TCP_BUFFER_SIZE
);
780 INSIST(length
<= 0xffff);
781 isc_buffer_putuint16(buffer
, (isc_uint16_t
)length
);
785 if (client
->udpsize
< SEND_BUFFER_SIZE
)
786 bufsize
= client
->udpsize
;
788 bufsize
= SEND_BUFFER_SIZE
;
789 if (length
> bufsize
) {
790 result
= ISC_R_NOSPACE
;
793 isc_buffer_init(buffer
, data
, bufsize
);
796 result
= ISC_R_SUCCESS
;
803 client_sendpkg(ns_client_t
*client
, isc_buffer_t
*buffer
) {
804 struct in6_pktinfo
*pktinfo
;
807 isc_sockaddr_t
*address
;
808 isc_socket_t
*socket
;
809 isc_netaddr_t netaddr
;
811 unsigned int sockflags
= ISC_SOCKFLAG_IMMEDIATE
;
813 if (TCP_CLIENT(client
)) {
814 socket
= client
->tcpsocket
;
817 socket
= client
->udpsocket
;
818 address
= &client
->peeraddr
;
820 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
821 if (ns_g_server
->blackholeacl
!= NULL
&&
822 dns_acl_match(&netaddr
, NULL
,
823 ns_g_server
->blackholeacl
,
824 &ns_g_server
->aclenv
,
825 &match
, NULL
) == ISC_R_SUCCESS
&&
827 return (DNS_R_BLACKHOLED
);
828 sockflags
|= ISC_SOCKFLAG_NORETRY
;
831 if ((client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0 &&
832 (client
->attributes
& NS_CLIENTATTR_MULTICAST
) == 0)
833 pktinfo
= &client
->pktinfo
;
837 isc_buffer_usedregion(buffer
, &r
);
841 result
= isc_socket_sendto2(socket
, &r
, client
->task
,
843 client
->sendevent
, sockflags
);
844 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_INPROGRESS
) {
846 if (result
== ISC_R_SUCCESS
)
847 client_senddone(client
->task
,
848 (isc_event_t
*)client
->sendevent
);
849 result
= ISC_R_SUCCESS
;
855 ns_client_sendraw(ns_client_t
*client
, dns_message_t
*message
) {
861 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
863 REQUIRE(NS_CLIENT_VALID(client
));
867 mr
= dns_message_getrawmessage(message
);
869 result
= ISC_R_UNEXPECTEDEND
;
873 result
= client_allocsendbuf(client
, &buffer
, NULL
, mr
->length
,
875 if (result
!= ISC_R_SUCCESS
)
879 * Copy message to buffer and fixup id.
881 isc_buffer_availableregion(&buffer
, &r
);
882 result
= isc_buffer_copyregion(&buffer
, mr
);
883 if (result
!= ISC_R_SUCCESS
)
885 r
.base
[0] = (client
->message
->id
>> 8) & 0xff;
886 r
.base
[1] = client
->message
->id
& 0xff;
888 result
= client_sendpkg(client
, &buffer
);
889 if (result
== ISC_R_SUCCESS
)
893 if (client
->tcpbuf
!= NULL
) {
894 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
895 client
->tcpbuf
= NULL
;
897 ns_client_next(client
, result
);
901 ns_client_send(ns_client_t
*client
) {
905 isc_buffer_t tcpbuffer
;
908 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
909 unsigned char sendbuf
[SEND_BUFFER_SIZE
];
910 unsigned int dnssec_opts
;
911 unsigned int preferred_glue
;
912 isc_boolean_t opt_included
= ISC_FALSE
;
914 REQUIRE(NS_CLIENT_VALID(client
));
918 if ((client
->attributes
& NS_CLIENTATTR_RA
) != 0)
919 client
->message
->flags
|= DNS_MESSAGEFLAG_RA
;
921 if ((client
->attributes
& NS_CLIENTATTR_WANTDNSSEC
) != 0)
924 dnssec_opts
= DNS_MESSAGERENDER_OMITDNSSEC
;
927 if (client
->view
!= NULL
) {
928 if (client
->view
->preferred_glue
== dns_rdatatype_a
)
929 preferred_glue
= DNS_MESSAGERENDER_PREFER_A
;
930 else if (client
->view
->preferred_glue
== dns_rdatatype_aaaa
)
931 preferred_glue
= DNS_MESSAGERENDER_PREFER_AAAA
;
935 * XXXRTH The following doesn't deal with TCP buffer resizing.
937 result
= client_allocsendbuf(client
, &buffer
, &tcpbuffer
, 0,
939 if (result
!= ISC_R_SUCCESS
)
942 result
= dns_compress_init(&cctx
, -1, client
->mctx
);
943 if (result
!= ISC_R_SUCCESS
)
945 cleanup_cctx
= ISC_TRUE
;
947 result
= dns_message_renderbegin(client
->message
, &cctx
, &buffer
);
948 if (result
!= ISC_R_SUCCESS
)
951 if (client
->opt
!= NULL
) {
952 result
= dns_message_setopt(client
->message
, client
->opt
);
953 opt_included
= ISC_TRUE
;
955 if (result
!= ISC_R_SUCCESS
)
958 result
= dns_message_rendersection(client
->message
,
959 DNS_SECTION_QUESTION
, 0);
960 if (result
== ISC_R_NOSPACE
) {
961 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
964 if (result
!= ISC_R_SUCCESS
)
966 result
= dns_message_rendersection(client
->message
,
968 DNS_MESSAGERENDER_PARTIAL
|
970 if (result
== ISC_R_NOSPACE
) {
971 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
974 if (result
!= ISC_R_SUCCESS
)
976 result
= dns_message_rendersection(client
->message
,
977 DNS_SECTION_AUTHORITY
,
978 DNS_MESSAGERENDER_PARTIAL
|
980 if (result
== ISC_R_NOSPACE
) {
981 client
->message
->flags
|= DNS_MESSAGEFLAG_TC
;
984 if (result
!= ISC_R_SUCCESS
)
986 result
= dns_message_rendersection(client
->message
,
987 DNS_SECTION_ADDITIONAL
,
988 preferred_glue
| dnssec_opts
);
989 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
992 result
= dns_message_renderend(client
->message
);
994 if (result
!= ISC_R_SUCCESS
)
998 dns_compress_invalidate(&cctx
);
999 cleanup_cctx
= ISC_FALSE
;
1002 if (TCP_CLIENT(client
)) {
1003 isc_buffer_usedregion(&buffer
, &r
);
1004 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
) r
.length
);
1005 isc_buffer_add(&tcpbuffer
, r
.length
);
1006 result
= client_sendpkg(client
, &tcpbuffer
);
1008 result
= client_sendpkg(client
, &buffer
);
1010 /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1011 isc_stats_increment(ns_g_server
->nsstats
, dns_nsstatscounter_response
);
1013 isc_stats_increment(ns_g_server
->nsstats
,
1014 dns_nsstatscounter_edns0out
);
1016 if (client
->message
->tsigkey
!= NULL
) {
1017 isc_stats_increment(ns_g_server
->nsstats
,
1018 dns_nsstatscounter_tsigout
);
1020 if (client
->message
->sig0key
!= NULL
) {
1021 isc_stats_increment(ns_g_server
->nsstats
,
1022 dns_nsstatscounter_sig0out
);
1024 if ((client
->message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
1025 isc_stats_increment(ns_g_server
->nsstats
,
1026 dns_nsstatscounter_truncatedresp
);
1028 if (result
== ISC_R_SUCCESS
)
1032 if (client
->tcpbuf
!= NULL
) {
1033 isc_mem_put(client
->mctx
, client
->tcpbuf
, TCP_BUFFER_SIZE
);
1034 client
->tcpbuf
= NULL
;
1038 dns_compress_invalidate(&cctx
);
1040 ns_client_next(client
, result
);
1043 #if NS_CLIENT_DROPPORT
1044 #define DROPPORT_NO 0
1045 #define DROPPORT_REQUEST 1
1046 #define DROPPORT_RESPONSE 2
1048 * ns_client_dropport determines if certain requests / responses
1049 * should be dropped based on the port number.
1052 * \li 0: Don't drop.
1053 * \li 1: Drop request.
1054 * \li 2: Drop (error) response.
1057 ns_client_dropport(in_port_t port
) {
1060 case 13: /* daytime */
1061 case 19: /* chargen */
1063 return (DROPPORT_REQUEST
);
1064 case 464: /* kpasswd */
1065 return (DROPPORT_RESPONSE
);
1067 return (DROPPORT_NO
);
1072 ns_client_error(ns_client_t
*client
, isc_result_t result
) {
1074 dns_message_t
*message
;
1076 REQUIRE(NS_CLIENT_VALID(client
));
1080 message
= client
->message
;
1081 rcode
= dns_result_torcode(result
);
1083 #if NS_CLIENT_DROPPORT
1085 * Don't send FORMERR to ports on the drop port list.
1087 if (rcode
== dns_rcode_formerr
&&
1088 ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) !=
1093 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
1094 if (dns_rcode_totext(rcode
, &b
) != ISC_R_SUCCESS
)
1095 isc_buffer_putstr(&b
, "UNKNOWN RCODE");
1096 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1097 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1098 "dropped error (%.*s) response: suspicious port",
1099 (int)isc_buffer_usedlength(&b
), buf
);
1100 ns_client_next(client
, ISC_R_SUCCESS
);
1106 * Message may be an in-progress reply that we had trouble
1107 * with, in which case QR will be set. We need to clear QR before
1108 * calling dns_message_reply() to avoid triggering an assertion.
1110 message
->flags
&= ~DNS_MESSAGEFLAG_QR
;
1112 * AA and AD shouldn't be set.
1114 message
->flags
&= ~(DNS_MESSAGEFLAG_AA
| DNS_MESSAGEFLAG_AD
);
1115 result
= dns_message_reply(message
, ISC_TRUE
);
1116 if (result
!= ISC_R_SUCCESS
) {
1118 * It could be that we've got a query with a good header,
1119 * but a bad question section, so we try again with
1120 * want_question_section set to ISC_FALSE.
1122 result
= dns_message_reply(message
, ISC_FALSE
);
1123 if (result
!= ISC_R_SUCCESS
) {
1124 ns_client_next(client
, result
);
1128 message
->rcode
= rcode
;
1131 * FORMERR loop avoidance: If we sent a FORMERR message
1132 * with the same ID to the same client less than two
1133 * seconds ago, assume that we are in an infinite error
1134 * packet dialog with a server for some protocol whose
1135 * error responses look enough like DNS queries to
1136 * elicit a FORMERR response. Drop a packet to break
1139 if (rcode
== dns_rcode_formerr
) {
1140 if (isc_sockaddr_equal(&client
->peeraddr
,
1141 &client
->formerrcache
.addr
) &&
1142 message
->id
== client
->formerrcache
.id
&&
1143 client
->requesttime
- client
->formerrcache
.time
< 2) {
1145 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1146 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1147 "possible error packet loop, "
1149 ns_client_next(client
, result
);
1152 client
->formerrcache
.addr
= client
->peeraddr
;
1153 client
->formerrcache
.time
= client
->requesttime
;
1154 client
->formerrcache
.id
= message
->id
;
1156 ns_client_send(client
);
1159 static inline isc_result_t
1160 client_addopt(ns_client_t
*client
) {
1161 dns_rdataset_t
*rdataset
;
1162 dns_rdatalist_t
*rdatalist
;
1164 isc_result_t result
;
1166 dns_resolver_t
*resolver
;
1167 isc_uint16_t udpsize
;
1169 REQUIRE(client
->opt
== NULL
); /* XXXRTH free old. */
1172 result
= dns_message_gettemprdatalist(client
->message
, &rdatalist
);
1173 if (result
!= ISC_R_SUCCESS
)
1176 result
= dns_message_gettemprdata(client
->message
, &rdata
);
1177 if (result
!= ISC_R_SUCCESS
)
1180 result
= dns_message_gettemprdataset(client
->message
, &rdataset
);
1181 if (result
!= ISC_R_SUCCESS
)
1183 dns_rdataset_init(rdataset
);
1185 rdatalist
->type
= dns_rdatatype_opt
;
1186 rdatalist
->covers
= 0;
1189 * Set the maximum UDP buffer size.
1191 view
= client
->view
;
1192 resolver
= (view
!= NULL
) ? view
->resolver
: NULL
;
1193 if (resolver
!= NULL
)
1194 udpsize
= dns_resolver_getudpsize(resolver
);
1196 udpsize
= ns_g_udpsize
;
1197 rdatalist
->rdclass
= udpsize
;
1200 * Set EXTENDED-RCODE, VERSION and Z to 0.
1202 rdatalist
->ttl
= (client
->extflags
& DNS_MESSAGEEXTFLAG_REPLYPRESERVE
);
1204 /* Set EDNS options if applicable */
1205 if (client
->attributes
& NS_CLIENTATTR_WANTNSID
&&
1206 (ns_g_server
->server_id
!= NULL
||
1207 ns_g_server
->server_usehostname
)) {
1209 * Space required for NSID data:
1210 * 2 bytes for opt code
1211 * + 2 bytes for NSID length
1214 char nsid
[BUFSIZ
], *nsidp
;
1215 isc_buffer_t
*buffer
= NULL
;
1217 if (ns_g_server
->server_usehostname
) {
1218 isc_result_t result
;
1219 result
= ns_os_gethostname(nsid
, sizeof(nsid
));
1220 if (result
!= ISC_R_SUCCESS
) {
1225 nsidp
= ns_g_server
->server_id
;
1227 rdata
->length
= strlen(nsidp
) + 4;
1228 result
= isc_buffer_allocate(client
->mctx
, &buffer
,
1230 if (result
!= ISC_R_SUCCESS
)
1233 isc_buffer_putuint16(buffer
, DNS_OPT_NSID
);
1234 isc_buffer_putuint16(buffer
, strlen(nsidp
));
1235 isc_buffer_putstr(buffer
, nsidp
);
1236 rdata
->data
= buffer
->base
;
1237 dns_message_takebuffer(client
->message
, &buffer
);
1244 rdata
->rdclass
= rdatalist
->rdclass
;
1245 rdata
->type
= rdatalist
->type
;
1248 ISC_LIST_INIT(rdatalist
->rdata
);
1249 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1250 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
)
1253 client
->opt
= rdataset
;
1255 return (ISC_R_SUCCESS
);
1258 static inline isc_boolean_t
1259 allowed(isc_netaddr_t
*addr
, dns_name_t
*signer
, dns_acl_t
*acl
) {
1261 isc_result_t result
;
1265 result
= dns_acl_match(addr
, signer
, acl
, &ns_g_server
->aclenv
,
1267 if (result
== ISC_R_SUCCESS
&& match
> 0)
1273 * Callback to see if a non-recursive query coming from 'srcaddr' to
1274 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1275 * delivered to 'myview'.
1277 * We run this unlocked as both the view list and the interface list
1278 * are updated when the appropriate task has exclusivity.
1281 ns_client_isself(dns_view_t
*myview
, dns_tsigkey_t
*mykey
,
1282 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*dstaddr
,
1283 dns_rdataclass_t rdclass
, void *arg
)
1286 dns_tsigkey_t
*key
= NULL
;
1287 dns_name_t
*tsig
= NULL
;
1288 isc_netaddr_t netsrc
;
1289 isc_netaddr_t netdst
;
1293 if (!ns_interfacemgr_listeningon(ns_g_server
->interfacemgr
, dstaddr
))
1296 isc_netaddr_fromsockaddr(&netsrc
, srcaddr
);
1297 isc_netaddr_fromsockaddr(&netdst
, dstaddr
);
1299 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1301 view
= ISC_LIST_NEXT(view
, link
)) {
1303 if (view
->matchrecursiveonly
)
1306 if (rdclass
!= view
->rdclass
)
1309 if (mykey
!= NULL
) {
1310 isc_boolean_t match
;
1311 isc_result_t result
;
1313 result
= dns_view_gettsig(view
, &mykey
->name
, &key
);
1314 if (result
!= ISC_R_SUCCESS
)
1316 match
= dst_key_compare(mykey
->key
, key
->key
);
1317 dns_tsigkey_detach(&key
);
1320 tsig
= dns_tsigkey_identity(mykey
);
1323 if (allowed(&netsrc
, tsig
, view
->matchclients
) &&
1324 allowed(&netdst
, tsig
, view
->matchdestinations
))
1327 return (ISC_TF(view
== myview
));
1331 * Handle an incoming request event from the socket (UDP case)
1332 * or tcpmsg (TCP case).
1335 client_request(isc_task_t
*task
, isc_event_t
*event
) {
1336 ns_client_t
*client
;
1337 isc_socketevent_t
*sevent
;
1338 isc_result_t result
;
1339 isc_result_t sigresult
= ISC_R_SUCCESS
;
1340 isc_buffer_t
*buffer
;
1341 isc_buffer_t tbuffer
;
1343 dns_rdataset_t
*opt
;
1344 dns_name_t
*signame
;
1345 isc_boolean_t ra
; /* Recursion available. */
1346 isc_netaddr_t netaddr
;
1347 isc_netaddr_t destaddr
;
1351 isc_boolean_t notimp
;
1353 isc_uint16_t optcode
;
1355 REQUIRE(event
!= NULL
);
1356 client
= event
->ev_arg
;
1357 REQUIRE(NS_CLIENT_VALID(client
));
1358 REQUIRE(task
== client
->task
);
1360 INSIST(client
->recursionquota
== NULL
);
1362 INSIST(client
->state
==
1363 TCP_CLIENT(client
) ?
1364 NS_CLIENTSTATE_READING
:
1365 NS_CLIENTSTATE_READY
);
1367 ns_client_requests
++;
1369 if (event
->ev_type
== ISC_SOCKEVENT_RECVDONE
) {
1370 INSIST(!TCP_CLIENT(client
));
1371 sevent
= (isc_socketevent_t
*)event
;
1372 REQUIRE(sevent
== client
->recvevent
);
1373 isc_buffer_init(&tbuffer
, sevent
->region
.base
, sevent
->n
);
1374 isc_buffer_add(&tbuffer
, sevent
->n
);
1376 result
= sevent
->result
;
1377 if (result
== ISC_R_SUCCESS
) {
1378 client
->peeraddr
= sevent
->address
;
1379 client
->peeraddr_valid
= ISC_TRUE
;
1381 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_PKTINFO
) != 0) {
1382 client
->attributes
|= NS_CLIENTATTR_PKTINFO
;
1383 client
->pktinfo
= sevent
->pktinfo
;
1385 if ((sevent
->attributes
& ISC_SOCKEVENTATTR_MULTICAST
) != 0)
1386 client
->attributes
|= NS_CLIENTATTR_MULTICAST
;
1389 INSIST(TCP_CLIENT(client
));
1390 REQUIRE(event
->ev_type
== DNS_EVENT_TCPMSG
);
1391 REQUIRE(event
->ev_sender
== &client
->tcpmsg
);
1392 buffer
= &client
->tcpmsg
.buffer
;
1393 result
= client
->tcpmsg
.result
;
1394 INSIST(client
->nreads
== 1);
1396 * client->peeraddr was set when the connection was accepted.
1401 if (exit_check(client
))
1403 client
->state
= client
->newstate
= NS_CLIENTSTATE_WORKING
;
1405 isc_task_getcurrenttime(task
, &client
->requesttime
);
1406 client
->now
= client
->requesttime
;
1408 if (result
!= ISC_R_SUCCESS
) {
1409 if (TCP_CLIENT(client
)) {
1410 ns_client_next(client
, result
);
1412 if (result
!= ISC_R_CANCELED
)
1413 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_CLIENT
,
1414 NS_LOGMODULE_CLIENT
,
1416 "UDP client handler shutting "
1417 "down due to fatal receive "
1419 isc_result_totext(result
));
1420 isc_task_shutdown(client
->task
);
1425 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
1427 #if NS_CLIENT_DROPPORT
1428 if (ns_client_dropport(isc_sockaddr_getport(&client
->peeraddr
)) ==
1430 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1431 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1432 "dropped request: suspicious port");
1433 ns_client_next(client
, ISC_R_SUCCESS
);
1438 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1439 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1441 TCP_CLIENT(client
) ? "TCP" : "UDP");
1444 * Check the blackhole ACL for UDP only, since TCP is done in
1447 if (!TCP_CLIENT(client
)) {
1449 if (ns_g_server
->blackholeacl
!= NULL
&&
1450 dns_acl_match(&netaddr
, NULL
, ns_g_server
->blackholeacl
,
1451 &ns_g_server
->aclenv
,
1452 &match
, NULL
) == ISC_R_SUCCESS
&&
1455 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1456 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
1457 "blackholed UDP datagram");
1458 ns_client_next(client
, ISC_R_SUCCESS
);
1464 * Silently drop multicast requests for the present.
1465 * XXXMPA look at when/if mDNS spec stabilizes.
1467 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0) {
1468 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1469 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(2),
1470 "dropping multicast request");
1471 ns_client_next(client
, DNS_R_REFUSED
);
1475 result
= dns_message_peekheader(buffer
, &id
, &flags
);
1476 if (result
!= ISC_R_SUCCESS
) {
1478 * There isn't enough header to determine whether
1479 * this was a request or a response. Drop it.
1481 ns_client_next(client
, result
);
1486 * The client object handles requests, not responses.
1487 * If this is a UDP response, forward it to the dispatcher.
1488 * If it's a TCP response, discard it here.
1490 if ((flags
& DNS_MESSAGEFLAG_QR
) != 0) {
1491 if (TCP_CLIENT(client
)) {
1492 CTRACE("unexpected response");
1493 ns_client_next(client
, DNS_R_FORMERR
);
1496 dns_dispatch_importrecv(client
->dispatch
, event
);
1497 ns_client_next(client
, ISC_R_SUCCESS
);
1503 * Update some statistics counters. Don't count responses.
1505 if (isc_sockaddr_pf(&client
->peeraddr
) == PF_INET
) {
1506 isc_stats_increment(ns_g_server
->nsstats
,
1507 dns_nsstatscounter_requestv4
);
1509 isc_stats_increment(ns_g_server
->nsstats
,
1510 dns_nsstatscounter_requestv6
);
1512 if (TCP_CLIENT(client
))
1513 isc_stats_increment(ns_g_server
->nsstats
,
1514 dns_nsstatscounter_tcp
);
1517 * It's a request. Parse it.
1519 result
= dns_message_parse(client
->message
, buffer
, 0);
1520 if (result
!= ISC_R_SUCCESS
) {
1522 * Parsing the request failed. Send a response
1523 * (typically FORMERR or SERVFAIL).
1525 ns_client_error(client
, result
);
1529 dns_opcodestats_increment(ns_g_server
->opcodestats
,
1530 client
->message
->opcode
);
1531 switch (client
->message
->opcode
) {
1532 case dns_opcode_query
:
1533 case dns_opcode_update
:
1534 case dns_opcode_notify
:
1537 case dns_opcode_iquery
:
1543 client
->message
->rcode
= dns_rcode_noerror
;
1545 /* RFC1123 section 6.1.3.2 */
1546 if ((client
->attributes
& NS_CLIENTATTR_MULTICAST
) != 0)
1547 client
->message
->flags
&= ~DNS_MESSAGEFLAG_RD
;
1552 opt
= dns_message_getopt(client
->message
);
1555 * Set the client's UDP buffer size.
1557 client
->udpsize
= opt
->rdclass
;
1560 * If the requested UDP buffer size is less than 512,
1561 * ignore it and use 512.
1563 if (client
->udpsize
< 512)
1564 client
->udpsize
= 512;
1567 * Get the flags out of the OPT record.
1569 client
->extflags
= (isc_uint16_t
)(opt
->ttl
& 0xFFFF);
1572 * Do we understand this version of EDNS?
1574 * XXXRTH need library support for this!
1576 client
->ednsversion
= (opt
->ttl
& 0x00FF0000) >> 16;
1577 if (client
->ednsversion
> 0) {
1578 isc_stats_increment(ns_g_server
->nsstats
,
1579 dns_nsstatscounter_badednsver
);
1580 result
= client_addopt(client
);
1581 if (result
== ISC_R_SUCCESS
)
1582 result
= DNS_R_BADVERS
;
1583 ns_client_error(client
, result
);
1587 /* Check for NSID request */
1588 result
= dns_rdataset_first(opt
);
1589 if (result
== ISC_R_SUCCESS
) {
1590 dns_rdata_init(&rdata
);
1591 dns_rdataset_current(opt
, &rdata
);
1592 if (rdata
.length
>= 2) {
1593 isc_buffer_t nsidbuf
;
1594 isc_buffer_init(&nsidbuf
,
1595 rdata
.data
, rdata
.length
);
1596 isc_buffer_add(&nsidbuf
, rdata
.length
);
1597 optcode
= isc_buffer_getuint16(&nsidbuf
);
1598 if (optcode
== DNS_OPT_NSID
)
1599 client
->attributes
|=
1600 NS_CLIENTATTR_WANTNSID
;
1604 isc_stats_increment(ns_g_server
->nsstats
,
1605 dns_nsstatscounter_edns0in
);
1608 * Create an OPT for our reply.
1610 result
= client_addopt(client
);
1611 if (result
!= ISC_R_SUCCESS
) {
1612 ns_client_error(client
, result
);
1617 if (client
->message
->rdclass
== 0) {
1618 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1619 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1620 "message class could not be determined");
1621 ns_client_dumpmessage(client
,
1622 "message class could not be determined");
1623 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_FORMERR
);
1628 * Determine the destination address. If the receiving interface is
1629 * bound to a specific address, we simply use it regardless of the
1630 * address family. All IPv4 queries should fall into this case.
1631 * Otherwise, if this is a TCP query, get the address from the
1632 * receiving socket (this needs a system call and can be heavy).
1633 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1635 * If all the attempts fail (this can happen due to memory shortage,
1636 * etc), we regard this as an error for safety.
1638 if ((client
->interface
->flags
& NS_INTERFACEFLAG_ANYADDR
) == 0)
1639 isc_netaddr_fromsockaddr(&destaddr
, &client
->interface
->addr
);
1641 result
= ISC_R_FAILURE
;
1643 if (TCP_CLIENT(client
)) {
1644 isc_sockaddr_t destsockaddr
;
1646 result
= isc_socket_getsockname(client
->tcpsocket
,
1648 if (result
== ISC_R_SUCCESS
)
1649 isc_netaddr_fromsockaddr(&destaddr
,
1652 if (result
!= ISC_R_SUCCESS
&&
1653 client
->interface
->addr
.type
.sa
.sa_family
== AF_INET6
&&
1654 (client
->attributes
& NS_CLIENTATTR_PKTINFO
) != 0) {
1655 isc_uint32_t zone
= 0;
1658 * XXXJT technically, we should convert the receiving
1659 * interface ID to a proper scope zone ID. However,
1660 * due to the fact there is no standard API for this,
1661 * we only handle link-local addresses and use the
1662 * interface index as link ID. Despite the assumption,
1663 * it should cover most typical cases.
1665 if (IN6_IS_ADDR_LINKLOCAL(&client
->pktinfo
.ipi6_addr
))
1666 zone
= (isc_uint32_t
)client
->pktinfo
.ipi6_ifindex
;
1668 isc_netaddr_fromin6(&destaddr
,
1669 &client
->pktinfo
.ipi6_addr
);
1670 isc_netaddr_setzone(&destaddr
, zone
);
1671 result
= ISC_R_SUCCESS
;
1673 if (result
!= ISC_R_SUCCESS
) {
1674 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1675 "failed to get request's "
1677 isc_result_totext(result
));
1678 ns_client_next(client
, ISC_R_SUCCESS
);
1684 * Find a view that matches the client's source address.
1686 for (view
= ISC_LIST_HEAD(ns_g_server
->viewlist
);
1688 view
= ISC_LIST_NEXT(view
, link
)) {
1689 if (client
->message
->rdclass
== view
->rdclass
||
1690 client
->message
->rdclass
== dns_rdataclass_any
)
1692 dns_name_t
*tsig
= NULL
;
1694 sigresult
= dns_message_rechecksig(client
->message
,
1696 if (sigresult
== ISC_R_SUCCESS
)
1697 tsig
= dns_tsigkey_identity(client
->message
->tsigkey
);
1699 if (allowed(&netaddr
, tsig
, view
->matchclients
) &&
1700 allowed(&destaddr
, tsig
, view
->matchdestinations
) &&
1701 !((client
->message
->flags
& DNS_MESSAGEFLAG_RD
)
1702 == 0 && view
->matchrecursiveonly
))
1704 dns_view_attach(view
, &client
->view
);
1711 char classname
[DNS_RDATACLASS_FORMATSIZE
];
1714 * Do a dummy TSIG verification attempt so that the
1715 * response will have a TSIG if the query did, as
1716 * required by RFC2845.
1721 dns_message_resetsig(client
->message
);
1723 r
= dns_message_getrawmessage(client
->message
);
1724 isc_buffer_init(&b
, r
->base
, r
->length
);
1725 isc_buffer_add(&b
, r
->length
);
1726 (void)dns_tsig_verify(&b
, client
->message
, NULL
, NULL
);
1728 dns_rdataclass_format(client
->message
->rdclass
, classname
,
1730 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1731 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
1732 "no matching view in class '%s'", classname
);
1733 ns_client_dumpmessage(client
, "no matching view in class");
1734 ns_client_error(client
, notimp
? DNS_R_NOTIMP
: DNS_R_REFUSED
);
1738 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
1739 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(5),
1740 "using view '%s'", view
->name
);
1743 * Check for a signature. We log bad signatures regardless of
1744 * whether they ultimately cause the request to be rejected or
1745 * not. We do not log the lack of a signature unless we are
1748 client
->signer
= NULL
;
1749 dns_name_init(&client
->signername
, NULL
);
1750 result
= dns_message_signer(client
->message
, &client
->signername
);
1751 if (result
!= ISC_R_NOTFOUND
) {
1753 if (dns_message_gettsig(client
->message
, &signame
) != NULL
) {
1754 isc_stats_increment(ns_g_server
->nsstats
,
1755 dns_nsstatscounter_tsigin
);
1757 isc_stats_increment(ns_g_server
->nsstats
,
1758 dns_nsstatscounter_sig0in
);
1762 if (result
== ISC_R_SUCCESS
) {
1763 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1764 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1765 "request has valid signature");
1766 client
->signer
= &client
->signername
;
1767 } else if (result
== ISC_R_NOTFOUND
) {
1768 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1769 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1770 "request is not signed");
1771 } else if (result
== DNS_R_NOIDENTITY
) {
1772 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1773 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
1774 "request is signed by a nonauthoritative key");
1779 isc_result_t tresult
;
1781 /* There is a signature, but it is bad. */
1782 isc_stats_increment(ns_g_server
->nsstats
,
1783 dns_nsstatscounter_invalidsig
);
1785 if (dns_message_gettsig(client
->message
, &signame
) != NULL
) {
1786 char namebuf
[DNS_NAME_FORMATSIZE
];
1787 char cnamebuf
[DNS_NAME_FORMATSIZE
];
1788 dns_name_format(signame
, namebuf
, sizeof(namebuf
));
1789 status
= client
->message
->tsigstatus
;
1790 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
1791 tresult
= dns_tsigrcode_totext(status
, &b
);
1792 INSIST(tresult
== ISC_R_SUCCESS
);
1793 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
1794 if (client
->message
->tsigkey
->generated
) {
1795 dns_name_format(client
->message
->tsigkey
->creator
,
1796 cnamebuf
, sizeof(cnamebuf
));
1797 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1798 NS_LOGMODULE_CLIENT
,
1800 "request has invalid signature: "
1801 "TSIG %s (%s): %s (%s)", namebuf
,
1803 isc_result_totext(result
),
1806 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1807 NS_LOGMODULE_CLIENT
,
1809 "request has invalid signature: "
1810 "TSIG %s: %s (%s)", namebuf
,
1811 isc_result_totext(result
),
1815 status
= client
->message
->sig0status
;
1816 isc_buffer_init(&b
, tsigrcode
, sizeof(tsigrcode
) - 1);
1817 tresult
= dns_tsigrcode_totext(status
, &b
);
1818 INSIST(tresult
== ISC_R_SUCCESS
);
1819 tsigrcode
[isc_buffer_usedlength(&b
)] = '\0';
1820 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
1821 NS_LOGMODULE_CLIENT
, ISC_LOG_ERROR
,
1822 "request has invalid signature: %s (%s)",
1823 isc_result_totext(result
), tsigrcode
);
1826 * Accept update messages signed by unknown keys so that
1827 * update forwarding works transparently through slaves
1828 * that don't have all the same keys as the master.
1830 if (!(client
->message
->tsigstatus
== dns_tsigerror_badkey
&&
1831 client
->message
->opcode
== dns_opcode_update
)) {
1832 ns_client_error(client
, sigresult
);
1838 * Decide whether recursive service is available to this client.
1839 * We do this here rather than in the query code so that we can
1840 * set the RA bit correctly on all kinds of responses, not just
1841 * responses to ordinary queries. Note if you can't query the
1842 * cache there is no point in setting RA.
1845 if (client
->view
->resolver
!= NULL
&&
1846 client
->view
->recursion
== ISC_TRUE
&&
1847 ns_client_checkaclsilent(client
, NULL
,
1848 client
->view
->recursionacl
,
1849 ISC_TRUE
) == ISC_R_SUCCESS
&&
1850 ns_client_checkaclsilent(client
, NULL
,
1851 client
->view
->queryacl
,
1852 ISC_TRUE
) == ISC_R_SUCCESS
&&
1853 ns_client_checkaclsilent(client
, &client
->interface
->addr
,
1854 client
->view
->recursiononacl
,
1855 ISC_TRUE
) == ISC_R_SUCCESS
&&
1856 ns_client_checkaclsilent(client
, &client
->interface
->addr
,
1857 client
->view
->queryonacl
,
1858 ISC_TRUE
) == ISC_R_SUCCESS
)
1862 client
->attributes
|= NS_CLIENTATTR_RA
;
1864 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
, NS_LOGMODULE_CLIENT
,
1865 ISC_LOG_DEBUG(3), ra
? "recursion available" :
1866 "recursion not available");
1869 * Adjust maximum UDP response size for this client.
1871 if (client
->udpsize
> 512) {
1872 dns_peer_t
*peer
= NULL
;
1873 isc_uint16_t udpsize
= view
->maxudp
;
1874 (void) dns_peerlist_peerbyaddr(view
->peers
, &netaddr
, &peer
);
1876 dns_peer_getmaxudp(peer
, &udpsize
);
1877 if (client
->udpsize
> udpsize
)
1878 client
->udpsize
= udpsize
;
1882 * Dispatch the request.
1884 switch (client
->message
->opcode
) {
1885 case dns_opcode_query
:
1887 ns_query_start(client
);
1889 case dns_opcode_update
:
1891 ns_client_settimeout(client
, 60);
1892 ns_update_start(client
, sigresult
);
1894 case dns_opcode_notify
:
1896 ns_client_settimeout(client
, 60);
1897 ns_notify_start(client
);
1899 case dns_opcode_iquery
:
1901 ns_client_error(client
, DNS_R_NOTIMP
);
1904 CTRACE("unknown opcode");
1905 ns_client_error(client
, DNS_R_NOTIMP
);
1913 client_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1914 ns_client_t
*client
;
1916 REQUIRE(event
!= NULL
);
1917 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_LIFE
||
1918 event
->ev_type
== ISC_TIMEREVENT_IDLE
);
1919 client
= event
->ev_arg
;
1920 REQUIRE(NS_CLIENT_VALID(client
));
1921 REQUIRE(task
== client
->task
);
1922 REQUIRE(client
->timer
!= NULL
);
1928 isc_event_free(&event
);
1930 if (client
->shutdown
!= NULL
) {
1931 (client
->shutdown
)(client
->shutdown_arg
, ISC_R_TIMEDOUT
);
1932 client
->shutdown
= NULL
;
1933 client
->shutdown_arg
= NULL
;
1936 if (client
->newstate
> NS_CLIENTSTATE_READY
)
1937 client
->newstate
= NS_CLIENTSTATE_READY
;
1938 (void)exit_check(client
);
1942 get_clientmctx(ns_clientmgr_t
*manager
, isc_mem_t
**mctxp
) {
1943 isc_mem_t
*clientmctx
;
1945 isc_result_t result
;
1949 * Caller must be holding the manager lock.
1952 INSIST(manager
->nextmctx
< NMCTXS
);
1953 clientmctx
= manager
->mctxpool
[manager
->nextmctx
];
1954 if (clientmctx
== NULL
) {
1955 result
= isc_mem_create(0, 0, &clientmctx
);
1956 if (result
!= ISC_R_SUCCESS
)
1958 isc_mem_setname(clientmctx
, "client", NULL
);
1960 manager
->mctxpool
[manager
->nextmctx
] = clientmctx
;
1962 manager
->nextmctx
++;
1963 if (manager
->nextmctx
== NMCTXS
)
1964 manager
->nextmctx
= 0;
1966 clientmctx
= manager
->mctx
;
1969 isc_mem_attach(clientmctx
, mctxp
);
1971 return (ISC_R_SUCCESS
);
1975 client_create(ns_clientmgr_t
*manager
, ns_client_t
**clientp
) {
1976 ns_client_t
*client
;
1977 isc_result_t result
;
1978 isc_mem_t
*mctx
= NULL
;
1981 * Caller must be holding the manager lock.
1983 * Note: creating a client does not add the client to the
1984 * manager's client list or set the client's manager pointer.
1985 * The caller is responsible for that.
1988 REQUIRE(clientp
!= NULL
&& *clientp
== NULL
);
1990 result
= get_clientmctx(manager
, &mctx
);
1991 if (result
!= ISC_R_SUCCESS
)
1994 client
= isc_mem_get(mctx
, sizeof(*client
));
1995 if (client
== NULL
) {
1996 isc_mem_detach(&mctx
);
1997 return (ISC_R_NOMEMORY
);
1999 client
->mctx
= mctx
;
2001 client
->task
= NULL
;
2002 result
= isc_task_create(manager
->taskmgr
, 0, &client
->task
);
2003 if (result
!= ISC_R_SUCCESS
)
2004 goto cleanup_client
;
2005 isc_task_setname(client
->task
, "client", client
);
2007 client
->timer
= NULL
;
2008 result
= isc_timer_create(manager
->timermgr
, isc_timertype_inactive
,
2009 NULL
, NULL
, client
->task
, client_timeout
,
2010 client
, &client
->timer
);
2011 if (result
!= ISC_R_SUCCESS
)
2013 client
->timerset
= ISC_FALSE
;
2015 client
->message
= NULL
;
2016 result
= dns_message_create(client
->mctx
, DNS_MESSAGE_INTENTPARSE
,
2018 if (result
!= ISC_R_SUCCESS
)
2021 /* XXXRTH Hardwired constants */
2023 client
->sendevent
= (isc_socketevent_t
*)
2024 isc_event_allocate(client
->mctx
, client
,
2025 ISC_SOCKEVENT_SENDDONE
,
2026 client_senddone
, client
,
2027 sizeof(isc_socketevent_t
));
2028 if (client
->sendevent
== NULL
) {
2029 result
= ISC_R_NOMEMORY
;
2030 goto cleanup_message
;
2033 client
->recvbuf
= isc_mem_get(client
->mctx
, RECV_BUFFER_SIZE
);
2034 if (client
->recvbuf
== NULL
) {
2035 result
= ISC_R_NOMEMORY
;
2036 goto cleanup_sendevent
;
2039 client
->recvevent
= (isc_socketevent_t
*)
2040 isc_event_allocate(client
->mctx
, client
,
2041 ISC_SOCKEVENT_RECVDONE
,
2042 client_request
, client
,
2043 sizeof(isc_socketevent_t
));
2044 if (client
->recvevent
== NULL
) {
2045 result
= ISC_R_NOMEMORY
;
2046 goto cleanup_recvbuf
;
2049 client
->magic
= NS_CLIENT_MAGIC
;
2050 client
->manager
= NULL
;
2051 client
->state
= NS_CLIENTSTATE_INACTIVE
;
2052 client
->newstate
= NS_CLIENTSTATE_MAX
;
2053 client
->naccepts
= 0;
2057 client
->nupdates
= 0;
2059 client
->references
= 0;
2060 client
->attributes
= 0;
2061 client
->view
= NULL
;
2062 client
->dispatch
= NULL
;
2063 client
->udpsocket
= NULL
;
2064 client
->tcplistener
= NULL
;
2065 client
->tcpsocket
= NULL
;
2066 client
->tcpmsg_valid
= ISC_FALSE
;
2067 client
->tcpbuf
= NULL
;
2069 client
->udpsize
= 512;
2070 client
->extflags
= 0;
2071 client
->ednsversion
= -1;
2072 client
->next
= NULL
;
2073 client
->shutdown
= NULL
;
2074 client
->shutdown_arg
= NULL
;
2075 dns_name_init(&client
->signername
, NULL
);
2076 client
->mortal
= ISC_FALSE
;
2077 client
->tcpquota
= NULL
;
2078 client
->recursionquota
= NULL
;
2079 client
->interface
= NULL
;
2080 client
->peeraddr_valid
= ISC_FALSE
;
2081 ISC_EVENT_INIT(&client
->ctlevent
, sizeof(client
->ctlevent
), 0, NULL
,
2082 NS_EVENT_CLIENTCONTROL
, client_start
, client
, client
,
2085 * Initialize FORMERR cache to sentinel value that will not match
2086 * any actual FORMERR response.
2088 isc_sockaddr_any(&client
->formerrcache
.addr
);
2089 client
->formerrcache
.time
= 0;
2090 client
->formerrcache
.id
= 0;
2091 ISC_LINK_INIT(client
, link
);
2092 client
->list
= NULL
;
2095 * We call the init routines for the various kinds of client here,
2096 * after we have created an otherwise valid client, because some
2097 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2099 result
= ns_query_init(client
);
2100 if (result
!= ISC_R_SUCCESS
)
2101 goto cleanup_recvevent
;
2103 result
= isc_task_onshutdown(client
->task
, client_shutdown
, client
);
2104 if (result
!= ISC_R_SUCCESS
)
2111 return (ISC_R_SUCCESS
);
2114 ns_query_free(client
);
2117 isc_event_free((isc_event_t
**)&client
->recvevent
);
2120 isc_mem_put(client
->mctx
, client
->recvbuf
, RECV_BUFFER_SIZE
);
2123 isc_event_free((isc_event_t
**)&client
->sendevent
);
2128 dns_message_destroy(&client
->message
);
2131 isc_timer_detach(&client
->timer
);
2134 isc_task_detach(&client
->task
);
2137 isc_mem_putanddetach(&client
->mctx
, client
, sizeof(*client
));
2143 client_read(ns_client_t
*client
) {
2144 isc_result_t result
;
2148 result
= dns_tcpmsg_readmessage(&client
->tcpmsg
, client
->task
,
2149 client_request
, client
);
2150 if (result
!= ISC_R_SUCCESS
)
2154 * Set a timeout to limit the amount of time we will wait
2155 * for a request on this TCP connection.
2157 ns_client_settimeout(client
, 30);
2159 client
->state
= client
->newstate
= NS_CLIENTSTATE_READING
;
2160 INSIST(client
->nreads
== 0);
2161 INSIST(client
->recursionquota
== NULL
);
2166 ns_client_next(client
, result
);
2170 client_newconn(isc_task_t
*task
, isc_event_t
*event
) {
2171 ns_client_t
*client
= event
->ev_arg
;
2172 isc_socket_newconnev_t
*nevent
= (isc_socket_newconnev_t
*)event
;
2173 isc_result_t result
;
2175 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_NEWCONN
);
2176 REQUIRE(NS_CLIENT_VALID(client
));
2177 REQUIRE(client
->task
== task
);
2181 INSIST(client
->state
== NS_CLIENTSTATE_READY
);
2183 INSIST(client
->naccepts
== 1);
2186 LOCK(&client
->interface
->lock
);
2187 INSIST(client
->interface
->ntcpcurrent
> 0);
2188 client
->interface
->ntcpcurrent
--;
2189 UNLOCK(&client
->interface
->lock
);
2192 * We must take ownership of the new socket before the exit
2193 * check to make sure it gets destroyed if we decide to exit.
2195 if (nevent
->result
== ISC_R_SUCCESS
) {
2196 client
->tcpsocket
= nevent
->newsocket
;
2197 isc_socket_setname(client
->tcpsocket
, "client-tcp", NULL
);
2198 client
->state
= NS_CLIENTSTATE_READING
;
2199 INSIST(client
->recursionquota
== NULL
);
2201 (void)isc_socket_getpeername(client
->tcpsocket
,
2203 client
->peeraddr_valid
= ISC_TRUE
;
2204 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2205 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2206 "new TCP connection");
2209 * XXXRTH What should we do? We're trying to accept but
2210 * it didn't work. If we just give up, then TCP
2211 * service may eventually stop.
2213 * For now, we just go idle.
2215 * Going idle is probably the right thing if the
2218 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2219 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2220 "accept failed: %s",
2221 isc_result_totext(nevent
->result
));
2224 if (exit_check(client
))
2227 if (nevent
->result
== ISC_R_SUCCESS
) {
2229 isc_netaddr_t netaddr
;
2231 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2233 if (ns_g_server
->blackholeacl
!= NULL
&&
2234 dns_acl_match(&netaddr
, NULL
,
2235 ns_g_server
->blackholeacl
,
2236 &ns_g_server
->aclenv
,
2237 &match
, NULL
) == ISC_R_SUCCESS
&&
2240 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2241 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2242 "blackholed connection attempt");
2243 client
->newstate
= NS_CLIENTSTATE_READY
;
2244 (void)exit_check(client
);
2248 INSIST(client
->tcpmsg_valid
== ISC_FALSE
);
2249 dns_tcpmsg_init(client
->mctx
, client
->tcpsocket
,
2251 client
->tcpmsg_valid
= ISC_TRUE
;
2254 * Let a new client take our place immediately, before
2255 * we wait for a request packet. If we don't,
2256 * telnetting to port 53 (once per CPU) will
2257 * deny service to legitimate TCP clients.
2259 result
= isc_quota_attach(&ns_g_server
->tcpquota
,
2261 if (result
== ISC_R_SUCCESS
)
2262 result
= ns_client_replace(client
);
2263 if (result
!= ISC_R_SUCCESS
) {
2264 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2265 NS_LOGMODULE_CLIENT
, ISC_LOG_WARNING
,
2266 "no more TCP clients: %s",
2267 isc_result_totext(result
));
2270 client_read(client
);
2274 isc_event_free(&event
);
2278 client_accept(ns_client_t
*client
) {
2279 isc_result_t result
;
2283 result
= isc_socket_accept(client
->tcplistener
, client
->task
,
2284 client_newconn
, client
);
2285 if (result
!= ISC_R_SUCCESS
) {
2286 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2287 "isc_socket_accept() failed: %s",
2288 isc_result_totext(result
));
2290 * XXXRTH What should we do? We're trying to accept but
2291 * it didn't work. If we just give up, then TCP
2292 * service may eventually stop.
2294 * For now, we just go idle.
2298 INSIST(client
->naccepts
== 0);
2300 LOCK(&client
->interface
->lock
);
2301 client
->interface
->ntcpcurrent
++;
2302 UNLOCK(&client
->interface
->lock
);
2306 client_udprecv(ns_client_t
*client
) {
2307 isc_result_t result
;
2312 r
.base
= client
->recvbuf
;
2313 r
.length
= RECV_BUFFER_SIZE
;
2314 result
= isc_socket_recv2(client
->udpsocket
, &r
, 1,
2315 client
->task
, client
->recvevent
, 0);
2316 if (result
!= ISC_R_SUCCESS
) {
2317 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2318 "isc_socket_recv2() failed: %s",
2319 isc_result_totext(result
));
2321 * This cannot happen in the current implementation, since
2322 * isc_socket_recv2() cannot fail if flags == 0.
2324 * If this does fail, we just go idle.
2328 INSIST(client
->nrecvs
== 0);
2333 ns_client_attach(ns_client_t
*source
, ns_client_t
**targetp
) {
2334 REQUIRE(NS_CLIENT_VALID(source
));
2335 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
2337 source
->references
++;
2338 ns_client_log(source
, NS_LOGCATEGORY_CLIENT
,
2339 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2340 "ns_client_attach: ref = %d", source
->references
);
2345 ns_client_detach(ns_client_t
**clientp
) {
2346 ns_client_t
*client
= *clientp
;
2348 client
->references
--;
2349 INSIST(client
->references
>= 0);
2351 ns_client_log(client
, NS_LOGCATEGORY_CLIENT
,
2352 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(10),
2353 "ns_client_detach: ref = %d", client
->references
);
2354 (void)exit_check(client
);
2358 ns_client_shuttingdown(ns_client_t
*client
) {
2359 return (ISC_TF(client
->newstate
== NS_CLIENTSTATE_FREED
));
2363 ns_client_replace(ns_client_t
*client
) {
2364 isc_result_t result
;
2368 result
= ns_clientmgr_createclients(client
->manager
,
2369 1, client
->interface
,
2370 (TCP_CLIENT(client
) ?
2371 ISC_TRUE
: ISC_FALSE
));
2372 if (result
!= ISC_R_SUCCESS
)
2376 * The responsibility for listening for new requests is hereby
2377 * transferred to the new client. Therefore, the old client
2378 * should refrain from listening for any more requests.
2380 client
->mortal
= ISC_TRUE
;
2382 return (ISC_R_SUCCESS
);
2390 clientmgr_destroy(ns_clientmgr_t
*manager
) {
2395 REQUIRE(ISC_LIST_EMPTY(manager
->active
));
2396 REQUIRE(ISC_LIST_EMPTY(manager
->inactive
));
2397 REQUIRE(ISC_LIST_EMPTY(manager
->recursing
));
2399 MTRACE("clientmgr_destroy");
2402 for (i
= 0; i
< NMCTXS
; i
++) {
2403 if (manager
->mctxpool
[i
] != NULL
)
2404 isc_mem_detach(&manager
->mctxpool
[i
]);
2408 DESTROYLOCK(&manager
->lock
);
2410 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2414 ns_clientmgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
2415 isc_timermgr_t
*timermgr
, ns_clientmgr_t
**managerp
)
2417 ns_clientmgr_t
*manager
;
2418 isc_result_t result
;
2423 manager
= isc_mem_get(mctx
, sizeof(*manager
));
2424 if (manager
== NULL
)
2425 return (ISC_R_NOMEMORY
);
2427 result
= isc_mutex_init(&manager
->lock
);
2428 if (result
!= ISC_R_SUCCESS
)
2429 goto cleanup_manager
;
2431 manager
->mctx
= mctx
;
2432 manager
->taskmgr
= taskmgr
;
2433 manager
->timermgr
= timermgr
;
2434 manager
->exiting
= ISC_FALSE
;
2435 ISC_LIST_INIT(manager
->active
);
2436 ISC_LIST_INIT(manager
->inactive
);
2437 ISC_LIST_INIT(manager
->recursing
);
2439 manager
->nextmctx
= 0;
2440 for (i
= 0; i
< NMCTXS
; i
++)
2441 manager
->mctxpool
[i
] = NULL
; /* will be created on-demand */
2443 manager
->magic
= MANAGER_MAGIC
;
2447 *managerp
= manager
;
2449 return (ISC_R_SUCCESS
);
2452 isc_mem_put(manager
->mctx
, manager
, sizeof(*manager
));
2458 ns_clientmgr_destroy(ns_clientmgr_t
**managerp
) {
2459 ns_clientmgr_t
*manager
;
2460 ns_client_t
*client
;
2461 isc_boolean_t need_destroy
= ISC_FALSE
;
2463 REQUIRE(managerp
!= NULL
);
2464 manager
= *managerp
;
2465 REQUIRE(VALID_MANAGER(manager
));
2469 LOCK(&manager
->lock
);
2471 manager
->exiting
= ISC_TRUE
;
2473 for (client
= ISC_LIST_HEAD(manager
->recursing
);
2475 client
= ISC_LIST_NEXT(client
, link
))
2476 isc_task_shutdown(client
->task
);
2478 for (client
= ISC_LIST_HEAD(manager
->active
);
2480 client
= ISC_LIST_NEXT(client
, link
))
2481 isc_task_shutdown(client
->task
);
2483 for (client
= ISC_LIST_HEAD(manager
->inactive
);
2485 client
= ISC_LIST_NEXT(client
, link
))
2486 isc_task_shutdown(client
->task
);
2488 if (ISC_LIST_EMPTY(manager
->active
) &&
2489 ISC_LIST_EMPTY(manager
->inactive
) &&
2490 ISC_LIST_EMPTY(manager
->recursing
))
2491 need_destroy
= ISC_TRUE
;
2493 UNLOCK(&manager
->lock
);
2496 clientmgr_destroy(manager
);
2502 ns_clientmgr_createclients(ns_clientmgr_t
*manager
, unsigned int n
,
2503 ns_interface_t
*ifp
, isc_boolean_t tcp
)
2505 isc_result_t result
= ISC_R_SUCCESS
;
2507 ns_client_t
*client
;
2509 REQUIRE(VALID_MANAGER(manager
));
2512 MTRACE("createclients");
2515 * We MUST lock the manager lock for the entire client creation
2516 * process. If we didn't do this, then a client could get a
2517 * shutdown event and disappear out from under us.
2520 LOCK(&manager
->lock
);
2522 for (i
= 0; i
< n
; i
++) {
2525 * Allocate a client. First try to get a recycled one;
2526 * if that fails, make a new one.
2528 client
= ISC_LIST_HEAD(manager
->inactive
);
2529 if (client
!= NULL
) {
2531 ISC_LIST_UNLINK(manager
->inactive
, client
, link
);
2532 client
->list
= NULL
;
2534 MTRACE("create new");
2535 result
= client_create(manager
, &client
);
2536 if (result
!= ISC_R_SUCCESS
)
2540 ns_interface_attach(ifp
, &client
->interface
);
2541 client
->state
= NS_CLIENTSTATE_READY
;
2542 INSIST(client
->recursionquota
== NULL
);
2545 client
->attributes
|= NS_CLIENTATTR_TCP
;
2546 isc_socket_attach(ifp
->tcpsocket
,
2547 &client
->tcplistener
);
2551 dns_dispatch_attach(ifp
->udpdispatch
,
2553 sock
= dns_dispatch_getsocket(client
->dispatch
);
2554 isc_socket_attach(sock
, &client
->udpsocket
);
2556 client
->manager
= manager
;
2557 ISC_LIST_APPEND(manager
->active
, client
, link
);
2558 client
->list
= &manager
->active
;
2560 INSIST(client
->nctls
== 0);
2562 ev
= &client
->ctlevent
;
2563 isc_task_send(client
->task
, &ev
);
2567 * We managed to create at least one client, so we
2570 result
= ISC_R_SUCCESS
;
2573 UNLOCK(&manager
->lock
);
2579 ns_client_getsockaddr(ns_client_t
*client
) {
2580 return (&client
->peeraddr
);
2584 ns_client_checkaclsilent(ns_client_t
*client
, isc_sockaddr_t
*sockaddr
,
2585 dns_acl_t
*acl
, isc_boolean_t default_allow
)
2587 isc_result_t result
;
2589 isc_netaddr_t netaddr
;
2599 if (sockaddr
== NULL
)
2600 isc_netaddr_fromsockaddr(&netaddr
, &client
->peeraddr
);
2602 isc_netaddr_fromsockaddr(&netaddr
, sockaddr
);
2604 result
= dns_acl_match(&netaddr
, client
->signer
, acl
,
2605 &ns_g_server
->aclenv
,
2608 if (result
!= ISC_R_SUCCESS
)
2609 goto deny
; /* Internal error, already logged. */
2612 goto deny
; /* Negative match or no match. */
2615 return (ISC_R_SUCCESS
);
2618 return (DNS_R_REFUSED
);
2622 ns_client_checkacl(ns_client_t
*client
, isc_sockaddr_t
*sockaddr
,
2623 const char *opname
, dns_acl_t
*acl
,
2624 isc_boolean_t default_allow
, int log_level
)
2626 isc_result_t result
=
2627 ns_client_checkaclsilent(client
, sockaddr
, acl
, default_allow
);
2629 if (result
== ISC_R_SUCCESS
)
2630 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2631 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(3),
2632 "%s approved", opname
);
2634 ns_client_log(client
, DNS_LOGCATEGORY_SECURITY
,
2635 NS_LOGMODULE_CLIENT
,
2636 log_level
, "%s denied", opname
);
2641 ns_client_name(ns_client_t
*client
, char *peerbuf
, size_t len
) {
2642 if (client
->peeraddr_valid
)
2643 isc_sockaddr_format(&client
->peeraddr
, peerbuf
, len
);
2645 snprintf(peerbuf
, len
, "@%p", client
);
2649 ns_client_logv(ns_client_t
*client
, isc_logcategory_t
*category
,
2650 isc_logmodule_t
*module
, int level
, const char *fmt
, va_list ap
)
2653 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2654 const char *name
= "";
2655 const char *sep
= "";
2657 vsnprintf(msgbuf
, sizeof(msgbuf
), fmt
, ap
);
2658 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
2659 if (client
->view
!= NULL
&& strcmp(client
->view
->name
, "_bind") != 0 &&
2660 strcmp(client
->view
->name
, "_default") != 0) {
2661 name
= client
->view
->name
;
2665 isc_log_write(ns_g_lctx
, category
, module
, level
,
2666 "client %s%s%s: %s", peerbuf
, sep
, name
, msgbuf
);
2670 ns_client_log(ns_client_t
*client
, isc_logcategory_t
*category
,
2671 isc_logmodule_t
*module
, int level
, const char *fmt
, ...)
2675 if (! isc_log_wouldlog(ns_g_lctx
, level
))
2679 ns_client_logv(client
, category
, module
, level
, fmt
, ap
);
2684 ns_client_aclmsg(const char *msg
, dns_name_t
*name
, dns_rdatatype_t type
,
2685 dns_rdataclass_t rdclass
, char *buf
, size_t len
)
2687 char namebuf
[DNS_NAME_FORMATSIZE
];
2688 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
2689 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
2691 dns_name_format(name
, namebuf
, sizeof(namebuf
));
2692 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
2693 dns_rdataclass_format(rdclass
, classbuf
, sizeof(classbuf
));
2694 (void)snprintf(buf
, len
, "%s '%s/%s/%s'", msg
, namebuf
, typebuf
,
2699 ns_client_dumpmessage(ns_client_t
*client
, const char *reason
) {
2700 isc_buffer_t buffer
;
2703 isc_result_t result
;
2706 * Note that these are multiline debug messages. We want a newline
2707 * to appear in the log after each message.
2711 buf
= isc_mem_get(client
->mctx
, len
);
2714 isc_buffer_init(&buffer
, buf
, len
);
2715 result
= dns_message_totext(client
->message
,
2716 &dns_master_style_debug
,
2718 if (result
== ISC_R_NOSPACE
) {
2719 isc_mem_put(client
->mctx
, buf
, len
);
2721 } else if (result
== ISC_R_SUCCESS
)
2722 ns_client_log(client
, NS_LOGCATEGORY_UNMATCHED
,
2723 NS_LOGMODULE_CLIENT
, ISC_LOG_DEBUG(1),
2725 (int)isc_buffer_usedlength(&buffer
),
2727 } while (result
== ISC_R_NOSPACE
);
2730 isc_mem_put(client
->mctx
, buf
, len
);
2734 ns_client_dumprecursing(FILE *f
, ns_clientmgr_t
*manager
) {
2735 ns_client_t
*client
;
2736 char namebuf
[DNS_NAME_FORMATSIZE
];
2737 char peerbuf
[ISC_SOCKADDR_FORMATSIZE
];
2741 REQUIRE(VALID_MANAGER(manager
));
2743 LOCK(&manager
->lock
);
2744 client
= ISC_LIST_HEAD(manager
->recursing
);
2745 while (client
!= NULL
) {
2746 ns_client_name(client
, peerbuf
, sizeof(peerbuf
));
2747 if (client
->view
!= NULL
&&
2748 strcmp(client
->view
->name
, "_bind") != 0 &&
2749 strcmp(client
->view
->name
, "_default") != 0) {
2750 name
= client
->view
->name
;
2756 dns_name_format(client
->query
.qname
, namebuf
, sizeof(namebuf
));
2757 fprintf(f
, "; client %s%s%s: '%s' requesttime %d\n",
2758 peerbuf
, sep
, name
, namebuf
, client
->requesttime
);
2759 client
= ISC_LIST_NEXT(client
, link
);
2761 UNLOCK(&manager
->lock
);
2765 ns_client_qnamereplace(ns_client_t
*client
, dns_name_t
*name
) {
2767 if (client
->manager
!= NULL
)
2768 LOCK(&client
->manager
->lock
);
2769 if (client
->query
.restarts
> 0) {
2771 * client->query.qname was dynamically allocated.
2773 dns_message_puttempname(client
->message
,
2774 &client
->query
.qname
);
2776 client
->query
.qname
= name
;
2777 if (client
->manager
!= NULL
)
2778 UNLOCK(&client
->manager
->lock
);