2 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: client.c,v 1.176.2.13.4.26 2005/07/27 02:53:14 marka Exp $ */
22 #include <isc/formatcheck.h>
23 #include <isc/mutex.h>
25 #include <isc/print.h>
26 #include <isc/stdio.h>
27 #include <isc/string.h>
29 #include <isc/timer.h>
33 #include <dns/dispatch.h>
34 #include <dns/events.h>
35 #include <dns/message.h>
36 #include <dns/rcode.h>
37 #include <dns/resolver.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
46 #include <named/interfacemgr.h>
47 #include <named/log.h>
48 #include <named/notify.h>
49 #include <named/server.h>
50 #include <named/update.h>
59 * All client state changes, other than that from idle to listening, occur
60 * as a result of events. This guarantees serialization and avoids the
63 * If a routine is ever created that allows someone other than the client's
64 * task to change the client, then the client will have to be locked.
67 #define NS_CLIENT_TRACE
68 #ifdef NS_CLIENT_TRACE
69 #define CTRACE(m) ns_client_log(client, \
70 NS_LOGCATEGORY_CLIENT, \
71 NS_LOGMODULE_CLIENT, \
74 #define MTRACE(m) isc_log_write(ns_g_lctx, \
75 NS_LOGCATEGORY_GENERAL, \
76 NS_LOGMODULE_CLIENT, \
78 "clientmgr @%p: %s", manager, (m))
80 #define CTRACE(m) ((void)(m))
81 #define MTRACE(m) ((void)(m))
84 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
86 #define TCP_BUFFER_SIZE (65535 + 2)
87 #define SEND_BUFFER_SIZE 4096
88 #define RECV_BUFFER_SIZE 4096
94 isc_taskmgr_t * taskmgr;
95 isc_timermgr_t * timermgr;
98 isc_boolean_t exiting;
99 client_list_t active; /* Active clients */
100 client_list_t recursing; /* Recursing clients */
101 client_list_t inactive; /* To be recycled */
104 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
105 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
108 * Client object states. Ordering is significant: higher-numbered
109 * states are generally "more active", meaning that the client can
110 * have more dynamically allocated data, outstanding events, etc.
111 * In the list below, any such properties listed for state N
112 * also apply to any state > N.
114 * To force the client into a less active state, set client->newstate
115 * to that state and call exit_check(). This will cause any
116 * activities defined for higher-numbered states to be aborted.
119 #define NS_CLIENTSTATE_FREED 0
121 * The client object no longer exists.
124 #define NS_CLIENTSTATE_INACTIVE 1
126 * The client object exists and has a task and timer.
127 * Its "query" struct and sendbuf are initialized.
128 * It is on the client manager's list of inactive clients.
129 * It has a message and OPT, both in the reset state.
132 #define NS_CLIENTSTATE_READY 2
134 * The client object is either a TCP or a UDP one, and
135 * it is associated with a network interface. It is on the
136 * client manager's list of active clients.
138 * If it is a TCP client object, it has a TCP listener socket
139 * and an outstanding TCP listen request.
141 * If it is a UDP client object, it has a UDP listener socket
142 * and an outstanding UDP receive request.
145 #define NS_CLIENTSTATE_READING 3
147 * The client object is a TCP client object that has received
148 * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
149 * outstanding TCP read request. This state is not used for
150 * UDP client objects.
153 #define NS_CLIENTSTATE_WORKING 4
155 * The client object has received a request and is working
156 * on it. It has a view, and it may have any of a non-reset OPT,
157 * recursion quota, and an outstanding write request.
160 #define NS_CLIENTSTATE_MAX 9
162 * Sentinel value used to indicate "no state". When client->newstate
163 * has this value, we are not attempting to exit the current state.
164 * Must be greater than any valid state.
168 static void client_read(ns_client_t *client);
169 static void client_accept(ns_client_t *client);
170 static void client_udprecv(ns_client_t *client);
171 static void clientmgr_destroy(ns_clientmgr_t *manager);
172 static isc_boolean_t exit_check(ns_client_t *client);
173 static void ns_client_endrequest(ns_client_t *client);
174 static void ns_client_checkactive(ns_client_t *client);
175 static void client_start(isc_task_t *task, isc_event_t *event);
176 static void client_request(isc_task_t *task, isc_event_t *event);
177 static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
180 ns_client_recursing(ns_client_t *client) {
181 REQUIRE(NS_CLIENT_VALID(client));
183 LOCK(&client->manager->lock);
184 ISC_LIST_UNLINK(*client->list, client, link);
185 ISC_LIST_APPEND(client->manager->recursing, client, link);
186 client->list = &client->manager->recursing;
187 UNLOCK(&client->manager->lock);
191 ns_client_killoldestquery(ns_client_t *client) {
193 REQUIRE(NS_CLIENT_VALID(client));
195 LOCK(&client->manager->lock);
196 oldest = ISC_LIST_HEAD(client->manager->recursing);
197 if (oldest != NULL) {
198 ns_query_cancel(oldest);
199 ISC_LIST_UNLINK(*oldest->list, oldest, link);
200 ISC_LIST_APPEND(client->manager->active, oldest, link);
201 oldest->list = &client->manager->active;
203 UNLOCK(&client->manager->lock);
207 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
209 isc_interval_t interval;
211 isc_interval_set(&interval, seconds, 0);
212 result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
213 &interval, ISC_FALSE);
214 client->timerset = ISC_TRUE;
215 if (result != ISC_R_SUCCESS) {
216 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
217 NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
218 "setting timeout: %s",
219 isc_result_totext(result));
220 /* Continue anyway. */
225 * Check for a deactivation or shutdown request and take appropriate
226 * action. Returns ISC_TRUE if either is in progress; in this case
227 * the caller must no longer use the client object as it may have been
231 exit_check(ns_client_t *client) {
232 ns_clientmgr_t *locked_manager = NULL;
233 ns_clientmgr_t *destroy_manager = NULL;
235 REQUIRE(NS_CLIENT_VALID(client));
237 if (client->state <= client->newstate)
238 return (ISC_FALSE); /* Business as usual. */
240 INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
243 * We need to detach from the view early when shutting down
244 * the server to break the following vicious circle:
246 * - The resolver will not shut down until the view refcount is zero
247 * - The view refcount does not go to zero until all clients detach
248 * - The client does not detach from the view until references is zero
249 * - references does not go to zero until the resolver has shut down
251 * Keep the view attached until any outstanding updates complete.
253 if (client->nupdates == 0 &&
254 client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
255 dns_view_detach(&client->view);
257 if (client->state == NS_CLIENTSTATE_WORKING) {
258 INSIST(client->newstate <= NS_CLIENTSTATE_READING);
260 * Let the update processing complete.
262 if (client->nupdates > 0)
265 * We are trying to abort request processing.
267 if (client->nsends > 0) {
268 isc_socket_t *socket;
269 if (TCP_CLIENT(client))
270 socket = client->tcpsocket;
272 socket = client->udpsocket;
273 isc_socket_cancel(socket, client->task,
274 ISC_SOCKCANCEL_SEND);
277 if (! (client->nsends == 0 && client->nrecvs == 0 &&
278 client->references == 0))
281 * Still waiting for I/O cancel completion.
282 * or lingering references.
287 * I/O cancel is complete. Burn down all state
288 * related to the current request.
290 ns_client_endrequest(client);
292 client->state = NS_CLIENTSTATE_READING;
293 INSIST(client->recursionquota == NULL);
294 if (NS_CLIENTSTATE_READING == client->newstate) {
296 client->newstate = NS_CLIENTSTATE_MAX;
297 return (ISC_TRUE); /* We're done. */
301 if (client->state == NS_CLIENTSTATE_READING) {
303 * We are trying to abort the current TCP connection,
306 INSIST(client->recursionquota == NULL);
307 INSIST(client->newstate <= NS_CLIENTSTATE_READY);
308 if (client->nreads > 0)
309 dns_tcpmsg_cancelread(&client->tcpmsg);
310 if (! client->nreads == 0) {
311 /* Still waiting for read cancel completion. */
315 if (client->tcpmsg_valid) {
316 dns_tcpmsg_invalidate(&client->tcpmsg);
317 client->tcpmsg_valid = ISC_FALSE;
319 if (client->tcpsocket != NULL) {
321 isc_socket_detach(&client->tcpsocket);
324 if (client->tcpquota != NULL)
325 isc_quota_detach(&client->tcpquota);
327 if (client->timerset) {
328 (void)isc_timer_reset(client->timer,
329 isc_timertype_inactive,
330 NULL, NULL, ISC_TRUE);
331 client->timerset = ISC_FALSE;
334 client->peeraddr_valid = ISC_FALSE;
336 client->state = NS_CLIENTSTATE_READY;
337 INSIST(client->recursionquota == NULL);
340 * Now the client is ready to accept a new TCP connection
341 * or UDP request, but we may have enough clients doing
342 * that already. Check whether this client needs to remain
343 * active and force it to go inactive if not.
345 ns_client_checkactive(client);
347 if (NS_CLIENTSTATE_READY == client->newstate) {
348 if (TCP_CLIENT(client)) {
349 client_accept(client);
351 client_udprecv(client);
352 client->newstate = NS_CLIENTSTATE_MAX;
357 if (client->state == NS_CLIENTSTATE_READY) {
358 INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
360 * We are trying to enter the inactive state.
362 if (client->naccepts > 0)
363 isc_socket_cancel(client->tcplistener, client->task,
364 ISC_SOCKCANCEL_ACCEPT);
366 if (! (client->naccepts == 0)) {
367 /* Still waiting for accept cancel completion. */
370 /* Accept cancel is complete. */
372 if (client->nrecvs > 0)
373 isc_socket_cancel(client->udpsocket, client->task,
374 ISC_SOCKCANCEL_RECV);
375 if (! (client->nrecvs == 0)) {
376 /* Still waiting for recv cancel completion. */
379 /* Recv cancel is complete. */
381 if (client->nctls > 0) {
382 /* Still waiting for control event to be delivered */
386 /* Deactivate the client. */
387 if (client->interface)
388 ns_interface_detach(&client->interface);
390 INSIST(client->naccepts == 0);
391 INSIST(client->recursionquota == NULL);
392 if (client->tcplistener != NULL)
393 isc_socket_detach(&client->tcplistener);
395 if (client->udpsocket != NULL)
396 isc_socket_detach(&client->udpsocket);
398 if (client->dispatch != NULL)
399 dns_dispatch_detach(&client->dispatch);
401 client->attributes = 0;
402 client->mortal = ISC_FALSE;
404 LOCK(&client->manager->lock);
406 * Put the client on the inactive list. If we are aiming for
407 * the "freed" state, it will be removed from the inactive
408 * list shortly, and we need to keep the manager locked until
409 * that has been done, lest the manager decide to reactivate
410 * the dying client inbetween.
412 locked_manager = client->manager;
413 ISC_LIST_UNLINK(*client->list, client, link);
414 ISC_LIST_APPEND(client->manager->inactive, client, link);
415 client->list = &client->manager->inactive;
416 client->state = NS_CLIENTSTATE_INACTIVE;
417 INSIST(client->recursionquota == NULL);
419 if (client->state == client->newstate) {
420 client->newstate = NS_CLIENTSTATE_MAX;
425 if (client->state == NS_CLIENTSTATE_INACTIVE) {
426 INSIST(client->newstate == NS_CLIENTSTATE_FREED);
428 * We are trying to free the client.
430 * When "shuttingdown" is true, either the task has received
431 * its shutdown event or no shutdown event has ever been
432 * set up. Thus, we have no outstanding shutdown
433 * event at this point.
435 REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
437 INSIST(client->recursionquota == NULL);
439 ns_query_free(client);
440 isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
441 isc_event_free((isc_event_t **)&client->sendevent);
442 isc_event_free((isc_event_t **)&client->recvevent);
443 isc_timer_detach(&client->timer);
445 if (client->tcpbuf != NULL)
446 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
447 if (client->opt != NULL) {
448 INSIST(dns_rdataset_isassociated(client->opt));
449 dns_rdataset_disassociate(client->opt);
450 dns_message_puttemprdataset(client->message, &client->opt);
452 dns_message_destroy(&client->message);
453 if (client->manager != NULL) {
454 ns_clientmgr_t *manager = client->manager;
455 if (locked_manager == NULL) {
456 LOCK(&manager->lock);
457 locked_manager = manager;
459 ISC_LIST_UNLINK(*client->list, client, link);
461 if (manager->exiting &&
462 ISC_LIST_EMPTY(manager->active) &&
463 ISC_LIST_EMPTY(manager->inactive) &&
464 ISC_LIST_EMPTY(manager->recursing))
465 destroy_manager = manager;
468 * Detaching the task must be done after unlinking from
469 * the manager's lists because the manager accesses
472 if (client->task != NULL)
473 isc_task_detach(&client->task);
477 isc_mem_put(client->mctx, client, sizeof(*client));
483 if (locked_manager != NULL) {
484 UNLOCK(&locked_manager->lock);
485 locked_manager = NULL;
489 * Only now is it safe to destroy the client manager (if needed),
490 * because we have accessed its lock for the last time.
492 if (destroy_manager != NULL)
493 clientmgr_destroy(destroy_manager);
499 * The client's task has received the client's control event
500 * as part of the startup process.
503 client_start(isc_task_t *task, isc_event_t *event) {
504 ns_client_t *client = (ns_client_t *) event->ev_arg;
506 INSIST(task == client->task);
510 INSIST(client->nctls == 1);
513 if (exit_check(client))
516 if (TCP_CLIENT(client)) {
517 client_accept(client);
519 client_udprecv(client);
525 * The client's task has received a shutdown event.
528 client_shutdown(isc_task_t *task, isc_event_t *event) {
531 REQUIRE(event != NULL);
532 REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
533 client = event->ev_arg;
534 REQUIRE(NS_CLIENT_VALID(client));
535 REQUIRE(task == client->task);
541 isc_event_free(&event);
543 if (client->shutdown != NULL) {
544 (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
545 client->shutdown = NULL;
546 client->shutdown_arg = NULL;
549 client->newstate = NS_CLIENTSTATE_FREED;
550 (void)exit_check(client);
554 ns_client_endrequest(ns_client_t *client) {
555 INSIST(client->naccepts == 0);
556 INSIST(client->nreads == 0);
557 INSIST(client->nsends == 0);
558 INSIST(client->nrecvs == 0);
559 INSIST(client->nupdates == 0);
560 INSIST(client->state == NS_CLIENTSTATE_WORKING);
562 CTRACE("endrequest");
564 if (client->next != NULL) {
565 (client->next)(client);
569 if (client->view != NULL)
570 dns_view_detach(&client->view);
571 if (client->opt != NULL) {
572 INSIST(dns_rdataset_isassociated(client->opt));
573 dns_rdataset_disassociate(client->opt);
574 dns_message_puttemprdataset(client->message, &client->opt);
577 client->udpsize = 512;
578 client->extflags = 0;
579 dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
581 if (client->recursionquota != NULL)
582 isc_quota_detach(&client->recursionquota);
585 * Clear all client attributes that are specific to
586 * the request; that's all except the TCP flag.
588 client->attributes &= NS_CLIENTATTR_TCP;
592 ns_client_checkactive(ns_client_t *client) {
593 if (client->mortal) {
595 * This client object should normally go inactive
596 * at this point, but if we have fewer active client
597 * objects than desired due to earlier quota exhaustion,
598 * keep it active to make up for the shortage.
600 isc_boolean_t need_another_client = ISC_FALSE;
601 if (TCP_CLIENT(client)) {
602 LOCK(&client->interface->lock);
603 if (client->interface->ntcpcurrent <
604 client->interface->ntcptarget)
605 need_another_client = ISC_TRUE;
606 UNLOCK(&client->interface->lock);
609 * The UDP client quota is enforced by making
610 * requests fail rather than by not listening
611 * for new ones. Therefore, there is always a
612 * full set of UDP clients listening.
615 if (! need_another_client) {
617 * We don't need this client object. Recycle it.
619 if (client->newstate >= NS_CLIENTSTATE_INACTIVE)
620 client->newstate = NS_CLIENTSTATE_INACTIVE;
626 ns_client_next(ns_client_t *client, isc_result_t result) {
629 REQUIRE(NS_CLIENT_VALID(client));
630 REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
631 client->state == NS_CLIENTSTATE_READING);
635 if (result != ISC_R_SUCCESS)
636 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
637 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
638 "request failed: %s", isc_result_totext(result));
641 * An error processing a TCP request may have left
642 * the connection out of sync. To be safe, we always
643 * sever the connection when result != ISC_R_SUCCESS.
645 if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
646 newstate = NS_CLIENTSTATE_READING;
648 newstate = NS_CLIENTSTATE_READY;
650 if (client->newstate > newstate)
651 client->newstate = newstate;
652 (void)exit_check(client);
657 client_senddone(isc_task_t *task, isc_event_t *event) {
659 isc_socketevent_t *sevent = (isc_socketevent_t *) event;
661 REQUIRE(sevent != NULL);
662 REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
663 client = sevent->ev_arg;
664 REQUIRE(NS_CLIENT_VALID(client));
665 REQUIRE(task == client->task);
666 REQUIRE(sevent == client->sendevent);
672 if (sevent->result != ISC_R_SUCCESS)
673 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
674 NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
675 "error sending response: %s",
676 isc_result_totext(sevent->result));
678 INSIST(client->nsends > 0);
681 if (client->tcpbuf != NULL) {
682 INSIST(TCP_CLIENT(client));
683 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
684 client->tcpbuf = NULL;
687 if (exit_check(client))
690 ns_client_next(client, ISC_R_SUCCESS);
694 * We only want to fail with ISC_R_NOSPACE when called from
695 * ns_client_sendraw() and not when called from ns_client_send(),
696 * tcpbuffer is NULL when called from ns_client_sendraw() and
697 * length != 0. tcpbuffer != NULL when called from ns_client_send()
702 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
703 isc_buffer_t *tcpbuffer, isc_uint32_t length,
704 unsigned char *sendbuf, unsigned char **datap)
707 isc_uint32_t bufsize;
710 INSIST(datap != NULL);
711 INSIST((tcpbuffer == NULL && length != 0) ||
712 (tcpbuffer != NULL && length == 0));
714 if (TCP_CLIENT(client)) {
715 INSIST(client->tcpbuf == NULL);
716 if (length + 2 > TCP_BUFFER_SIZE) {
717 result = ISC_R_NOSPACE;
720 client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
721 if (client->tcpbuf == NULL) {
722 result = ISC_R_NOMEMORY;
725 data = client->tcpbuf;
726 if (tcpbuffer != NULL) {
727 isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
728 isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
730 isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
731 INSIST(length <= 0xffff);
732 isc_buffer_putuint16(buffer, (isc_uint16_t)length);
736 if (client->udpsize < SEND_BUFFER_SIZE)
737 bufsize = client->udpsize;
739 bufsize = SEND_BUFFER_SIZE;
740 if (length > bufsize) {
741 result = ISC_R_NOSPACE;
744 isc_buffer_init(buffer, data, bufsize);
747 result = ISC_R_SUCCESS;
754 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
755 struct in6_pktinfo *pktinfo;
758 isc_sockaddr_t *address;
759 isc_socket_t *socket;
760 isc_netaddr_t netaddr;
762 unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
764 if (TCP_CLIENT(client)) {
765 socket = client->tcpsocket;
768 socket = client->udpsocket;
769 address = &client->peeraddr;
771 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
772 if (ns_g_server->blackholeacl != NULL &&
773 dns_acl_match(&netaddr, NULL,
774 ns_g_server->blackholeacl,
775 &ns_g_server->aclenv,
776 &match, NULL) == ISC_R_SUCCESS &&
778 return (DNS_R_BLACKHOLED);
779 sockflags |= ISC_SOCKFLAG_NORETRY;
782 if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
783 (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
784 pktinfo = &client->pktinfo;
788 isc_buffer_usedregion(buffer, &r);
792 result = isc_socket_sendto2(socket, &r, client->task,
794 client->sendevent, sockflags);
795 if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
797 if (result == ISC_R_SUCCESS)
798 client_senddone(client->task,
799 (isc_event_t *)client->sendevent);
800 result = ISC_R_SUCCESS;
806 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
812 unsigned char sendbuf[SEND_BUFFER_SIZE];
814 REQUIRE(NS_CLIENT_VALID(client));
818 mr = dns_message_getrawmessage(message);
820 result = ISC_R_UNEXPECTEDEND;
824 result = client_allocsendbuf(client, &buffer, NULL, mr->length,
826 if (result != ISC_R_SUCCESS)
830 * Copy message to buffer and fixup id.
832 isc_buffer_availableregion(&buffer, &r);
833 result = isc_buffer_copyregion(&buffer, mr);
834 if (result != ISC_R_SUCCESS)
836 r.base[0] = (client->message->id >> 8) & 0xff;
837 r.base[1] = client->message->id & 0xff;
839 result = client_sendpkg(client, &buffer);
840 if (result == ISC_R_SUCCESS)
844 if (client->tcpbuf != NULL) {
845 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
846 client->tcpbuf = NULL;
848 ns_client_next(client, result);
852 ns_client_send(ns_client_t *client) {
856 isc_buffer_t tcpbuffer;
859 isc_boolean_t cleanup_cctx = ISC_FALSE;
860 unsigned char sendbuf[SEND_BUFFER_SIZE];
861 unsigned int dnssec_opts;
862 unsigned int preferred_glue;
864 REQUIRE(NS_CLIENT_VALID(client));
868 if ((client->attributes & NS_CLIENTATTR_RA) != 0)
869 client->message->flags |= DNS_MESSAGEFLAG_RA;
871 if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
874 dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC;
877 if (client->view != NULL) {
878 if (client->view->preferred_glue == dns_rdatatype_a)
879 preferred_glue = DNS_MESSAGERENDER_PREFER_A;
880 else if (client->view->preferred_glue == dns_rdatatype_aaaa)
881 preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
885 * XXXRTH The following doesn't deal with TCP buffer resizing.
887 result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
889 if (result != ISC_R_SUCCESS)
892 result = dns_compress_init(&cctx, -1, client->mctx);
893 if (result != ISC_R_SUCCESS)
895 cleanup_cctx = ISC_TRUE;
897 result = dns_message_renderbegin(client->message, &cctx, &buffer);
898 if (result != ISC_R_SUCCESS)
900 if (client->opt != NULL) {
901 result = dns_message_setopt(client->message, client->opt);
903 * XXXRTH dns_message_setopt() should probably do this...
906 if (result != ISC_R_SUCCESS)
909 result = dns_message_rendersection(client->message,
910 DNS_SECTION_QUESTION, 0);
911 if (result == ISC_R_NOSPACE) {
912 client->message->flags |= DNS_MESSAGEFLAG_TC;
915 if (result != ISC_R_SUCCESS)
917 result = dns_message_rendersection(client->message,
919 DNS_MESSAGERENDER_PARTIAL |
921 if (result == ISC_R_NOSPACE) {
922 client->message->flags |= DNS_MESSAGEFLAG_TC;
925 if (result != ISC_R_SUCCESS)
927 result = dns_message_rendersection(client->message,
928 DNS_SECTION_AUTHORITY,
929 DNS_MESSAGERENDER_PARTIAL |
931 if (result == ISC_R_NOSPACE) {
932 client->message->flags |= DNS_MESSAGEFLAG_TC;
935 if (result != ISC_R_SUCCESS)
937 result = dns_message_rendersection(client->message,
938 DNS_SECTION_ADDITIONAL,
939 preferred_glue | dnssec_opts);
940 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
943 result = dns_message_renderend(client->message);
945 if (result != ISC_R_SUCCESS)
949 dns_compress_invalidate(&cctx);
950 cleanup_cctx = ISC_FALSE;
953 if (TCP_CLIENT(client)) {
954 isc_buffer_usedregion(&buffer, &r);
955 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
956 isc_buffer_add(&tcpbuffer, r.length);
957 result = client_sendpkg(client, &tcpbuffer);
959 result = client_sendpkg(client, &buffer);
960 if (result == ISC_R_SUCCESS)
964 if (client->tcpbuf != NULL) {
965 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
966 client->tcpbuf = NULL;
970 dns_compress_invalidate(&cctx);
972 ns_client_next(client, result);
976 ns_client_error(ns_client_t *client, isc_result_t result) {
978 dns_message_t *message;
980 REQUIRE(NS_CLIENT_VALID(client));
984 message = client->message;
985 rcode = dns_result_torcode(result);
988 * Message may be an in-progress reply that we had trouble
989 * with, in which case QR will be set. We need to clear QR before
990 * calling dns_message_reply() to avoid triggering an assertion.
992 message->flags &= ~DNS_MESSAGEFLAG_QR;
994 * AA and AD shouldn't be set.
996 message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
997 result = dns_message_reply(message, ISC_TRUE);
998 if (result != ISC_R_SUCCESS) {
1000 * It could be that we've got a query with a good header,
1001 * but a bad question section, so we try again with
1002 * want_question_section set to ISC_FALSE.
1004 result = dns_message_reply(message, ISC_FALSE);
1005 if (result != ISC_R_SUCCESS) {
1006 ns_client_next(client, result);
1010 message->rcode = rcode;
1013 * FORMERR loop avoidance: If we sent a FORMERR message
1014 * with the same ID to the same client less than two
1015 * seconds ago, assume that we are in an infinite error
1016 * packet dialog with a server for some protocol whose
1017 * error responses look enough like DNS queries to
1018 * elicit a FORMERR response. Drop a packet to break
1021 if (rcode == dns_rcode_formerr) {
1022 if (isc_sockaddr_equal(&client->peeraddr,
1023 &client->formerrcache.addr) &&
1024 message->id == client->formerrcache.id &&
1025 client->requesttime - client->formerrcache.time < 2) {
1027 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1028 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1029 "possible error packet loop, "
1031 ns_client_next(client, result);
1034 client->formerrcache.addr = client->peeraddr;
1035 client->formerrcache.time = client->requesttime;
1036 client->formerrcache.id = message->id;
1038 ns_client_send(client);
1041 static inline isc_result_t
1042 client_addopt(ns_client_t *client) {
1043 dns_rdataset_t *rdataset;
1044 dns_rdatalist_t *rdatalist;
1046 isc_result_t result;
1048 dns_resolver_t *resolver;
1049 isc_uint16_t udpsize;
1051 REQUIRE(client->opt == NULL); /* XXXRTH free old. */
1054 result = dns_message_gettemprdatalist(client->message, &rdatalist);
1055 if (result != ISC_R_SUCCESS)
1058 result = dns_message_gettemprdata(client->message, &rdata);
1059 if (result != ISC_R_SUCCESS)
1062 result = dns_message_gettemprdataset(client->message, &rdataset);
1063 if (result != ISC_R_SUCCESS)
1065 dns_rdataset_init(rdataset);
1067 rdatalist->type = dns_rdatatype_opt;
1068 rdatalist->covers = 0;
1071 * Set the maximum UDP buffer size.
1073 view = client->view;
1074 resolver = (view != NULL) ? view->resolver : NULL;
1075 if (resolver != NULL)
1076 udpsize = dns_resolver_getudpsize(resolver);
1078 udpsize = ns_g_udpsize;
1079 rdatalist->rdclass = udpsize;
1082 * Set EXTENDED-RCODE, VERSION and Z to 0.
1084 rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1087 * No ENDS options in the default case.
1091 rdata->rdclass = rdatalist->rdclass;
1092 rdata->type = rdatalist->type;
1095 ISC_LIST_INIT(rdatalist->rdata);
1096 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1097 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1100 client->opt = rdataset;
1102 return (ISC_R_SUCCESS);
1105 static inline isc_boolean_t
1106 allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1108 isc_result_t result;
1112 result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1114 if (result == ISC_R_SUCCESS && match > 0)
1120 * Handle an incoming request event from the socket (UDP case)
1121 * or tcpmsg (TCP case).
1124 client_request(isc_task_t *task, isc_event_t *event) {
1125 ns_client_t *client;
1126 isc_socketevent_t *sevent;
1127 isc_result_t result;
1128 isc_result_t sigresult = ISC_R_SUCCESS;
1129 isc_buffer_t *buffer;
1130 isc_buffer_t tbuffer;
1132 dns_rdataset_t *opt;
1133 isc_boolean_t ra; /* Recursion available. */
1134 isc_netaddr_t netaddr;
1135 isc_netaddr_t destaddr;
1139 isc_boolean_t notimp;
1141 REQUIRE(event != NULL);
1142 client = event->ev_arg;
1143 REQUIRE(NS_CLIENT_VALID(client));
1144 REQUIRE(task == client->task);
1146 INSIST(client->recursionquota == NULL);
1148 INSIST(client->state ==
1149 TCP_CLIENT(client) ?
1150 NS_CLIENTSTATE_READING :
1151 NS_CLIENTSTATE_READY);
1153 if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1154 INSIST(!TCP_CLIENT(client));
1155 sevent = (isc_socketevent_t *)event;
1156 REQUIRE(sevent == client->recvevent);
1157 isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1158 isc_buffer_add(&tbuffer, sevent->n);
1160 result = sevent->result;
1161 if (result == ISC_R_SUCCESS) {
1162 client->peeraddr = sevent->address;
1163 client->peeraddr_valid = ISC_TRUE;
1165 if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1166 client->attributes |= NS_CLIENTATTR_PKTINFO;
1167 client->pktinfo = sevent->pktinfo;
1169 if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1170 client->attributes |= NS_CLIENTATTR_MULTICAST;
1173 INSIST(TCP_CLIENT(client));
1174 REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1175 REQUIRE(event->ev_sender == &client->tcpmsg);
1176 buffer = &client->tcpmsg.buffer;
1177 result = client->tcpmsg.result;
1178 INSIST(client->nreads == 1);
1180 * client->peeraddr was set when the connection was accepted.
1185 if (exit_check(client))
1187 client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1189 isc_task_getcurrenttime(task, &client->requesttime);
1190 client->now = client->requesttime;
1192 if (result != ISC_R_SUCCESS) {
1193 if (TCP_CLIENT(client)) {
1194 ns_client_next(client, result);
1196 if (result != ISC_R_CANCELED)
1197 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1198 NS_LOGMODULE_CLIENT,
1200 "UDP client handler shutting "
1201 "down due to fatal receive "
1203 isc_result_totext(result));
1204 isc_task_shutdown(client->task);
1209 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1211 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1212 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1214 TCP_CLIENT(client) ? "TCP" : "UDP");
1217 * Check the blackhole ACL for UDP only, since TCP is done in
1220 if (!TCP_CLIENT(client)) {
1222 if (ns_g_server->blackholeacl != NULL &&
1223 dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1224 &ns_g_server->aclenv,
1225 &match, NULL) == ISC_R_SUCCESS &&
1228 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1229 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1230 "blackholed UDP datagram");
1231 ns_client_next(client, ISC_R_SUCCESS);
1237 * Silently drop multicast requests for the present.
1238 * XXXMPA look at when/if mDNS spec stabilizes.
1240 if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1241 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1242 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1243 "dropping multicast request");
1244 ns_client_next(client, DNS_R_REFUSED);
1247 result = dns_message_peekheader(buffer, &id, &flags);
1248 if (result != ISC_R_SUCCESS) {
1250 * There isn't enough header to determine whether
1251 * this was a request or a response. Drop it.
1253 ns_client_next(client, result);
1258 * The client object handles requests, not responses.
1259 * If this is a UDP response, forward it to the dispatcher.
1260 * If it's a TCP response, discard it here.
1262 if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1263 if (TCP_CLIENT(client)) {
1264 CTRACE("unexpected response");
1265 ns_client_next(client, DNS_R_FORMERR);
1268 dns_dispatch_importrecv(client->dispatch, event);
1269 ns_client_next(client, ISC_R_SUCCESS);
1275 * It's a request. Parse it.
1277 result = dns_message_parse(client->message, buffer, 0);
1278 if (result != ISC_R_SUCCESS) {
1280 * Parsing the request failed. Send a response
1281 * (typically FORMERR or SERVFAIL).
1283 ns_client_error(client, result);
1287 switch (client->message->opcode) {
1288 case dns_opcode_query:
1289 case dns_opcode_update:
1290 case dns_opcode_notify:
1293 case dns_opcode_iquery:
1299 client->message->rcode = dns_rcode_noerror;
1301 /* RFC1123 section 6.1.3.2 */
1302 if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1303 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1308 opt = dns_message_getopt(client->message);
1310 unsigned int version;
1313 * Set the client's UDP buffer size.
1315 client->udpsize = opt->rdclass;
1318 * If the requested UDP buffer size is less than 512,
1319 * ignore it and use 512.
1321 if (client->udpsize < 512)
1322 client->udpsize = 512;
1325 * Get the flags out of the OPT record.
1327 client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1330 * Create an OPT for our reply.
1332 result = client_addopt(client);
1333 if (result != ISC_R_SUCCESS) {
1334 ns_client_error(client, result);
1339 * Do we understand this version of ENDS?
1341 * XXXRTH need library support for this!
1343 version = (opt->ttl & 0x00FF0000) >> 16;
1345 ns_client_error(client, DNS_R_BADVERS);
1350 if (client->message->rdclass == 0) {
1351 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1352 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1353 "message class could not be determined");
1354 ns_client_dumpmessage(client,
1355 "message class could not be determined");
1356 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1361 * Determine the destination address. If the receiving interface is
1362 * bound to a specific address, we simply use it regardless of the
1363 * address family. All IPv4 queries should fall into this case.
1364 * Otherwise, if this is a TCP query, get the address from the
1365 * receiving socket (this needs a system call and can be heavy).
1366 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1368 * If all the attempts fail (this can happen due to memory shortage,
1369 * etc), we regard this as an error for safety.
1371 if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1372 isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
1374 result = ISC_R_FAILURE;
1376 if (TCP_CLIENT(client)) {
1377 isc_sockaddr_t destsockaddr;
1379 result = isc_socket_getsockname(client->tcpsocket,
1381 if (result == ISC_R_SUCCESS)
1382 isc_netaddr_fromsockaddr(&destaddr,
1385 if (result != ISC_R_SUCCESS &&
1386 client->interface->addr.type.sa.sa_family == AF_INET6 &&
1387 (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1388 isc_uint32_t zone = 0;
1391 * XXXJT technically, we should convert the receiving
1392 * interface ID to a proper scope zone ID. However,
1393 * due to the fact there is no standard API for this,
1394 * we only handle link-local addresses and use the
1395 * interface index as link ID. Despite the assumption,
1396 * it should cover most typical cases.
1398 if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1399 zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex;
1401 isc_netaddr_fromin6(&destaddr,
1402 &client->pktinfo.ipi6_addr);
1403 isc_netaddr_setzone(&destaddr, zone);
1404 result = ISC_R_SUCCESS;
1406 if (result != ISC_R_SUCCESS) {
1407 UNEXPECTED_ERROR(__FILE__, __LINE__,
1408 "failed to get request's "
1410 isc_result_totext(result));
1416 * Find a view that matches the client's source address.
1418 for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1420 view = ISC_LIST_NEXT(view, link)) {
1421 if (client->message->rdclass == view->rdclass ||
1422 client->message->rdclass == dns_rdataclass_any)
1424 dns_name_t *tsig = NULL;
1425 sigresult = dns_message_rechecksig(client->message,
1427 if (sigresult == ISC_R_SUCCESS)
1428 tsig = client->message->tsigname;
1430 if (allowed(&netaddr, tsig, view->matchclients) &&
1431 allowed(&destaddr, tsig, view->matchdestinations) &&
1432 !((client->message->flags & DNS_MESSAGEFLAG_RD)
1433 == 0 && view->matchrecursiveonly))
1435 dns_view_attach(view, &client->view);
1442 char classname[DNS_RDATACLASS_FORMATSIZE];
1445 * Do a dummy TSIG verification attempt so that the
1446 * response will have a TSIG if the query did, as
1447 * required by RFC2845.
1452 dns_message_resetsig(client->message);
1454 r = dns_message_getrawmessage(client->message);
1455 isc_buffer_init(&b, r->base, r->length);
1456 isc_buffer_add(&b, r->length);
1457 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
1459 dns_rdataclass_format(client->message->rdclass, classname,
1461 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1462 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1463 "no matching view in class '%s'", classname);
1464 ns_client_dumpmessage(client, "no matching view in class");
1465 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1469 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1470 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1471 "using view '%s'", view->name);
1474 * Check for a signature. We log bad signatures regardless of
1475 * whether they ultimately cause the request to be rejected or
1476 * not. We do not log the lack of a signature unless we are
1479 client->signer = NULL;
1480 dns_name_init(&client->signername, NULL);
1481 result = dns_message_signer(client->message, &client->signername);
1482 if (result == ISC_R_SUCCESS) {
1483 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1484 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1485 "request has valid signature");
1486 client->signer = &client->signername;
1487 } else if (result == ISC_R_NOTFOUND) {
1488 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1489 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1490 "request is not signed");
1491 } else if (result == DNS_R_NOIDENTITY) {
1492 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1493 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1494 "request is signed by a nonauthoritative key");
1498 dns_name_t *name = NULL;
1500 isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1501 RUNTIME_CHECK(dns_tsigrcode_totext(client->message->tsigstatus,
1502 &b) == ISC_R_SUCCESS);
1503 tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1504 /* There is a signature, but it is bad. */
1505 if (dns_message_gettsig(client->message, &name) != NULL) {
1506 char namebuf[DNS_NAME_FORMATSIZE];
1507 dns_name_format(name, namebuf, sizeof(namebuf));
1508 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1509 NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1510 "request has invalid signature: "
1511 "TSIG %s: %s (%s)", namebuf,
1512 isc_result_totext(result), tsigrcode);
1514 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1515 NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1516 "request has invalid signature: %s (%s)",
1517 isc_result_totext(result), tsigrcode);
1520 * Accept update messages signed by unknown keys so that
1521 * update forwarding works transparently through slaves
1522 * that don't have all the same keys as the master.
1524 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1525 client->message->opcode == dns_opcode_update)) {
1526 ns_client_error(client, sigresult);
1532 * Decide whether recursive service is available to this client.
1533 * We do this here rather than in the query code so that we can
1534 * set the RA bit correctly on all kinds of responses, not just
1535 * responses to ordinary queries.
1538 if (client->view->resolver != NULL &&
1539 client->view->recursion == ISC_TRUE &&
1540 ns_client_checkaclsilent(client, client->view->recursionacl,
1541 ISC_TRUE) == ISC_R_SUCCESS)
1545 client->attributes |= NS_CLIENTATTR_RA;
1547 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1548 ISC_LOG_DEBUG(3), ra ? "recursion available" :
1549 "recursion not available");
1552 * Dispatch the request.
1554 switch (client->message->opcode) {
1555 case dns_opcode_query:
1557 ns_query_start(client);
1559 case dns_opcode_update:
1561 ns_client_settimeout(client, 60);
1562 ns_update_start(client, sigresult);
1564 case dns_opcode_notify:
1566 ns_client_settimeout(client, 60);
1567 ns_notify_start(client);
1569 case dns_opcode_iquery:
1571 ns_client_error(client, DNS_R_NOTIMP);
1574 CTRACE("unknown opcode");
1575 ns_client_error(client, DNS_R_NOTIMP);
1583 client_timeout(isc_task_t *task, isc_event_t *event) {
1584 ns_client_t *client;
1586 REQUIRE(event != NULL);
1587 REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1588 event->ev_type == ISC_TIMEREVENT_IDLE);
1589 client = event->ev_arg;
1590 REQUIRE(NS_CLIENT_VALID(client));
1591 REQUIRE(task == client->task);
1592 REQUIRE(client->timer != NULL);
1598 isc_event_free(&event);
1600 if (client->shutdown != NULL) {
1601 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1602 client->shutdown = NULL;
1603 client->shutdown_arg = NULL;
1606 if (client->newstate > NS_CLIENTSTATE_READY)
1607 client->newstate = NS_CLIENTSTATE_READY;
1608 (void)exit_check(client);
1612 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
1613 ns_client_t *client;
1614 isc_result_t result;
1617 * Caller must be holding the manager lock.
1619 * Note: creating a client does not add the client to the
1620 * manager's client list or set the client's manager pointer.
1621 * The caller is responsible for that.
1624 REQUIRE(clientp != NULL && *clientp == NULL);
1626 client = isc_mem_get(manager->mctx, sizeof(*client));
1628 return (ISC_R_NOMEMORY);
1630 client->task = NULL;
1631 result = isc_task_create(manager->taskmgr, 0, &client->task);
1632 if (result != ISC_R_SUCCESS)
1633 goto cleanup_client;
1634 isc_task_setname(client->task, "client", client);
1636 client->timer = NULL;
1637 result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
1638 NULL, NULL, client->task, client_timeout,
1639 client, &client->timer);
1640 if (result != ISC_R_SUCCESS)
1642 client->timerset = ISC_FALSE;
1644 client->message = NULL;
1645 result = dns_message_create(manager->mctx, DNS_MESSAGE_INTENTPARSE,
1647 if (result != ISC_R_SUCCESS)
1650 /* XXXRTH Hardwired constants */
1652 client->sendevent = (isc_socketevent_t *)
1653 isc_event_allocate(manager->mctx, client,
1654 ISC_SOCKEVENT_SENDDONE,
1655 client_senddone, client,
1656 sizeof(isc_socketevent_t));
1657 if (client->sendevent == NULL) {
1658 result = ISC_R_NOMEMORY;
1659 goto cleanup_message;
1662 client->recvbuf = isc_mem_get(manager->mctx, RECV_BUFFER_SIZE);
1663 if (client->recvbuf == NULL) {
1664 result = ISC_R_NOMEMORY;
1665 goto cleanup_sendevent;
1668 client->recvevent = (isc_socketevent_t *)
1669 isc_event_allocate(manager->mctx, client,
1670 ISC_SOCKEVENT_RECVDONE,
1671 client_request, client,
1672 sizeof(isc_socketevent_t));
1673 if (client->recvevent == NULL) {
1674 result = ISC_R_NOMEMORY;
1675 goto cleanup_recvbuf;
1678 client->magic = NS_CLIENT_MAGIC;
1679 client->mctx = manager->mctx;
1680 client->manager = NULL;
1681 client->state = NS_CLIENTSTATE_INACTIVE;
1682 client->newstate = NS_CLIENTSTATE_MAX;
1683 client->naccepts = 0;
1687 client->nupdates = 0;
1689 client->references = 0;
1690 client->attributes = 0;
1691 client->view = NULL;
1692 client->dispatch = NULL;
1693 client->udpsocket = NULL;
1694 client->tcplistener = NULL;
1695 client->tcpsocket = NULL;
1696 client->tcpmsg_valid = ISC_FALSE;
1697 client->tcpbuf = NULL;
1699 client->udpsize = 512;
1700 client->extflags = 0;
1701 client->next = NULL;
1702 client->shutdown = NULL;
1703 client->shutdown_arg = NULL;
1704 dns_name_init(&client->signername, NULL);
1705 client->mortal = ISC_FALSE;
1706 client->tcpquota = NULL;
1707 client->recursionquota = NULL;
1708 client->interface = NULL;
1709 client->peeraddr_valid = ISC_FALSE;
1710 ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
1711 NS_EVENT_CLIENTCONTROL, client_start, client, client,
1714 * Initialize FORMERR cache to sentinel value that will not match
1715 * any actual FORMERR response.
1717 isc_sockaddr_any(&client->formerrcache.addr);
1718 client->formerrcache.time = 0;
1719 client->formerrcache.id = 0;
1720 ISC_LINK_INIT(client, link);
1721 client->list = NULL;
1724 * We call the init routines for the various kinds of client here,
1725 * after we have created an otherwise valid client, because some
1726 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
1728 result = ns_query_init(client);
1729 if (result != ISC_R_SUCCESS)
1730 goto cleanup_recvevent;
1732 result = isc_task_onshutdown(client->task, client_shutdown, client);
1733 if (result != ISC_R_SUCCESS)
1740 return (ISC_R_SUCCESS);
1743 ns_query_free(client);
1746 isc_event_free((isc_event_t **)&client->recvevent);
1749 isc_mem_put(manager->mctx, client->recvbuf, RECV_BUFFER_SIZE);
1752 isc_event_free((isc_event_t **)&client->sendevent);
1757 dns_message_destroy(&client->message);
1760 isc_timer_detach(&client->timer);
1763 isc_task_detach(&client->task);
1766 isc_mem_put(manager->mctx, client, sizeof(*client));
1772 client_read(ns_client_t *client) {
1773 isc_result_t result;
1777 result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
1778 client_request, client);
1779 if (result != ISC_R_SUCCESS)
1783 * Set a timeout to limit the amount of time we will wait
1784 * for a request on this TCP connection.
1786 ns_client_settimeout(client, 30);
1788 client->state = client->newstate = NS_CLIENTSTATE_READING;
1789 INSIST(client->nreads == 0);
1790 INSIST(client->recursionquota == NULL);
1795 ns_client_next(client, result);
1799 client_newconn(isc_task_t *task, isc_event_t *event) {
1800 ns_client_t *client = event->ev_arg;
1801 isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
1802 isc_result_t result;
1804 REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
1805 REQUIRE(NS_CLIENT_VALID(client));
1806 REQUIRE(client->task == task);
1810 INSIST(client->state == NS_CLIENTSTATE_READY);
1812 INSIST(client->naccepts == 1);
1815 LOCK(&client->interface->lock);
1816 INSIST(client->interface->ntcpcurrent > 0);
1817 client->interface->ntcpcurrent--;
1818 UNLOCK(&client->interface->lock);
1821 * We must take ownership of the new socket before the exit
1822 * check to make sure it gets destroyed if we decide to exit.
1824 if (nevent->result == ISC_R_SUCCESS) {
1825 client->tcpsocket = nevent->newsocket;
1826 client->state = NS_CLIENTSTATE_READING;
1827 INSIST(client->recursionquota == NULL);
1829 (void)isc_socket_getpeername(client->tcpsocket,
1831 client->peeraddr_valid = ISC_TRUE;
1832 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1833 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1834 "new TCP connection");
1837 * XXXRTH What should we do? We're trying to accept but
1838 * it didn't work. If we just give up, then TCP
1839 * service may eventually stop.
1841 * For now, we just go idle.
1843 * Going idle is probably the right thing if the
1846 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1847 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1848 "accept failed: %s",
1849 isc_result_totext(nevent->result));
1852 if (exit_check(client))
1855 if (nevent->result == ISC_R_SUCCESS) {
1857 isc_netaddr_t netaddr;
1859 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1861 if (ns_g_server->blackholeacl != NULL &&
1862 dns_acl_match(&netaddr, NULL,
1863 ns_g_server->blackholeacl,
1864 &ns_g_server->aclenv,
1865 &match, NULL) == ISC_R_SUCCESS &&
1868 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1869 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1870 "blackholed connection attempt");
1871 client->newstate = NS_CLIENTSTATE_READY;
1872 (void)exit_check(client);
1876 INSIST(client->tcpmsg_valid == ISC_FALSE);
1877 dns_tcpmsg_init(client->mctx, client->tcpsocket,
1879 client->tcpmsg_valid = ISC_TRUE;
1882 * Let a new client take our place immediately, before
1883 * we wait for a request packet. If we don't,
1884 * telnetting to port 53 (once per CPU) will
1885 * deny service to legititmate TCP clients.
1887 result = isc_quota_attach(&ns_g_server->tcpquota,
1889 if (result == ISC_R_SUCCESS)
1890 result = ns_client_replace(client);
1891 if (result != ISC_R_SUCCESS) {
1892 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1893 NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
1894 "no more TCP clients: %s",
1895 isc_result_totext(result));
1898 client_read(client);
1902 isc_event_free(&event);
1906 client_accept(ns_client_t *client) {
1907 isc_result_t result;
1911 result = isc_socket_accept(client->tcplistener, client->task,
1912 client_newconn, client);
1913 if (result != ISC_R_SUCCESS) {
1914 UNEXPECTED_ERROR(__FILE__, __LINE__,
1915 "isc_socket_accept() failed: %s",
1916 isc_result_totext(result));
1918 * XXXRTH What should we do? We're trying to accept but
1919 * it didn't work. If we just give up, then TCP
1920 * service may eventually stop.
1922 * For now, we just go idle.
1926 INSIST(client->naccepts == 0);
1928 LOCK(&client->interface->lock);
1929 client->interface->ntcpcurrent++;
1930 UNLOCK(&client->interface->lock);
1934 client_udprecv(ns_client_t *client) {
1935 isc_result_t result;
1940 r.base = client->recvbuf;
1941 r.length = RECV_BUFFER_SIZE;
1942 result = isc_socket_recv2(client->udpsocket, &r, 1,
1943 client->task, client->recvevent, 0);
1944 if (result != ISC_R_SUCCESS) {
1945 UNEXPECTED_ERROR(__FILE__, __LINE__,
1946 "isc_socket_recv2() failed: %s",
1947 isc_result_totext(result));
1949 * This cannot happen in the current implementation, since
1950 * isc_socket_recv2() cannot fail if flags == 0.
1952 * If this does fail, we just go idle.
1956 INSIST(client->nrecvs == 0);
1961 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
1962 REQUIRE(NS_CLIENT_VALID(source));
1963 REQUIRE(targetp != NULL && *targetp == NULL);
1965 source->references++;
1966 ns_client_log(source, NS_LOGCATEGORY_CLIENT,
1967 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1968 "ns_client_attach: ref = %d", source->references);
1973 ns_client_detach(ns_client_t **clientp) {
1974 ns_client_t *client = *clientp;
1976 client->references--;
1977 INSIST(client->references >= 0);
1979 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1980 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1981 "ns_client_detach: ref = %d", client->references);
1982 (void)exit_check(client);
1986 ns_client_shuttingdown(ns_client_t *client) {
1987 return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
1991 ns_client_replace(ns_client_t *client) {
1992 isc_result_t result;
1996 result = ns_clientmgr_createclients(client->manager,
1997 1, client->interface,
1998 (TCP_CLIENT(client) ?
1999 ISC_TRUE : ISC_FALSE));
2000 if (result != ISC_R_SUCCESS)
2004 * The responsibility for listening for new requests is hereby
2005 * transferred to the new client. Therefore, the old client
2006 * should refrain from listening for any more requests.
2008 client->mortal = ISC_TRUE;
2010 return (ISC_R_SUCCESS);
2018 clientmgr_destroy(ns_clientmgr_t *manager) {
2019 REQUIRE(ISC_LIST_EMPTY(manager->active));
2020 REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2021 REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2023 MTRACE("clientmgr_destroy");
2025 DESTROYLOCK(&manager->lock);
2027 isc_mem_put(manager->mctx, manager, sizeof(*manager));
2031 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2032 isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2034 ns_clientmgr_t *manager;
2035 isc_result_t result;
2037 manager = isc_mem_get(mctx, sizeof(*manager));
2038 if (manager == NULL)
2039 return (ISC_R_NOMEMORY);
2041 result = isc_mutex_init(&manager->lock);
2042 if (result != ISC_R_SUCCESS)
2043 goto cleanup_manager;
2045 manager->mctx = mctx;
2046 manager->taskmgr = taskmgr;
2047 manager->timermgr = timermgr;
2048 manager->exiting = ISC_FALSE;
2049 ISC_LIST_INIT(manager->active);
2050 ISC_LIST_INIT(manager->inactive);
2051 ISC_LIST_INIT(manager->recursing);
2052 manager->magic = MANAGER_MAGIC;
2056 *managerp = manager;
2058 return (ISC_R_SUCCESS);
2061 isc_mem_put(manager->mctx, manager, sizeof(*manager));
2067 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2068 ns_clientmgr_t *manager;
2069 ns_client_t *client;
2070 isc_boolean_t need_destroy = ISC_FALSE;
2072 REQUIRE(managerp != NULL);
2073 manager = *managerp;
2074 REQUIRE(VALID_MANAGER(manager));
2078 LOCK(&manager->lock);
2080 manager->exiting = ISC_TRUE;
2082 for (client = ISC_LIST_HEAD(manager->recursing);
2084 client = ISC_LIST_NEXT(client, link))
2085 isc_task_shutdown(client->task);
2087 for (client = ISC_LIST_HEAD(manager->active);
2089 client = ISC_LIST_NEXT(client, link))
2090 isc_task_shutdown(client->task);
2092 for (client = ISC_LIST_HEAD(manager->inactive);
2094 client = ISC_LIST_NEXT(client, link))
2095 isc_task_shutdown(client->task);
2097 if (ISC_LIST_EMPTY(manager->active) &&
2098 ISC_LIST_EMPTY(manager->inactive) &&
2099 ISC_LIST_EMPTY(manager->recursing))
2100 need_destroy = ISC_TRUE;
2102 UNLOCK(&manager->lock);
2105 clientmgr_destroy(manager);
2111 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2112 ns_interface_t *ifp, isc_boolean_t tcp)
2114 isc_result_t result = ISC_R_SUCCESS;
2116 ns_client_t *client;
2118 REQUIRE(VALID_MANAGER(manager));
2121 MTRACE("createclients");
2124 * We MUST lock the manager lock for the entire client creation
2125 * process. If we didn't do this, then a client could get a
2126 * shutdown event and disappear out from under us.
2129 LOCK(&manager->lock);
2131 for (i = 0; i < n; i++) {
2134 * Allocate a client. First try to get a recycled one;
2135 * if that fails, make a new one.
2137 client = ISC_LIST_HEAD(manager->inactive);
2138 if (client != NULL) {
2140 ISC_LIST_UNLINK(manager->inactive, client, link);
2141 client->list = NULL;
2143 MTRACE("create new");
2144 result = client_create(manager, &client);
2145 if (result != ISC_R_SUCCESS)
2149 ns_interface_attach(ifp, &client->interface);
2150 client->state = NS_CLIENTSTATE_READY;
2151 INSIST(client->recursionquota == NULL);
2154 client->attributes |= NS_CLIENTATTR_TCP;
2155 isc_socket_attach(ifp->tcpsocket,
2156 &client->tcplistener);
2160 dns_dispatch_attach(ifp->udpdispatch,
2162 sock = dns_dispatch_getsocket(client->dispatch);
2163 isc_socket_attach(sock, &client->udpsocket);
2165 client->manager = manager;
2166 ISC_LIST_APPEND(manager->active, client, link);
2167 client->list = &manager->active;
2169 INSIST(client->nctls == 0);
2171 ev = &client->ctlevent;
2172 isc_task_send(client->task, &ev);
2176 * We managed to create at least one client, so we
2179 result = ISC_R_SUCCESS;
2182 UNLOCK(&manager->lock);
2188 ns_client_getsockaddr(ns_client_t *client) {
2189 return (&client->peeraddr);
2193 ns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl,
2194 isc_boolean_t default_allow)
2196 isc_result_t result;
2198 isc_netaddr_t netaddr;
2207 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2209 result = dns_acl_match(&netaddr, client->signer, acl,
2210 &ns_g_server->aclenv,
2212 if (result != ISC_R_SUCCESS)
2213 goto deny; /* Internal error, already logged. */
2216 goto deny; /* Negative match or no match. */
2219 return (ISC_R_SUCCESS);
2222 return (DNS_R_REFUSED);
2226 ns_client_checkacl(ns_client_t *client,
2227 const char *opname, dns_acl_t *acl,
2228 isc_boolean_t default_allow, int log_level)
2230 isc_result_t result =
2231 ns_client_checkaclsilent(client, acl, default_allow);
2233 if (result == ISC_R_SUCCESS)
2234 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2235 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2236 "%s approved", opname);
2238 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2239 NS_LOGMODULE_CLIENT,
2240 log_level, "%s denied", opname);
2245 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2246 if (client->peeraddr_valid)
2247 isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2249 snprintf(peerbuf, len, "@%p", client);
2253 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2254 isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2257 char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2258 const char *name = "";
2259 const char *sep = "";
2261 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2262 ns_client_name(client, peerbuf, sizeof(peerbuf));
2263 if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2264 strcmp(client->view->name, "_default") != 0) {
2265 name = client->view->name;
2269 isc_log_write(ns_g_lctx, category, module, level,
2270 "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2274 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2275 isc_logmodule_t *module, int level, const char *fmt, ...)
2279 if (! isc_log_wouldlog(ns_g_lctx, level))
2283 ns_client_logv(client, category, module, level, fmt, ap);
2288 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2289 dns_rdataclass_t rdclass, char *buf, size_t len)
2291 char namebuf[DNS_NAME_FORMATSIZE];
2292 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2293 char classbuf[DNS_RDATACLASS_FORMATSIZE];
2295 dns_name_format(name, namebuf, sizeof(namebuf));
2296 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2297 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2298 (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2303 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2304 isc_buffer_t buffer;
2307 isc_result_t result;
2310 * Note that these are multiline debug messages. We want a newline
2311 * to appear in the log after each message.
2315 buf = isc_mem_get(client->mctx, len);
2318 isc_buffer_init(&buffer, buf, len);
2319 result = dns_message_totext(client->message,
2320 &dns_master_style_debug,
2322 if (result == ISC_R_NOSPACE) {
2323 isc_mem_put(client->mctx, buf, len);
2325 } else if (result == ISC_R_SUCCESS)
2326 ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2327 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2329 (int)isc_buffer_usedlength(&buffer),
2331 } while (result == ISC_R_NOSPACE);
2334 isc_mem_put(client->mctx, buf, len);
2338 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2339 ns_client_t *client;
2340 char namebuf[DNS_NAME_FORMATSIZE];
2341 char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2345 REQUIRE(VALID_MANAGER(manager));
2347 LOCK(&manager->lock);
2348 client = ISC_LIST_HEAD(manager->recursing);
2349 while (client != NULL) {
2350 ns_client_name(client, peerbuf, sizeof(peerbuf));
2351 if (client->view != NULL &&
2352 strcmp(client->view->name, "_bind") != 0 &&
2353 strcmp(client->view->name, "_default") != 0) {
2354 name = client->view->name;
2360 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2361 fprintf(f, "; client %s%s%s: '%s' requesttime %d\n",
2362 peerbuf, sep, name, namebuf, client->requesttime);
2363 client = ISC_LIST_NEXT(client, link);
2365 UNLOCK(&manager->lock);