client.c revision 171577
1/*
2 * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003  Internet Software Consortium.
4 *
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.
8 *
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.
16 */
17
18/* $Id: client.c,v 1.219.18.20.14.1 2007/06/26 02:58:54 marka Exp $ */
19
20#include <config.h>
21
22#include <isc/formatcheck.h>
23#include <isc/mutex.h>
24#include <isc/once.h>
25#include <isc/platform.h>
26#include <isc/print.h>
27#include <isc/stdio.h>
28#include <isc/string.h>
29#include <isc/task.h>
30#include <isc/timer.h>
31#include <isc/util.h>
32
33#include <dns/db.h>
34#include <dns/dispatch.h>
35#include <dns/events.h>
36#include <dns/message.h>
37#include <dns/peer.h>
38#include <dns/rcode.h>
39#include <dns/rdata.h>
40#include <dns/rdataclass.h>
41#include <dns/rdatalist.h>
42#include <dns/rdataset.h>
43#include <dns/resolver.h>
44#include <dns/tsig.h>
45#include <dns/view.h>
46#include <dns/zone.h>
47
48#include <named/interfacemgr.h>
49#include <named/log.h>
50#include <named/notify.h>
51#include <named/server.h>
52#include <named/update.h>
53
54/***
55 *** Client
56 ***/
57
58/*! \file
59 * Client Routines
60 *
61 * Important note!
62 *
63 * All client state changes, other than that from idle to listening, occur
64 * as a result of events.  This guarantees serialization and avoids the
65 * need for locking.
66 *
67 * If a routine is ever created that allows someone other than the client's
68 * task to change the client, then the client will have to be locked.
69 */
70
71#define NS_CLIENT_TRACE
72#ifdef NS_CLIENT_TRACE
73#define CTRACE(m)	ns_client_log(client, \
74				      NS_LOGCATEGORY_CLIENT, \
75				      NS_LOGMODULE_CLIENT, \
76				      ISC_LOG_DEBUG(3), \
77				      "%s", (m))
78#define MTRACE(m)	isc_log_write(ns_g_lctx, \
79				      NS_LOGCATEGORY_GENERAL, \
80				      NS_LOGMODULE_CLIENT, \
81				      ISC_LOG_DEBUG(3), \
82				      "clientmgr @%p: %s", manager, (m))
83#else
84#define CTRACE(m)	((void)(m))
85#define MTRACE(m)	((void)(m))
86#endif
87
88#define TCP_CLIENT(c)	(((c)->attributes & NS_CLIENTATTR_TCP) != 0)
89
90#define TCP_BUFFER_SIZE			(65535 + 2)
91#define SEND_BUFFER_SIZE		4096
92#define RECV_BUFFER_SIZE		4096
93
94#ifdef ISC_PLATFORM_USETHREADS
95#define NMCTXS				100
96/*%<
97 * Number of 'mctx pools' for clients. (Should this be configurable?)
98 * When enabling threads, we use a pool of memory contexts shared by
99 * client objects, since concurrent access to a shared context would cause
100 * heavy contentions.  The above constant is expected to be enough for
101 * completely avoiding contentions among threads for an authoritative-only
102 * server.
103 */
104#else
105#define NMCTXS				0
106/*%<
107 * If named with built without thread, simply share manager's context.  Using
108 * a separate context in this case would simply waste memory.
109 */
110#endif
111
112/*% nameserver client manager structure */
113struct ns_clientmgr {
114	/* Unlocked. */
115	unsigned int			magic;
116	isc_mem_t *			mctx;
117	isc_taskmgr_t *			taskmgr;
118	isc_timermgr_t *		timermgr;
119	isc_mutex_t			lock;
120	/* Locked by lock. */
121	isc_boolean_t			exiting;
122	client_list_t			active; 	/*%< Active clients */
123	client_list_t			recursing; 	/*%< Recursing clients */
124	client_list_t 			inactive;	/*%< To be recycled */
125#if NMCTXS > 0
126	/*%< mctx pool for clients. */
127	unsigned int			nextmctx;
128	isc_mem_t *			mctxpool[NMCTXS];
129#endif
130};
131
132#define MANAGER_MAGIC			ISC_MAGIC('N', 'S', 'C', 'm')
133#define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, MANAGER_MAGIC)
134
135/*!
136 * Client object states.  Ordering is significant: higher-numbered
137 * states are generally "more active", meaning that the client can
138 * have more dynamically allocated data, outstanding events, etc.
139 * In the list below, any such properties listed for state N
140 * also apply to any state > N.
141 *
142 * To force the client into a less active state, set client->newstate
143 * to that state and call exit_check().  This will cause any
144 * activities defined for higher-numbered states to be aborted.
145 */
146
147#define NS_CLIENTSTATE_FREED    0
148/*%<
149 * The client object no longer exists.
150 */
151
152#define NS_CLIENTSTATE_INACTIVE 1
153/*%<
154 * The client object exists and has a task and timer.
155 * Its "query" struct and sendbuf are initialized.
156 * It is on the client manager's list of inactive clients.
157 * It has a message and OPT, both in the reset state.
158 */
159
160#define NS_CLIENTSTATE_READY    2
161/*%<
162 * The client object is either a TCP or a UDP one, and
163 * it is associated with a network interface.  It is on the
164 * client manager's list of active clients.
165 *
166 * If it is a TCP client object, it has a TCP listener socket
167 * and an outstanding TCP listen request.
168 *
169 * If it is a UDP client object, it has a UDP listener socket
170 * and an outstanding UDP receive request.
171 */
172
173#define NS_CLIENTSTATE_READING  3
174/*%<
175 * The client object is a TCP client object that has received
176 * a connection.  It has a tcpsocket, tcpmsg, TCP quota, and an
177 * outstanding TCP read request.  This state is not used for
178 * UDP client objects.
179 */
180
181#define NS_CLIENTSTATE_WORKING  4
182/*%<
183 * The client object has received a request and is working
184 * on it.  It has a view, and it may have any of a non-reset OPT,
185 * recursion quota, and an outstanding write request.
186 */
187
188#define NS_CLIENTSTATE_MAX      9
189/*%<
190 * Sentinel value used to indicate "no state".  When client->newstate
191 * has this value, we are not attempting to exit the current state.
192 * Must be greater than any valid state.
193 */
194
195/*
196 * Enable ns_client_dropport() by default.
197 */
198#ifndef NS_CLIENT_DROPPORT
199#define NS_CLIENT_DROPPORT 1
200#endif
201
202unsigned int ns_client_requests;
203
204static void client_read(ns_client_t *client);
205static void client_accept(ns_client_t *client);
206static void client_udprecv(ns_client_t *client);
207static void clientmgr_destroy(ns_clientmgr_t *manager);
208static isc_boolean_t exit_check(ns_client_t *client);
209static void ns_client_endrequest(ns_client_t *client);
210static void ns_client_checkactive(ns_client_t *client);
211static void client_start(isc_task_t *task, isc_event_t *event);
212static void client_request(isc_task_t *task, isc_event_t *event);
213static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
214
215void
216ns_client_recursing(ns_client_t *client) {
217	REQUIRE(NS_CLIENT_VALID(client));
218
219	LOCK(&client->manager->lock);
220	ISC_LIST_UNLINK(*client->list, client, link);
221	ISC_LIST_APPEND(client->manager->recursing, client, link);
222	client->list = &client->manager->recursing;
223	UNLOCK(&client->manager->lock);
224}
225
226void
227ns_client_killoldestquery(ns_client_t *client) {
228	ns_client_t *oldest;
229	REQUIRE(NS_CLIENT_VALID(client));
230
231	LOCK(&client->manager->lock);
232	oldest = ISC_LIST_HEAD(client->manager->recursing);
233	if (oldest != NULL) {
234		ns_query_cancel(oldest);
235		ISC_LIST_UNLINK(*oldest->list, oldest, link);
236		ISC_LIST_APPEND(client->manager->active, oldest, link);
237		oldest->list = &client->manager->active;
238	}
239	UNLOCK(&client->manager->lock);
240}
241
242void
243ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
244	isc_result_t result;
245	isc_interval_t interval;
246
247	isc_interval_set(&interval, seconds, 0);
248	result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
249				 &interval, ISC_FALSE);
250	client->timerset = ISC_TRUE;
251	if (result != ISC_R_SUCCESS) {
252		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
253			      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
254			      "setting timeout: %s",
255			      isc_result_totext(result));
256		/* Continue anyway. */
257	}
258}
259
260/*%
261 * Check for a deactivation or shutdown request and take appropriate
262 * action.  Returns ISC_TRUE if either is in progress; in this case
263 * the caller must no longer use the client object as it may have been
264 * freed.
265 */
266static isc_boolean_t
267exit_check(ns_client_t *client) {
268	ns_clientmgr_t *locked_manager = NULL;
269	ns_clientmgr_t *destroy_manager = NULL;
270
271	REQUIRE(NS_CLIENT_VALID(client));
272
273	if (client->state <= client->newstate)
274		return (ISC_FALSE); /* Business as usual. */
275
276	INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
277
278	/*
279	 * We need to detach from the view early when shutting down
280	 * the server to break the following vicious circle:
281	 *
282	 *  - The resolver will not shut down until the view refcount is zero
283	 *  - The view refcount does not go to zero until all clients detach
284	 *  - The client does not detach from the view until references is zero
285	 *  - references does not go to zero until the resolver has shut down
286	 *
287	 * Keep the view attached until any outstanding updates complete.
288	 */
289	if (client->nupdates == 0 &&
290	    client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
291		dns_view_detach(&client->view);
292
293	if (client->state == NS_CLIENTSTATE_WORKING) {
294		INSIST(client->newstate <= NS_CLIENTSTATE_READING);
295		/*
296		 * Let the update processing complete.
297		 */
298		if (client->nupdates > 0)
299			return (ISC_TRUE);
300		/*
301		 * We are trying to abort request processing.
302		 */
303		if (client->nsends > 0) {
304			isc_socket_t *socket;
305			if (TCP_CLIENT(client))
306				socket = client->tcpsocket;
307			else
308				socket = client->udpsocket;
309			isc_socket_cancel(socket, client->task,
310					  ISC_SOCKCANCEL_SEND);
311		}
312
313		if (! (client->nsends == 0 && client->nrecvs == 0 &&
314		       client->references == 0))
315		{
316			/*
317			 * Still waiting for I/O cancel completion.
318			 * or lingering references.
319			 */
320			return (ISC_TRUE);
321		}
322		/*
323		 * I/O cancel is complete.  Burn down all state
324		 * related to the current request.  Ensure that
325		 * the client is on the active list and not the
326		 * recursing list.
327		 */
328		LOCK(&client->manager->lock);
329		if (client->list == &client->manager->recursing) {
330			ISC_LIST_UNLINK(*client->list, client, link);
331			ISC_LIST_APPEND(client->manager->active, client, link);
332			client->list = &client->manager->active;
333		}
334		UNLOCK(&client->manager->lock);
335		ns_client_endrequest(client);
336
337		client->state = NS_CLIENTSTATE_READING;
338		INSIST(client->recursionquota == NULL);
339		if (NS_CLIENTSTATE_READING == client->newstate) {
340			client_read(client);
341			client->newstate = NS_CLIENTSTATE_MAX;
342			return (ISC_TRUE); /* We're done. */
343		}
344	}
345
346	if (client->state == NS_CLIENTSTATE_READING) {
347		/*
348		 * We are trying to abort the current TCP connection,
349		 * if any.
350		 */
351		INSIST(client->recursionquota == NULL);
352		INSIST(client->newstate <= NS_CLIENTSTATE_READY);
353		if (client->nreads > 0)
354			dns_tcpmsg_cancelread(&client->tcpmsg);
355		if (! client->nreads == 0) {
356			/* Still waiting for read cancel completion. */
357			return (ISC_TRUE);
358		}
359
360		if (client->tcpmsg_valid) {
361			dns_tcpmsg_invalidate(&client->tcpmsg);
362			client->tcpmsg_valid = ISC_FALSE;
363		}
364		if (client->tcpsocket != NULL) {
365			CTRACE("closetcp");
366			isc_socket_detach(&client->tcpsocket);
367		}
368
369		if (client->tcpquota != NULL)
370			isc_quota_detach(&client->tcpquota);
371
372		if (client->timerset) {
373			(void)isc_timer_reset(client->timer,
374					      isc_timertype_inactive,
375					      NULL, NULL, ISC_TRUE);
376			client->timerset = ISC_FALSE;
377		}
378
379		client->peeraddr_valid = ISC_FALSE;
380
381		client->state = NS_CLIENTSTATE_READY;
382		INSIST(client->recursionquota == NULL);
383
384		/*
385		 * Now the client is ready to accept a new TCP connection
386		 * or UDP request, but we may have enough clients doing
387		 * that already.  Check whether this client needs to remain
388		 * active and force it to go inactive if not.
389		 */
390		ns_client_checkactive(client);
391
392		if (NS_CLIENTSTATE_READY == client->newstate) {
393			if (TCP_CLIENT(client)) {
394				client_accept(client);
395			} else
396				client_udprecv(client);
397			client->newstate = NS_CLIENTSTATE_MAX;
398			return (ISC_TRUE);
399		}
400	}
401
402	if (client->state == NS_CLIENTSTATE_READY) {
403		INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
404		/*
405		 * We are trying to enter the inactive state.
406		 */
407		if (client->naccepts > 0)
408			isc_socket_cancel(client->tcplistener, client->task,
409					  ISC_SOCKCANCEL_ACCEPT);
410
411		if (! (client->naccepts == 0)) {
412			/* Still waiting for accept cancel completion. */
413			return (ISC_TRUE);
414		}
415		/* Accept cancel is complete. */
416
417		if (client->nrecvs > 0)
418			isc_socket_cancel(client->udpsocket, client->task,
419					  ISC_SOCKCANCEL_RECV);
420		if (! (client->nrecvs == 0)) {
421			/* Still waiting for recv cancel completion. */
422			return (ISC_TRUE);
423		}
424		/* Recv cancel is complete. */
425
426		if (client->nctls > 0) {
427			/* Still waiting for control event to be delivered */
428			return (ISC_TRUE);
429		}
430
431		/* Deactivate the client. */
432		if (client->interface)
433			ns_interface_detach(&client->interface);
434
435		INSIST(client->naccepts == 0);
436		INSIST(client->recursionquota == NULL);
437		if (client->tcplistener != NULL)
438			isc_socket_detach(&client->tcplistener);
439
440		if (client->udpsocket != NULL)
441			isc_socket_detach(&client->udpsocket);
442
443		if (client->dispatch != NULL)
444			dns_dispatch_detach(&client->dispatch);
445
446		client->attributes = 0;
447		client->mortal = ISC_FALSE;
448
449		LOCK(&client->manager->lock);
450		/*
451		 * Put the client on the inactive list.  If we are aiming for
452		 * the "freed" state, it will be removed from the inactive
453		 * list shortly, and we need to keep the manager locked until
454		 * that has been done, lest the manager decide to reactivate
455		 * the dying client inbetween.
456		 */
457		locked_manager = client->manager;
458		ISC_LIST_UNLINK(*client->list, client, link);
459		ISC_LIST_APPEND(client->manager->inactive, client, link);
460		client->list = &client->manager->inactive;
461		client->state = NS_CLIENTSTATE_INACTIVE;
462		INSIST(client->recursionquota == NULL);
463
464		if (client->state == client->newstate) {
465			client->newstate = NS_CLIENTSTATE_MAX;
466			goto unlock;
467		}
468	}
469
470	if (client->state == NS_CLIENTSTATE_INACTIVE) {
471		INSIST(client->newstate == NS_CLIENTSTATE_FREED);
472		/*
473		 * We are trying to free the client.
474		 *
475		 * When "shuttingdown" is true, either the task has received
476		 * its shutdown event or no shutdown event has ever been
477		 * set up.  Thus, we have no outstanding shutdown
478		 * event at this point.
479		 */
480		REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
481
482		INSIST(client->recursionquota == NULL);
483
484		ns_query_free(client);
485		isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
486		isc_event_free((isc_event_t **)&client->sendevent);
487		isc_event_free((isc_event_t **)&client->recvevent);
488		isc_timer_detach(&client->timer);
489
490		if (client->tcpbuf != NULL)
491			isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
492		if (client->opt != NULL) {
493			INSIST(dns_rdataset_isassociated(client->opt));
494			dns_rdataset_disassociate(client->opt);
495			dns_message_puttemprdataset(client->message, &client->opt);
496		}
497		dns_message_destroy(&client->message);
498		if (client->manager != NULL) {
499			ns_clientmgr_t *manager = client->manager;
500			if (locked_manager == NULL) {
501				LOCK(&manager->lock);
502				locked_manager = manager;
503			}
504			ISC_LIST_UNLINK(*client->list, client, link);
505			client->list = NULL;
506			if (manager->exiting &&
507			    ISC_LIST_EMPTY(manager->active) &&
508			    ISC_LIST_EMPTY(manager->inactive) &&
509			    ISC_LIST_EMPTY(manager->recursing))
510				destroy_manager = manager;
511		}
512		/*
513		 * Detaching the task must be done after unlinking from
514		 * the manager's lists because the manager accesses
515		 * client->task.
516		 */
517		if (client->task != NULL)
518			isc_task_detach(&client->task);
519
520		CTRACE("free");
521		client->magic = 0;
522		isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
523
524		goto unlock;
525	}
526
527 unlock:
528	if (locked_manager != NULL) {
529		UNLOCK(&locked_manager->lock);
530		locked_manager = NULL;
531	}
532
533	/*
534	 * Only now is it safe to destroy the client manager (if needed),
535	 * because we have accessed its lock for the last time.
536	 */
537	if (destroy_manager != NULL)
538		clientmgr_destroy(destroy_manager);
539
540	return (ISC_TRUE);
541}
542
543/*%
544 * The client's task has received the client's control event
545 * as part of the startup process.
546 */
547static void
548client_start(isc_task_t *task, isc_event_t *event) {
549	ns_client_t *client = (ns_client_t *) event->ev_arg;
550
551	INSIST(task == client->task);
552
553	UNUSED(task);
554
555	INSIST(client->nctls == 1);
556	client->nctls--;
557
558	if (exit_check(client))
559		return;
560
561	if (TCP_CLIENT(client)) {
562		client_accept(client);
563	} else {
564		client_udprecv(client);
565	}
566}
567
568
569/*%
570 * The client's task has received a shutdown event.
571 */
572static void
573client_shutdown(isc_task_t *task, isc_event_t *event) {
574	ns_client_t *client;
575
576	REQUIRE(event != NULL);
577	REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
578	client = event->ev_arg;
579	REQUIRE(NS_CLIENT_VALID(client));
580	REQUIRE(task == client->task);
581
582	UNUSED(task);
583
584	CTRACE("shutdown");
585
586	isc_event_free(&event);
587
588	if (client->shutdown != NULL) {
589		(client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
590		client->shutdown = NULL;
591		client->shutdown_arg = NULL;
592	}
593
594	client->newstate = NS_CLIENTSTATE_FREED;
595	(void)exit_check(client);
596}
597
598static void
599ns_client_endrequest(ns_client_t *client) {
600	INSIST(client->naccepts == 0);
601	INSIST(client->nreads == 0);
602	INSIST(client->nsends == 0);
603	INSIST(client->nrecvs == 0);
604	INSIST(client->nupdates == 0);
605	INSIST(client->state == NS_CLIENTSTATE_WORKING);
606
607	CTRACE("endrequest");
608
609	if (client->next != NULL) {
610		(client->next)(client);
611		client->next = NULL;
612	}
613
614	if (client->view != NULL)
615		dns_view_detach(&client->view);
616	if (client->opt != NULL) {
617		INSIST(dns_rdataset_isassociated(client->opt));
618		dns_rdataset_disassociate(client->opt);
619		dns_message_puttemprdataset(client->message, &client->opt);
620	}
621
622	client->udpsize = 512;
623	client->extflags = 0;
624	client->ednsversion = -1;
625	dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
626
627	if (client->recursionquota != NULL)
628		isc_quota_detach(&client->recursionquota);
629
630	/*
631	 * Clear all client attributes that are specific to
632	 * the request; that's all except the TCP flag.
633	 */
634	client->attributes &= NS_CLIENTATTR_TCP;
635}
636
637static void
638ns_client_checkactive(ns_client_t *client) {
639	if (client->mortal) {
640		/*
641		 * This client object should normally go inactive
642		 * at this point, but if we have fewer active client
643		 * objects than  desired due to earlier quota exhaustion,
644		 * keep it active to make up for the shortage.
645		 */
646		isc_boolean_t need_another_client = ISC_FALSE;
647		if (TCP_CLIENT(client)) {
648			LOCK(&client->interface->lock);
649			if (client->interface->ntcpcurrent <
650			    client->interface->ntcptarget)
651				need_another_client = ISC_TRUE;
652			UNLOCK(&client->interface->lock);
653		} else {
654			/*
655			 * The UDP client quota is enforced by making
656			 * requests fail rather than by not listening
657			 * for new ones.  Therefore, there is always a
658			 * full set of UDP clients listening.
659			 */
660		}
661		if (! need_another_client) {
662			/*
663			 * We don't need this client object.  Recycle it.
664			 */
665			if (client->newstate >= NS_CLIENTSTATE_INACTIVE)
666				client->newstate = NS_CLIENTSTATE_INACTIVE;
667		}
668	}
669}
670
671void
672ns_client_next(ns_client_t *client, isc_result_t result) {
673	int newstate;
674
675	REQUIRE(NS_CLIENT_VALID(client));
676	REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
677		client->state == NS_CLIENTSTATE_READING);
678
679	CTRACE("next");
680
681	if (result != ISC_R_SUCCESS)
682		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
683			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
684			      "request failed: %s", isc_result_totext(result));
685
686	/*
687	 * An error processing a TCP request may have left
688	 * the connection out of sync.  To be safe, we always
689	 * sever the connection when result != ISC_R_SUCCESS.
690	 */
691	if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
692		newstate = NS_CLIENTSTATE_READING;
693	else
694		newstate = NS_CLIENTSTATE_READY;
695
696	if (client->newstate > newstate)
697		client->newstate = newstate;
698	(void)exit_check(client);
699}
700
701
702static void
703client_senddone(isc_task_t *task, isc_event_t *event) {
704	ns_client_t *client;
705	isc_socketevent_t *sevent = (isc_socketevent_t *) event;
706
707	REQUIRE(sevent != NULL);
708	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
709	client = sevent->ev_arg;
710	REQUIRE(NS_CLIENT_VALID(client));
711	REQUIRE(task == client->task);
712	REQUIRE(sevent == client->sendevent);
713
714	UNUSED(task);
715
716	CTRACE("senddone");
717
718	if (sevent->result != ISC_R_SUCCESS)
719		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
720			      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
721			      "error sending response: %s",
722			      isc_result_totext(sevent->result));
723
724	INSIST(client->nsends > 0);
725	client->nsends--;
726
727	if (client->tcpbuf != NULL) {
728		INSIST(TCP_CLIENT(client));
729		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
730		client->tcpbuf = NULL;
731	}
732
733	if (exit_check(client))
734		return;
735
736	ns_client_next(client, ISC_R_SUCCESS);
737}
738
739/*%
740 * We only want to fail with ISC_R_NOSPACE when called from
741 * ns_client_sendraw() and not when called from ns_client_send(),
742 * tcpbuffer is NULL when called from ns_client_sendraw() and
743 * length != 0.  tcpbuffer != NULL when called from ns_client_send()
744 * and length == 0.
745 */
746
747static isc_result_t
748client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
749		    isc_buffer_t *tcpbuffer, isc_uint32_t length,
750		    unsigned char *sendbuf, unsigned char **datap)
751{
752	unsigned char *data;
753	isc_uint32_t bufsize;
754	isc_result_t result;
755
756	INSIST(datap != NULL);
757	INSIST((tcpbuffer == NULL && length != 0) ||
758	       (tcpbuffer != NULL && length == 0));
759
760	if (TCP_CLIENT(client)) {
761		INSIST(client->tcpbuf == NULL);
762		if (length + 2 > TCP_BUFFER_SIZE) {
763			result = ISC_R_NOSPACE;
764			goto done;
765		}
766		client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
767		if (client->tcpbuf == NULL) {
768			result = ISC_R_NOMEMORY;
769			goto done;
770		}
771		data = client->tcpbuf;
772		if (tcpbuffer != NULL) {
773			isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
774			isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
775		} else {
776			isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
777			INSIST(length <= 0xffff);
778			isc_buffer_putuint16(buffer, (isc_uint16_t)length);
779		}
780	} else {
781		data = sendbuf;
782		if (client->udpsize < SEND_BUFFER_SIZE)
783			bufsize = client->udpsize;
784		else
785			bufsize = SEND_BUFFER_SIZE;
786		if (length > bufsize) {
787			result = ISC_R_NOSPACE;
788			goto done;
789		}
790		isc_buffer_init(buffer, data, bufsize);
791	}
792	*datap = data;
793	result = ISC_R_SUCCESS;
794
795 done:
796	return (result);
797}
798
799static isc_result_t
800client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
801	struct in6_pktinfo *pktinfo;
802	isc_result_t result;
803	isc_region_t r;
804	isc_sockaddr_t *address;
805	isc_socket_t *socket;
806	isc_netaddr_t netaddr;
807	int match;
808	unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
809
810	if (TCP_CLIENT(client)) {
811		socket = client->tcpsocket;
812		address = NULL;
813	} else {
814		socket = client->udpsocket;
815		address = &client->peeraddr;
816
817		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
818		if (ns_g_server->blackholeacl != NULL &&
819		    dns_acl_match(&netaddr, NULL,
820			    	  ns_g_server->blackholeacl,
821				  &ns_g_server->aclenv,
822				  &match, NULL) == ISC_R_SUCCESS &&
823		    match > 0)
824			return (DNS_R_BLACKHOLED);
825		sockflags |= ISC_SOCKFLAG_NORETRY;
826	}
827
828	if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
829	    (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
830		pktinfo = &client->pktinfo;
831	else
832		pktinfo = NULL;
833
834	isc_buffer_usedregion(buffer, &r);
835
836	CTRACE("sendto");
837
838	result = isc_socket_sendto2(socket, &r, client->task,
839				    address, pktinfo,
840				    client->sendevent, sockflags);
841	if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
842		client->nsends++;
843		if (result == ISC_R_SUCCESS)
844			client_senddone(client->task,
845					(isc_event_t *)client->sendevent);
846		result = ISC_R_SUCCESS;
847	}
848	return (result);
849}
850
851void
852ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
853	isc_result_t result;
854	unsigned char *data;
855	isc_buffer_t buffer;
856	isc_region_t r;
857	isc_region_t *mr;
858	unsigned char sendbuf[SEND_BUFFER_SIZE];
859
860	REQUIRE(NS_CLIENT_VALID(client));
861
862	CTRACE("sendraw");
863
864	mr = dns_message_getrawmessage(message);
865	if (mr == NULL) {
866		result = ISC_R_UNEXPECTEDEND;
867		goto done;
868	}
869
870	result = client_allocsendbuf(client, &buffer, NULL, mr->length,
871				     sendbuf, &data);
872	if (result != ISC_R_SUCCESS)
873		goto done;
874
875	/*
876	 * Copy message to buffer and fixup id.
877	 */
878	isc_buffer_availableregion(&buffer, &r);
879	result = isc_buffer_copyregion(&buffer, mr);
880	if (result != ISC_R_SUCCESS)
881		goto done;
882	r.base[0] = (client->message->id >> 8) & 0xff;
883	r.base[1] = client->message->id & 0xff;
884
885	result = client_sendpkg(client, &buffer);
886	if (result == ISC_R_SUCCESS)
887		return;
888
889 done:
890	if (client->tcpbuf != NULL) {
891		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
892		client->tcpbuf = NULL;
893	}
894	ns_client_next(client, result);
895}
896
897void
898ns_client_send(ns_client_t *client) {
899	isc_result_t result;
900	unsigned char *data;
901	isc_buffer_t buffer;
902	isc_buffer_t tcpbuffer;
903	isc_region_t r;
904	dns_compress_t cctx;
905	isc_boolean_t cleanup_cctx = ISC_FALSE;
906	unsigned char sendbuf[SEND_BUFFER_SIZE];
907	unsigned int dnssec_opts;
908	unsigned int preferred_glue;
909
910	REQUIRE(NS_CLIENT_VALID(client));
911
912	CTRACE("send");
913
914	if ((client->attributes & NS_CLIENTATTR_RA) != 0)
915		client->message->flags |= DNS_MESSAGEFLAG_RA;
916
917	if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
918		dnssec_opts = 0;
919	else
920		dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC;
921
922	preferred_glue = 0;
923	if (client->view != NULL) {
924		if (client->view->preferred_glue == dns_rdatatype_a)
925			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
926		else if (client->view->preferred_glue == dns_rdatatype_aaaa)
927			preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
928	}
929
930	/*
931	 * XXXRTH  The following doesn't deal with TCP buffer resizing.
932	 */
933	result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
934				     sendbuf, &data);
935	if (result != ISC_R_SUCCESS)
936		goto done;
937
938	result = dns_compress_init(&cctx, -1, client->mctx);
939	if (result != ISC_R_SUCCESS)
940		goto done;
941	cleanup_cctx = ISC_TRUE;
942
943	result = dns_message_renderbegin(client->message, &cctx, &buffer);
944	if (result != ISC_R_SUCCESS)
945		goto done;
946	if (client->opt != NULL) {
947		result = dns_message_setopt(client->message, client->opt);
948		/*
949		 * XXXRTH dns_message_setopt() should probably do this...
950		 */
951		client->opt = NULL;
952		if (result != ISC_R_SUCCESS)
953			goto done;
954	}
955	result = dns_message_rendersection(client->message,
956					   DNS_SECTION_QUESTION, 0);
957	if (result == ISC_R_NOSPACE) {
958		client->message->flags |= DNS_MESSAGEFLAG_TC;
959		goto renderend;
960	}
961	if (result != ISC_R_SUCCESS)
962		goto done;
963	result = dns_message_rendersection(client->message,
964					   DNS_SECTION_ANSWER,
965					   DNS_MESSAGERENDER_PARTIAL |
966					   dnssec_opts);
967	if (result == ISC_R_NOSPACE) {
968		client->message->flags |= DNS_MESSAGEFLAG_TC;
969		goto renderend;
970	}
971	if (result != ISC_R_SUCCESS)
972		goto done;
973	result = dns_message_rendersection(client->message,
974					   DNS_SECTION_AUTHORITY,
975					   DNS_MESSAGERENDER_PARTIAL |
976					   dnssec_opts);
977	if (result == ISC_R_NOSPACE) {
978		client->message->flags |= DNS_MESSAGEFLAG_TC;
979		goto renderend;
980	}
981	if (result != ISC_R_SUCCESS)
982		goto done;
983	result = dns_message_rendersection(client->message,
984					   DNS_SECTION_ADDITIONAL,
985					   preferred_glue | dnssec_opts);
986	if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
987		goto done;
988 renderend:
989	result = dns_message_renderend(client->message);
990
991	if (result != ISC_R_SUCCESS)
992		goto done;
993
994	if (cleanup_cctx) {
995		dns_compress_invalidate(&cctx);
996		cleanup_cctx = ISC_FALSE;
997	}
998
999	if (TCP_CLIENT(client)) {
1000		isc_buffer_usedregion(&buffer, &r);
1001		isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1002		isc_buffer_add(&tcpbuffer, r.length);
1003		result = client_sendpkg(client, &tcpbuffer);
1004	} else
1005		result = client_sendpkg(client, &buffer);
1006	if (result == ISC_R_SUCCESS)
1007		return;
1008
1009 done:
1010	if (client->tcpbuf != NULL) {
1011		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1012		client->tcpbuf = NULL;
1013	}
1014
1015	if (cleanup_cctx)
1016		dns_compress_invalidate(&cctx);
1017
1018	ns_client_next(client, result);
1019}
1020
1021#if NS_CLIENT_DROPPORT
1022#define DROPPORT_NO		0
1023#define DROPPORT_REQUEST	1
1024#define DROPPORT_RESPONSE	2
1025/*%
1026 * ns_client_dropport determines if certain requests / responses
1027 * should be dropped based on the port number.
1028 *
1029 * Returns:
1030 * \li	0:	Don't drop.
1031 * \li	1:	Drop request.
1032 * \li	2:	Drop (error) response.
1033 */
1034static int
1035ns_client_dropport(in_port_t port) {
1036	switch (port) {
1037	case 7: /* echo */
1038	case 13: /* daytime */
1039	case 19: /* chargen */
1040	case 37: /* time */
1041		return (DROPPORT_REQUEST);
1042	case 464: /* kpasswd */
1043		return (DROPPORT_RESPONSE);
1044	}
1045	return (DROPPORT_NO);
1046}
1047#endif
1048
1049void
1050ns_client_error(ns_client_t *client, isc_result_t result) {
1051	dns_rcode_t rcode;
1052	dns_message_t *message;
1053
1054	REQUIRE(NS_CLIENT_VALID(client));
1055
1056	CTRACE("error");
1057
1058	message = client->message;
1059	rcode = dns_result_torcode(result);
1060
1061#if NS_CLIENT_DROPPORT
1062	/*
1063	 * Don't send FORMERR to ports on the drop port list.
1064	 */
1065	if (rcode == dns_rcode_formerr &&
1066	    ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1067	    DROPPORT_NO) {
1068		char buf[64];
1069		isc_buffer_t b;
1070
1071		isc_buffer_init(&b, buf, sizeof(buf) - 1);
1072		if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1073			isc_buffer_putstr(&b, "UNKNOWN RCODE");
1074		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1075			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1076			      "dropped error (%.*s) response: suspicious port",
1077			      (int)isc_buffer_usedlength(&b), buf);
1078		ns_client_next(client, ISC_R_SUCCESS);
1079		return;
1080	}
1081#endif
1082
1083	/*
1084	 * Message may be an in-progress reply that we had trouble
1085	 * with, in which case QR will be set.  We need to clear QR before
1086	 * calling dns_message_reply() to avoid triggering an assertion.
1087	 */
1088	message->flags &= ~DNS_MESSAGEFLAG_QR;
1089	/*
1090	 * AA and AD shouldn't be set.
1091	 */
1092	message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1093	result = dns_message_reply(message, ISC_TRUE);
1094	if (result != ISC_R_SUCCESS) {
1095		/*
1096		 * It could be that we've got a query with a good header,
1097		 * but a bad question section, so we try again with
1098		 * want_question_section set to ISC_FALSE.
1099		 */
1100		result = dns_message_reply(message, ISC_FALSE);
1101		if (result != ISC_R_SUCCESS) {
1102			ns_client_next(client, result);
1103			return;
1104		}
1105	}
1106	message->rcode = rcode;
1107
1108	/*
1109	 * FORMERR loop avoidance:  If we sent a FORMERR message
1110	 * with the same ID to the same client less than two
1111	 * seconds ago, assume that we are in an infinite error
1112	 * packet dialog with a server for some protocol whose
1113	 * error responses look enough like DNS queries to
1114	 * elicit a FORMERR response.  Drop a packet to break
1115	 * the loop.
1116	 */
1117	if (rcode == dns_rcode_formerr) {
1118		if (isc_sockaddr_equal(&client->peeraddr,
1119				       &client->formerrcache.addr) &&
1120		    message->id == client->formerrcache.id &&
1121		    client->requesttime - client->formerrcache.time < 2) {
1122			/* Drop packet. */
1123			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1124				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1125				      "possible error packet loop, "
1126				      "FORMERR dropped");
1127			ns_client_next(client, result);
1128			return;
1129		}
1130		client->formerrcache.addr = client->peeraddr;
1131		client->formerrcache.time = client->requesttime;
1132		client->formerrcache.id = message->id;
1133	}
1134	ns_client_send(client);
1135}
1136
1137static inline isc_result_t
1138client_addopt(ns_client_t *client) {
1139	dns_rdataset_t *rdataset;
1140	dns_rdatalist_t *rdatalist;
1141	dns_rdata_t *rdata;
1142	isc_result_t result;
1143	dns_view_t *view;
1144	dns_resolver_t *resolver;
1145	isc_uint16_t udpsize;
1146
1147	REQUIRE(client->opt == NULL);	/* XXXRTH free old. */
1148
1149	rdatalist = NULL;
1150	result = dns_message_gettemprdatalist(client->message, &rdatalist);
1151	if (result != ISC_R_SUCCESS)
1152		return (result);
1153	rdata = NULL;
1154	result = dns_message_gettemprdata(client->message, &rdata);
1155	if (result != ISC_R_SUCCESS)
1156		return (result);
1157	rdataset = NULL;
1158	result = dns_message_gettemprdataset(client->message, &rdataset);
1159	if (result != ISC_R_SUCCESS)
1160		return (result);
1161	dns_rdataset_init(rdataset);
1162
1163	rdatalist->type = dns_rdatatype_opt;
1164	rdatalist->covers = 0;
1165
1166	/*
1167	 * Set the maximum UDP buffer size.
1168	 */
1169	view = client->view;
1170	resolver = (view != NULL) ? view->resolver : NULL;
1171	if (resolver != NULL)
1172		udpsize = dns_resolver_getudpsize(resolver);
1173	else
1174		udpsize = ns_g_udpsize;
1175	rdatalist->rdclass = udpsize;
1176
1177	/*
1178	 * Set EXTENDED-RCODE, VERSION and Z to 0.
1179	 */
1180	rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1181
1182	/*
1183	 * No ENDS options in the default case.
1184	 */
1185	rdata->data = NULL;
1186	rdata->length = 0;
1187	rdata->rdclass = rdatalist->rdclass;
1188	rdata->type = rdatalist->type;
1189	rdata->flags = 0;
1190
1191	ISC_LIST_INIT(rdatalist->rdata);
1192	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1193	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1194		      == ISC_R_SUCCESS);
1195
1196	client->opt = rdataset;
1197
1198	return (ISC_R_SUCCESS);
1199}
1200
1201static inline isc_boolean_t
1202allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1203	int match;
1204	isc_result_t result;
1205
1206	if (acl == NULL)
1207		return (ISC_TRUE);
1208	result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1209			       &match, NULL);
1210	if (result == ISC_R_SUCCESS && match > 0)
1211		return (ISC_TRUE);
1212	return (ISC_FALSE);
1213}
1214
1215/*
1216 * Callback to see if a non-recursive query coming from 'srcaddr' to
1217 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1218 * delivered to 'myview'.
1219 *
1220 * We run this unlocked as both the view list and the interface list
1221 * are updated when the approprite task has exclusivity.
1222 */
1223isc_boolean_t
1224ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1225		 isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1226		 dns_rdataclass_t rdclass, void *arg)
1227{
1228	dns_view_t *view;
1229	dns_tsigkey_t *key;
1230	isc_netaddr_t netsrc;
1231	isc_netaddr_t netdst;
1232
1233	UNUSED(arg);
1234
1235	if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1236		return (ISC_FALSE);
1237
1238	isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1239	isc_netaddr_fromsockaddr(&netdst, dstaddr);
1240
1241	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1242	     view != NULL;
1243	     view = ISC_LIST_NEXT(view, link)) {
1244		dns_name_t *tsig = NULL;
1245
1246		if (view->matchrecursiveonly)
1247			continue;
1248
1249		if (rdclass != view->rdclass)
1250			continue;
1251
1252		if (mykey != NULL) {
1253			isc_boolean_t match;
1254			isc_result_t result;
1255
1256			tsig = &mykey->name;
1257			result = dns_view_gettsig(view, tsig, &key);
1258			if (result != ISC_R_SUCCESS)
1259				continue;
1260			match = dst_key_compare(mykey->key, key->key);
1261			dns_tsigkey_detach(&key);
1262			if (!match)
1263				continue;
1264		}
1265
1266		if (allowed(&netsrc, tsig, view->matchclients) &&
1267		    allowed(&netdst, tsig, view->matchdestinations))
1268			break;
1269	}
1270	return (ISC_TF(view == myview));
1271}
1272
1273/*
1274 * Handle an incoming request event from the socket (UDP case)
1275 * or tcpmsg (TCP case).
1276 */
1277static void
1278client_request(isc_task_t *task, isc_event_t *event) {
1279	ns_client_t *client;
1280	isc_socketevent_t *sevent;
1281	isc_result_t result;
1282	isc_result_t sigresult = ISC_R_SUCCESS;
1283	isc_buffer_t *buffer;
1284	isc_buffer_t tbuffer;
1285	dns_view_t *view;
1286	dns_rdataset_t *opt;
1287	isc_boolean_t ra; 	/* Recursion available. */
1288	isc_netaddr_t netaddr;
1289	isc_netaddr_t destaddr;
1290	int match;
1291	dns_messageid_t id;
1292	unsigned int flags;
1293	isc_boolean_t notimp;
1294
1295	REQUIRE(event != NULL);
1296	client = event->ev_arg;
1297	REQUIRE(NS_CLIENT_VALID(client));
1298	REQUIRE(task == client->task);
1299
1300	INSIST(client->recursionquota == NULL);
1301
1302	INSIST(client->state ==
1303	       TCP_CLIENT(client) ?
1304	       NS_CLIENTSTATE_READING :
1305	       NS_CLIENTSTATE_READY);
1306
1307	ns_client_requests++;
1308
1309	if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1310		INSIST(!TCP_CLIENT(client));
1311		sevent = (isc_socketevent_t *)event;
1312		REQUIRE(sevent == client->recvevent);
1313		isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1314		isc_buffer_add(&tbuffer, sevent->n);
1315		buffer = &tbuffer;
1316		result = sevent->result;
1317		if (result == ISC_R_SUCCESS) {
1318			client->peeraddr = sevent->address;
1319			client->peeraddr_valid = ISC_TRUE;
1320		}
1321		if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1322			client->attributes |= NS_CLIENTATTR_PKTINFO;
1323			client->pktinfo = sevent->pktinfo;
1324		}
1325		if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1326			client->attributes |= NS_CLIENTATTR_MULTICAST;
1327		client->nrecvs--;
1328	} else {
1329		INSIST(TCP_CLIENT(client));
1330		REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1331		REQUIRE(event->ev_sender == &client->tcpmsg);
1332		buffer = &client->tcpmsg.buffer;
1333		result = client->tcpmsg.result;
1334		INSIST(client->nreads == 1);
1335		/*
1336		 * client->peeraddr was set when the connection was accepted.
1337		 */
1338		client->nreads--;
1339	}
1340
1341	if (exit_check(client))
1342		goto cleanup;
1343	client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1344
1345	isc_task_getcurrenttime(task, &client->requesttime);
1346	client->now = client->requesttime;
1347
1348	if (result != ISC_R_SUCCESS) {
1349		if (TCP_CLIENT(client)) {
1350			ns_client_next(client, result);
1351		} else {
1352			if  (result != ISC_R_CANCELED)
1353				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1354					      NS_LOGMODULE_CLIENT,
1355					      ISC_LOG_ERROR,
1356					      "UDP client handler shutting "
1357					      "down due to fatal receive "
1358					      "error: %s",
1359					      isc_result_totext(result));
1360			isc_task_shutdown(client->task);
1361		}
1362		goto cleanup;
1363	}
1364
1365	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1366
1367#if NS_CLIENT_DROPPORT
1368	if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1369	    DROPPORT_REQUEST) {
1370		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1371			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1372			      "dropped request: suspicious port");
1373		ns_client_next(client, ISC_R_SUCCESS);
1374		goto cleanup;
1375	}
1376#endif
1377
1378	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1379		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1380		      "%s request",
1381		      TCP_CLIENT(client) ? "TCP" : "UDP");
1382
1383	/*
1384	 * Check the blackhole ACL for UDP only, since TCP is done in
1385	 * client_newconn.
1386	 */
1387	if (!TCP_CLIENT(client)) {
1388
1389		if (ns_g_server->blackholeacl != NULL &&
1390		    dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1391				  &ns_g_server->aclenv,
1392				  &match, NULL) == ISC_R_SUCCESS &&
1393		    match > 0)
1394		{
1395			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1396				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1397				      "blackholed UDP datagram");
1398			ns_client_next(client, ISC_R_SUCCESS);
1399			goto cleanup;
1400		}
1401	}
1402
1403	/*
1404	 * Silently drop multicast requests for the present.
1405	 * XXXMPA look at when/if mDNS spec stabilizes.
1406	 */
1407	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1408		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1409			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1410			      "dropping multicast request");
1411		ns_client_next(client, DNS_R_REFUSED);
1412		goto cleanup;
1413	}
1414
1415	result = dns_message_peekheader(buffer, &id, &flags);
1416	if (result != ISC_R_SUCCESS) {
1417		/*
1418		 * There isn't enough header to determine whether
1419		 * this was a request or a response.  Drop it.
1420		 */
1421		ns_client_next(client, result);
1422		goto cleanup;
1423	}
1424
1425	/*
1426	 * The client object handles requests, not responses.
1427	 * If this is a UDP response, forward it to the dispatcher.
1428	 * If it's a TCP response, discard it here.
1429	 */
1430	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1431		if (TCP_CLIENT(client)) {
1432			CTRACE("unexpected response");
1433			ns_client_next(client, DNS_R_FORMERR);
1434			goto cleanup;
1435		} else {
1436			dns_dispatch_importrecv(client->dispatch, event);
1437			ns_client_next(client, ISC_R_SUCCESS);
1438			goto cleanup;
1439		}
1440	}
1441
1442	/*
1443	 * Hash the incoming request here as it is after
1444	 * dns_dispatch_importrecv().
1445	 */
1446	dns_dispatch_hash(&client->now, sizeof(client->now));
1447	dns_dispatch_hash(isc_buffer_base(buffer),
1448			  isc_buffer_usedlength(buffer));
1449
1450	/*
1451	 * It's a request.  Parse it.
1452	 */
1453	result = dns_message_parse(client->message, buffer, 0);
1454	if (result != ISC_R_SUCCESS) {
1455		/*
1456		 * Parsing the request failed.  Send a response
1457		 * (typically FORMERR or SERVFAIL).
1458		 */
1459		ns_client_error(client, result);
1460		goto cleanup;
1461	}
1462
1463	switch (client->message->opcode) {
1464	case dns_opcode_query:
1465	case dns_opcode_update:
1466	case dns_opcode_notify:
1467		notimp = ISC_FALSE;
1468		break;
1469	case dns_opcode_iquery:
1470	default:
1471		notimp = ISC_TRUE;
1472		break;
1473	}
1474
1475	client->message->rcode = dns_rcode_noerror;
1476
1477	/* RFC1123 section 6.1.3.2 */
1478	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1479		client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1480
1481	/*
1482	 * Deal with EDNS.
1483	 */
1484	opt = dns_message_getopt(client->message);
1485	if (opt != NULL) {
1486		/*
1487		 * Set the client's UDP buffer size.
1488		 */
1489		client->udpsize = opt->rdclass;
1490
1491		/*
1492		 * If the requested UDP buffer size is less than 512,
1493		 * ignore it and use 512.
1494		 */
1495		if (client->udpsize < 512)
1496			client->udpsize = 512;
1497
1498		/*
1499		 * Get the flags out of the OPT record.
1500		 */
1501		client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1502
1503		/*
1504		 * Do we understand this version of EDNS?
1505		 *
1506		 * XXXRTH need library support for this!
1507		 */
1508		client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1509		if (client->ednsversion > 0) {
1510			result = client_addopt(client);
1511			if (result == ISC_R_SUCCESS)
1512				result = DNS_R_BADVERS;
1513			ns_client_error(client, result);
1514			goto cleanup;
1515		}
1516		/*
1517		 * Create an OPT for our reply.
1518		 */
1519		result = client_addopt(client);
1520		if (result != ISC_R_SUCCESS) {
1521			ns_client_error(client, result);
1522			goto cleanup;
1523		}
1524	}
1525
1526	if (client->message->rdclass == 0) {
1527		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1528			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1529			      "message class could not be determined");
1530		ns_client_dumpmessage(client,
1531				      "message class could not be determined");
1532		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1533		goto cleanup;
1534	}
1535
1536	/*
1537	 * Determine the destination address.  If the receiving interface is
1538	 * bound to a specific address, we simply use it regardless of the
1539	 * address family.  All IPv4 queries should fall into this case.
1540	 * Otherwise, if this is a TCP query, get the address from the
1541	 * receiving socket (this needs a system call and can be heavy).
1542	 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1543	 * supported).
1544	 * If all the attempts fail (this can happen due to memory shortage,
1545	 * etc), we regard this as an error for safety.
1546	 */
1547	if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1548		isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
1549	else {
1550		result = ISC_R_FAILURE;
1551
1552		if (TCP_CLIENT(client)) {
1553			isc_sockaddr_t destsockaddr;
1554
1555			result = isc_socket_getsockname(client->tcpsocket,
1556							&destsockaddr);
1557			if (result == ISC_R_SUCCESS)
1558				isc_netaddr_fromsockaddr(&destaddr,
1559							 &destsockaddr);
1560		}
1561		if (result != ISC_R_SUCCESS &&
1562		    client->interface->addr.type.sa.sa_family == AF_INET6 &&
1563		    (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1564			isc_uint32_t zone = 0;
1565
1566			/*
1567			 * XXXJT technically, we should convert the receiving
1568			 * interface ID to a proper scope zone ID.  However,
1569			 * due to the fact there is no standard API for this,
1570			 * we only handle link-local addresses and use the
1571			 * interface index as link ID.  Despite the assumption,
1572			 * it should cover most typical cases.
1573			 */
1574			if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1575				zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex;
1576
1577			isc_netaddr_fromin6(&destaddr,
1578					    &client->pktinfo.ipi6_addr);
1579			isc_netaddr_setzone(&destaddr, zone);
1580			result = ISC_R_SUCCESS;
1581		}
1582		if (result != ISC_R_SUCCESS) {
1583			UNEXPECTED_ERROR(__FILE__, __LINE__,
1584					 "failed to get request's "
1585					 "destination: %s",
1586					 isc_result_totext(result));
1587			goto cleanup;
1588		}
1589	}
1590
1591	/*
1592	 * Find a view that matches the client's source address.
1593	 */
1594	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1595	     view != NULL;
1596	     view = ISC_LIST_NEXT(view, link)) {
1597		if (client->message->rdclass == view->rdclass ||
1598		    client->message->rdclass == dns_rdataclass_any)
1599		{
1600			dns_name_t *tsig = NULL;
1601			sigresult = dns_message_rechecksig(client->message,
1602							   view);
1603			if (sigresult == ISC_R_SUCCESS)
1604				tsig = client->message->tsigname;
1605
1606			if (allowed(&netaddr, tsig, view->matchclients) &&
1607			    allowed(&destaddr, tsig, view->matchdestinations) &&
1608			    !((client->message->flags & DNS_MESSAGEFLAG_RD)
1609			      == 0 && view->matchrecursiveonly))
1610			{
1611				dns_view_attach(view, &client->view);
1612				break;
1613			}
1614		}
1615	}
1616
1617	if (view == NULL) {
1618		char classname[DNS_RDATACLASS_FORMATSIZE];
1619
1620		/*
1621		 * Do a dummy TSIG verification attempt so that the
1622		 * response will have a TSIG if the query did, as
1623		 * required by RFC2845.
1624		 */
1625		isc_buffer_t b;
1626		isc_region_t *r;
1627
1628		dns_message_resetsig(client->message);
1629
1630		r = dns_message_getrawmessage(client->message);
1631		isc_buffer_init(&b, r->base, r->length);
1632		isc_buffer_add(&b, r->length);
1633		(void)dns_tsig_verify(&b, client->message, NULL, NULL);
1634
1635		dns_rdataclass_format(client->message->rdclass, classname,
1636				      sizeof(classname));
1637		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1638			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1639			      "no matching view in class '%s'", classname);
1640		ns_client_dumpmessage(client, "no matching view in class");
1641		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1642		goto cleanup;
1643	}
1644
1645	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1646		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1647		      "using view '%s'", view->name);
1648
1649	/*
1650	 * Check for a signature.  We log bad signatures regardless of
1651	 * whether they ultimately cause the request to be rejected or
1652	 * not.  We do not log the lack of a signature unless we are
1653	 * debugging.
1654	 */
1655	client->signer = NULL;
1656	dns_name_init(&client->signername, NULL);
1657	result = dns_message_signer(client->message, &client->signername);
1658	if (result == ISC_R_SUCCESS) {
1659		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1660			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1661			      "request has valid signature");
1662		client->signer = &client->signername;
1663	} else if (result == ISC_R_NOTFOUND) {
1664		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1665			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1666			      "request is not signed");
1667	} else if (result == DNS_R_NOIDENTITY) {
1668		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1669			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1670			      "request is signed by a nonauthoritative key");
1671	} else {
1672		char tsigrcode[64];
1673		isc_buffer_t b;
1674		dns_name_t *name = NULL;
1675
1676		isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1677		RUNTIME_CHECK(dns_tsigrcode_totext(client->message->tsigstatus,
1678						   &b) == ISC_R_SUCCESS);
1679		tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1680		/* There is a signature, but it is bad. */
1681		if (dns_message_gettsig(client->message, &name) != NULL) {
1682			char namebuf[DNS_NAME_FORMATSIZE];
1683			dns_name_format(name, namebuf, sizeof(namebuf));
1684			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1685				      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1686				      "request has invalid signature: "
1687				      "TSIG %s: %s (%s)", namebuf,
1688				      isc_result_totext(result), tsigrcode);
1689		} else {
1690			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1691				      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1692				      "request has invalid signature: %s (%s)",
1693				      isc_result_totext(result), tsigrcode);
1694		}
1695		/*
1696		 * Accept update messages signed by unknown keys so that
1697		 * update forwarding works transparently through slaves
1698		 * that don't have all the same keys as the master.
1699		 */
1700		if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1701		      client->message->opcode == dns_opcode_update)) {
1702			ns_client_error(client, sigresult);
1703			goto cleanup;
1704		}
1705	}
1706
1707	/*
1708	 * Decide whether recursive service is available to this client.
1709	 * We do this here rather than in the query code so that we can
1710	 * set the RA bit correctly on all kinds of responses, not just
1711	 * responses to ordinary queries.  Note if you can't query the
1712	 * cache there is no point in setting RA.
1713	 */
1714	ra = ISC_FALSE;
1715	if (client->view->resolver != NULL &&
1716	    client->view->recursion == ISC_TRUE &&
1717	    ns_client_checkaclsilent(client, client->view->recursionacl,
1718				     ISC_TRUE) == ISC_R_SUCCESS &&
1719	    ns_client_checkaclsilent(client, client->view->queryacl,
1720				     ISC_TRUE) == ISC_R_SUCCESS)
1721		ra = ISC_TRUE;
1722
1723	if (ra == ISC_TRUE)
1724		client->attributes |= NS_CLIENTATTR_RA;
1725
1726	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1727		      ISC_LOG_DEBUG(3), ra ? "recursion available" :
1728		      			     "recursion not available");
1729
1730	/*
1731	 * Adjust maximum UDP response size for this client.
1732	 */
1733	if (client->udpsize > 512) {
1734		dns_peer_t *peer = NULL;
1735		isc_uint16_t udpsize = view->maxudp;
1736		(void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1737		if (peer != NULL)
1738			dns_peer_getmaxudp(peer, &udpsize);
1739		if (client->udpsize > udpsize)
1740			client->udpsize = udpsize;
1741	}
1742
1743	/*
1744	 * Dispatch the request.
1745	 */
1746	switch (client->message->opcode) {
1747	case dns_opcode_query:
1748		CTRACE("query");
1749		ns_query_start(client);
1750		break;
1751	case dns_opcode_update:
1752		CTRACE("update");
1753		ns_client_settimeout(client, 60);
1754		ns_update_start(client, sigresult);
1755		break;
1756	case dns_opcode_notify:
1757		CTRACE("notify");
1758		ns_client_settimeout(client, 60);
1759		ns_notify_start(client);
1760		break;
1761	case dns_opcode_iquery:
1762		CTRACE("iquery");
1763		ns_client_error(client, DNS_R_NOTIMP);
1764		break;
1765	default:
1766		CTRACE("unknown opcode");
1767		ns_client_error(client, DNS_R_NOTIMP);
1768	}
1769
1770 cleanup:
1771	return;
1772}
1773
1774static void
1775client_timeout(isc_task_t *task, isc_event_t *event) {
1776	ns_client_t *client;
1777
1778	REQUIRE(event != NULL);
1779	REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1780		event->ev_type == ISC_TIMEREVENT_IDLE);
1781	client = event->ev_arg;
1782	REQUIRE(NS_CLIENT_VALID(client));
1783	REQUIRE(task == client->task);
1784	REQUIRE(client->timer != NULL);
1785
1786	UNUSED(task);
1787
1788	CTRACE("timeout");
1789
1790	isc_event_free(&event);
1791
1792	if (client->shutdown != NULL) {
1793		(client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1794		client->shutdown = NULL;
1795		client->shutdown_arg = NULL;
1796	}
1797
1798	if (client->newstate > NS_CLIENTSTATE_READY)
1799		client->newstate = NS_CLIENTSTATE_READY;
1800	(void)exit_check(client);
1801}
1802
1803static isc_result_t
1804get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
1805	isc_mem_t *clientmctx;
1806#if NMCTXS > 0
1807	isc_result_t result;
1808#endif
1809
1810	/*
1811	 * Caller must be holding the manager lock.
1812	 */
1813#if NMCTXS > 0
1814	INSIST(manager->nextmctx < NMCTXS);
1815	clientmctx = manager->mctxpool[manager->nextmctx];
1816	if (clientmctx == NULL) {
1817		result = isc_mem_create(0, 0, &clientmctx);
1818		if (result != ISC_R_SUCCESS)
1819			return (result);
1820
1821		manager->mctxpool[manager->nextmctx] = clientmctx;
1822		manager->nextmctx++;
1823		if (manager->nextmctx == NMCTXS)
1824			manager->nextmctx = 0;
1825	}
1826#else
1827	clientmctx = manager->mctx;
1828#endif
1829
1830	isc_mem_attach(clientmctx, mctxp);
1831
1832	return (ISC_R_SUCCESS);
1833}
1834
1835static isc_result_t
1836client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
1837	ns_client_t *client;
1838	isc_result_t result;
1839	isc_mem_t *mctx = NULL;
1840
1841	/*
1842	 * Caller must be holding the manager lock.
1843	 *
1844	 * Note: creating a client does not add the client to the
1845	 * manager's client list or set the client's manager pointer.
1846	 * The caller is responsible for that.
1847	 */
1848
1849	REQUIRE(clientp != NULL && *clientp == NULL);
1850
1851	result = get_clientmctx(manager, &mctx);
1852	if (result != ISC_R_SUCCESS)
1853		return (result);
1854
1855	client = isc_mem_get(mctx, sizeof(*client));
1856	if (client == NULL) {
1857		isc_mem_detach(&mctx);
1858		return (ISC_R_NOMEMORY);
1859	}
1860	client->mctx = mctx;
1861
1862	client->task = NULL;
1863	result = isc_task_create(manager->taskmgr, 0, &client->task);
1864	if (result != ISC_R_SUCCESS)
1865		goto cleanup_client;
1866	isc_task_setname(client->task, "client", client);
1867
1868	client->timer = NULL;
1869	result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
1870				  NULL, NULL, client->task, client_timeout,
1871				  client, &client->timer);
1872	if (result != ISC_R_SUCCESS)
1873		goto cleanup_task;
1874	client->timerset = ISC_FALSE;
1875
1876	client->message = NULL;
1877	result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
1878				    &client->message);
1879	if (result != ISC_R_SUCCESS)
1880		goto cleanup_timer;
1881
1882	/* XXXRTH  Hardwired constants */
1883
1884	client->sendevent = (isc_socketevent_t *)
1885			    isc_event_allocate(client->mctx, client,
1886					       ISC_SOCKEVENT_SENDDONE,
1887					       client_senddone, client,
1888					       sizeof(isc_socketevent_t));
1889	if (client->sendevent == NULL) {
1890		result = ISC_R_NOMEMORY;
1891		goto cleanup_message;
1892	}
1893
1894	client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
1895	if  (client->recvbuf == NULL) {
1896		result = ISC_R_NOMEMORY;
1897		goto cleanup_sendevent;
1898	}
1899
1900	client->recvevent = (isc_socketevent_t *)
1901			    isc_event_allocate(client->mctx, client,
1902					       ISC_SOCKEVENT_RECVDONE,
1903					       client_request, client,
1904					       sizeof(isc_socketevent_t));
1905	if (client->recvevent == NULL) {
1906		result = ISC_R_NOMEMORY;
1907		goto cleanup_recvbuf;
1908	}
1909
1910	client->magic = NS_CLIENT_MAGIC;
1911	client->manager = NULL;
1912	client->state = NS_CLIENTSTATE_INACTIVE;
1913	client->newstate = NS_CLIENTSTATE_MAX;
1914	client->naccepts = 0;
1915	client->nreads = 0;
1916	client->nsends = 0;
1917	client->nrecvs = 0;
1918	client->nupdates = 0;
1919	client->nctls = 0;
1920	client->references = 0;
1921	client->attributes = 0;
1922	client->view = NULL;
1923	client->dispatch = NULL;
1924	client->udpsocket = NULL;
1925	client->tcplistener = NULL;
1926	client->tcpsocket = NULL;
1927	client->tcpmsg_valid = ISC_FALSE;
1928	client->tcpbuf = NULL;
1929	client->opt = NULL;
1930	client->udpsize = 512;
1931	client->extflags = 0;
1932	client->ednsversion = -1;
1933	client->next = NULL;
1934	client->shutdown = NULL;
1935	client->shutdown_arg = NULL;
1936	dns_name_init(&client->signername, NULL);
1937	client->mortal = ISC_FALSE;
1938	client->tcpquota = NULL;
1939	client->recursionquota = NULL;
1940	client->interface = NULL;
1941	client->peeraddr_valid = ISC_FALSE;
1942	ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
1943		       NS_EVENT_CLIENTCONTROL, client_start, client, client,
1944		       NULL, NULL);
1945	/*
1946	 * Initialize FORMERR cache to sentinel value that will not match
1947	 * any actual FORMERR response.
1948	 */
1949	isc_sockaddr_any(&client->formerrcache.addr);
1950	client->formerrcache.time = 0;
1951	client->formerrcache.id = 0;
1952	ISC_LINK_INIT(client, link);
1953	client->list = NULL;
1954
1955	/*
1956	 * We call the init routines for the various kinds of client here,
1957	 * after we have created an otherwise valid client, because some
1958	 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
1959	 */
1960	result = ns_query_init(client);
1961	if (result != ISC_R_SUCCESS)
1962		goto cleanup_recvevent;
1963
1964	result = isc_task_onshutdown(client->task, client_shutdown, client);
1965	if (result != ISC_R_SUCCESS)
1966		goto cleanup_query;
1967
1968	CTRACE("create");
1969
1970	*clientp = client;
1971
1972	return (ISC_R_SUCCESS);
1973
1974 cleanup_query:
1975	ns_query_free(client);
1976
1977 cleanup_recvevent:
1978	isc_event_free((isc_event_t **)&client->recvevent);
1979
1980 cleanup_recvbuf:
1981	isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
1982
1983 cleanup_sendevent:
1984	isc_event_free((isc_event_t **)&client->sendevent);
1985
1986	client->magic = 0;
1987
1988 cleanup_message:
1989	dns_message_destroy(&client->message);
1990
1991 cleanup_timer:
1992	isc_timer_detach(&client->timer);
1993
1994 cleanup_task:
1995	isc_task_detach(&client->task);
1996
1997 cleanup_client:
1998	isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
1999
2000	return (result);
2001}
2002
2003static void
2004client_read(ns_client_t *client) {
2005	isc_result_t result;
2006
2007	CTRACE("read");
2008
2009	result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2010					client_request, client);
2011	if (result != ISC_R_SUCCESS)
2012		goto fail;
2013
2014	/*
2015	 * Set a timeout to limit the amount of time we will wait
2016	 * for a request on this TCP connection.
2017	 */
2018	ns_client_settimeout(client, 30);
2019
2020	client->state = client->newstate = NS_CLIENTSTATE_READING;
2021	INSIST(client->nreads == 0);
2022	INSIST(client->recursionquota == NULL);
2023	client->nreads++;
2024
2025	return;
2026 fail:
2027	ns_client_next(client, result);
2028}
2029
2030static void
2031client_newconn(isc_task_t *task, isc_event_t *event) {
2032	ns_client_t *client = event->ev_arg;
2033	isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2034	isc_result_t result;
2035
2036	REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2037	REQUIRE(NS_CLIENT_VALID(client));
2038	REQUIRE(client->task == task);
2039
2040	UNUSED(task);
2041
2042	INSIST(client->state == NS_CLIENTSTATE_READY);
2043
2044	INSIST(client->naccepts == 1);
2045	client->naccepts--;
2046
2047	LOCK(&client->interface->lock);
2048	INSIST(client->interface->ntcpcurrent > 0);
2049	client->interface->ntcpcurrent--;
2050	UNLOCK(&client->interface->lock);
2051
2052	/*
2053	 * We must take ownership of the new socket before the exit
2054	 * check to make sure it gets destroyed if we decide to exit.
2055	 */
2056	if (nevent->result == ISC_R_SUCCESS) {
2057		client->tcpsocket = nevent->newsocket;
2058		client->state = NS_CLIENTSTATE_READING;
2059		INSIST(client->recursionquota == NULL);
2060
2061		(void)isc_socket_getpeername(client->tcpsocket,
2062					     &client->peeraddr);
2063		client->peeraddr_valid = ISC_TRUE;
2064		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2065			   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2066			   "new TCP connection");
2067	} else {
2068		/*
2069		 * XXXRTH  What should we do?  We're trying to accept but
2070		 *         it didn't work.  If we just give up, then TCP
2071		 *	   service may eventually stop.
2072		 *
2073		 *	   For now, we just go idle.
2074		 *
2075		 *	   Going idle is probably the right thing if the
2076		 *	   I/O was canceled.
2077		 */
2078		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2079			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2080			      "accept failed: %s",
2081			      isc_result_totext(nevent->result));
2082	}
2083
2084	if (exit_check(client))
2085		goto freeevent;
2086
2087	if (nevent->result == ISC_R_SUCCESS) {
2088		int match;
2089		isc_netaddr_t netaddr;
2090
2091		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2092
2093		if (ns_g_server->blackholeacl != NULL &&
2094		    dns_acl_match(&netaddr, NULL,
2095			    	  ns_g_server->blackholeacl,
2096				  &ns_g_server->aclenv,
2097				  &match, NULL) == ISC_R_SUCCESS &&
2098		    match > 0)
2099		{
2100			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2101				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2102				      "blackholed connection attempt");
2103			client->newstate = NS_CLIENTSTATE_READY;
2104			(void)exit_check(client);
2105			goto freeevent;
2106		}
2107
2108		INSIST(client->tcpmsg_valid == ISC_FALSE);
2109		dns_tcpmsg_init(client->mctx, client->tcpsocket,
2110				&client->tcpmsg);
2111		client->tcpmsg_valid = ISC_TRUE;
2112
2113		/*
2114		 * Let a new client take our place immediately, before
2115		 * we wait for a request packet.  If we don't,
2116		 * telnetting to port 53 (once per CPU) will
2117		 * deny service to legititmate TCP clients.
2118		 */
2119		result = isc_quota_attach(&ns_g_server->tcpquota,
2120					  &client->tcpquota);
2121		if (result == ISC_R_SUCCESS)
2122			result = ns_client_replace(client);
2123		if (result != ISC_R_SUCCESS) {
2124			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2125				      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2126				      "no more TCP clients: %s",
2127				      isc_result_totext(result));
2128		}
2129
2130		client_read(client);
2131	}
2132
2133 freeevent:
2134	isc_event_free(&event);
2135}
2136
2137static void
2138client_accept(ns_client_t *client) {
2139	isc_result_t result;
2140
2141	CTRACE("accept");
2142
2143	result = isc_socket_accept(client->tcplistener, client->task,
2144				   client_newconn, client);
2145	if (result != ISC_R_SUCCESS) {
2146		UNEXPECTED_ERROR(__FILE__, __LINE__,
2147				 "isc_socket_accept() failed: %s",
2148				 isc_result_totext(result));
2149		/*
2150		 * XXXRTH  What should we do?  We're trying to accept but
2151		 *         it didn't work.  If we just give up, then TCP
2152		 *	   service may eventually stop.
2153		 *
2154		 *	   For now, we just go idle.
2155		 */
2156		return;
2157	}
2158	INSIST(client->naccepts == 0);
2159	client->naccepts++;
2160	LOCK(&client->interface->lock);
2161	client->interface->ntcpcurrent++;
2162	UNLOCK(&client->interface->lock);
2163}
2164
2165static void
2166client_udprecv(ns_client_t *client) {
2167	isc_result_t result;
2168	isc_region_t r;
2169
2170	CTRACE("udprecv");
2171
2172	r.base = client->recvbuf;
2173	r.length = RECV_BUFFER_SIZE;
2174	result = isc_socket_recv2(client->udpsocket, &r, 1,
2175				  client->task, client->recvevent, 0);
2176	if (result != ISC_R_SUCCESS) {
2177		UNEXPECTED_ERROR(__FILE__, __LINE__,
2178				 "isc_socket_recv2() failed: %s",
2179				 isc_result_totext(result));
2180		/*
2181		 * This cannot happen in the current implementation, since
2182		 * isc_socket_recv2() cannot fail if flags == 0.
2183		 *
2184		 * If this does fail, we just go idle.
2185		 */
2186		return;
2187	}
2188	INSIST(client->nrecvs == 0);
2189	client->nrecvs++;
2190}
2191
2192void
2193ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2194	REQUIRE(NS_CLIENT_VALID(source));
2195	REQUIRE(targetp != NULL && *targetp == NULL);
2196
2197	source->references++;
2198	ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2199		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2200		      "ns_client_attach: ref = %d", source->references);
2201	*targetp = source;
2202}
2203
2204void
2205ns_client_detach(ns_client_t **clientp) {
2206	ns_client_t *client = *clientp;
2207
2208	client->references--;
2209	INSIST(client->references >= 0);
2210	*clientp = NULL;
2211	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2212		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2213		      "ns_client_detach: ref = %d", client->references);
2214	(void)exit_check(client);
2215}
2216
2217isc_boolean_t
2218ns_client_shuttingdown(ns_client_t *client) {
2219	return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2220}
2221
2222isc_result_t
2223ns_client_replace(ns_client_t *client) {
2224	isc_result_t result;
2225
2226	CTRACE("replace");
2227
2228	result = ns_clientmgr_createclients(client->manager,
2229					    1, client->interface,
2230					    (TCP_CLIENT(client) ?
2231					     ISC_TRUE : ISC_FALSE));
2232	if (result != ISC_R_SUCCESS)
2233		return (result);
2234
2235	/*
2236	 * The responsibility for listening for new requests is hereby
2237	 * transferred to the new client.  Therefore, the old client
2238	 * should refrain from listening for any more requests.
2239	 */
2240	client->mortal = ISC_TRUE;
2241
2242	return (ISC_R_SUCCESS);
2243}
2244
2245/***
2246 *** Client Manager
2247 ***/
2248
2249static void
2250clientmgr_destroy(ns_clientmgr_t *manager) {
2251#if NMCTXS > 0
2252	int i;
2253#endif
2254
2255	REQUIRE(ISC_LIST_EMPTY(manager->active));
2256	REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2257	REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2258
2259	MTRACE("clientmgr_destroy");
2260
2261#if NMCTXS > 0
2262	for (i = 0; i < NMCTXS; i++) {
2263		if (manager->mctxpool[i] != NULL)
2264			isc_mem_detach(&manager->mctxpool[i]);
2265	}
2266#endif
2267
2268	DESTROYLOCK(&manager->lock);
2269	manager->magic = 0;
2270	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2271}
2272
2273isc_result_t
2274ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2275		    isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2276{
2277	ns_clientmgr_t *manager;
2278	isc_result_t result;
2279#if NMCTXS > 0
2280	int i;
2281#endif
2282
2283	manager = isc_mem_get(mctx, sizeof(*manager));
2284	if (manager == NULL)
2285		return (ISC_R_NOMEMORY);
2286
2287	result = isc_mutex_init(&manager->lock);
2288	if (result != ISC_R_SUCCESS)
2289		goto cleanup_manager;
2290
2291	manager->mctx = mctx;
2292	manager->taskmgr = taskmgr;
2293	manager->timermgr = timermgr;
2294	manager->exiting = ISC_FALSE;
2295	ISC_LIST_INIT(manager->active);
2296	ISC_LIST_INIT(manager->inactive);
2297	ISC_LIST_INIT(manager->recursing);
2298#if NMCTXS > 0
2299	manager->nextmctx = 0;
2300	for (i = 0; i < NMCTXS; i++)
2301		manager->mctxpool[i] = NULL; /* will be created on-demand */
2302#endif
2303	manager->magic = MANAGER_MAGIC;
2304
2305	MTRACE("create");
2306
2307	*managerp = manager;
2308
2309	return (ISC_R_SUCCESS);
2310
2311 cleanup_manager:
2312	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2313
2314	return (result);
2315}
2316
2317void
2318ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2319	ns_clientmgr_t *manager;
2320	ns_client_t *client;
2321	isc_boolean_t need_destroy = ISC_FALSE;
2322
2323	REQUIRE(managerp != NULL);
2324	manager = *managerp;
2325	REQUIRE(VALID_MANAGER(manager));
2326
2327	MTRACE("destroy");
2328
2329	LOCK(&manager->lock);
2330
2331	manager->exiting = ISC_TRUE;
2332
2333	for (client = ISC_LIST_HEAD(manager->recursing);
2334	     client != NULL;
2335	     client = ISC_LIST_NEXT(client, link))
2336		isc_task_shutdown(client->task);
2337
2338	for (client = ISC_LIST_HEAD(manager->active);
2339	     client != NULL;
2340	     client = ISC_LIST_NEXT(client, link))
2341		isc_task_shutdown(client->task);
2342
2343	for (client = ISC_LIST_HEAD(manager->inactive);
2344	     client != NULL;
2345	     client = ISC_LIST_NEXT(client, link))
2346		isc_task_shutdown(client->task);
2347
2348	if (ISC_LIST_EMPTY(manager->active) &&
2349	    ISC_LIST_EMPTY(manager->inactive) &&
2350	    ISC_LIST_EMPTY(manager->recursing))
2351		need_destroy = ISC_TRUE;
2352
2353	UNLOCK(&manager->lock);
2354
2355	if (need_destroy)
2356		clientmgr_destroy(manager);
2357
2358	*managerp = NULL;
2359}
2360
2361isc_result_t
2362ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2363			   ns_interface_t *ifp, isc_boolean_t tcp)
2364{
2365	isc_result_t result = ISC_R_SUCCESS;
2366	unsigned int i;
2367	ns_client_t *client;
2368
2369	REQUIRE(VALID_MANAGER(manager));
2370	REQUIRE(n > 0);
2371
2372	MTRACE("createclients");
2373
2374	/*
2375	 * We MUST lock the manager lock for the entire client creation
2376	 * process.  If we didn't do this, then a client could get a
2377	 * shutdown event and disappear out from under us.
2378	 */
2379
2380	LOCK(&manager->lock);
2381
2382	for (i = 0; i < n; i++) {
2383		isc_event_t *ev;
2384		/*
2385		 * Allocate a client.  First try to get a recycled one;
2386		 * if that fails, make a new one.
2387		 */
2388		client = ISC_LIST_HEAD(manager->inactive);
2389		if (client != NULL) {
2390			MTRACE("recycle");
2391			ISC_LIST_UNLINK(manager->inactive, client, link);
2392			client->list = NULL;
2393		} else {
2394			MTRACE("create new");
2395			result = client_create(manager, &client);
2396			if (result != ISC_R_SUCCESS)
2397				break;
2398		}
2399
2400		ns_interface_attach(ifp, &client->interface);
2401		client->state = NS_CLIENTSTATE_READY;
2402		INSIST(client->recursionquota == NULL);
2403
2404		if (tcp) {
2405			client->attributes |= NS_CLIENTATTR_TCP;
2406			isc_socket_attach(ifp->tcpsocket,
2407					  &client->tcplistener);
2408		} else {
2409			isc_socket_t *sock;
2410
2411			dns_dispatch_attach(ifp->udpdispatch,
2412					    &client->dispatch);
2413			sock = dns_dispatch_getsocket(client->dispatch);
2414			isc_socket_attach(sock, &client->udpsocket);
2415		}
2416		client->manager = manager;
2417		ISC_LIST_APPEND(manager->active, client, link);
2418		client->list = &manager->active;
2419
2420		INSIST(client->nctls == 0);
2421		client->nctls++;
2422		ev = &client->ctlevent;
2423		isc_task_send(client->task, &ev);
2424	}
2425	if (i != 0) {
2426		/*
2427		 * We managed to create at least one client, so we
2428		 * declare victory.
2429		 */
2430		result = ISC_R_SUCCESS;
2431	}
2432
2433	UNLOCK(&manager->lock);
2434
2435	return (result);
2436}
2437
2438isc_sockaddr_t *
2439ns_client_getsockaddr(ns_client_t *client) {
2440	return (&client->peeraddr);
2441}
2442
2443isc_result_t
2444ns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl,
2445			 isc_boolean_t default_allow)
2446{
2447	isc_result_t result;
2448	int match;
2449	isc_netaddr_t netaddr;
2450
2451	if (acl == NULL) {
2452		if (default_allow)
2453			goto allow;
2454		else
2455			goto deny;
2456	}
2457
2458	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2459
2460	result = dns_acl_match(&netaddr, client->signer, acl,
2461			       &ns_g_server->aclenv,
2462			       &match, NULL);
2463	if (result != ISC_R_SUCCESS)
2464		goto deny; /* Internal error, already logged. */
2465	if (match > 0)
2466		goto allow;
2467	goto deny; /* Negative match or no match. */
2468
2469 allow:
2470	return (ISC_R_SUCCESS);
2471
2472 deny:
2473	return (DNS_R_REFUSED);
2474}
2475
2476isc_result_t
2477ns_client_checkacl(ns_client_t *client,
2478		   const char *opname, dns_acl_t *acl,
2479		   isc_boolean_t default_allow, int log_level)
2480{
2481	isc_result_t result =
2482		ns_client_checkaclsilent(client, acl, default_allow);
2483
2484	if (result == ISC_R_SUCCESS)
2485		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2486			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2487			      "%s approved", opname);
2488	else
2489		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2490			      NS_LOGMODULE_CLIENT,
2491			      log_level, "%s denied", opname);
2492	return (result);
2493}
2494
2495static void
2496ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2497	if (client->peeraddr_valid)
2498		isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2499	else
2500		snprintf(peerbuf, len, "@%p", client);
2501}
2502
2503void
2504ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2505	   isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2506{
2507	char msgbuf[2048];
2508	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2509	const char *name = "";
2510	const char *sep = "";
2511
2512	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2513	ns_client_name(client, peerbuf, sizeof(peerbuf));
2514	if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2515	    strcmp(client->view->name, "_default") != 0) {
2516		name = client->view->name;
2517		sep = ": view ";
2518	}
2519
2520	isc_log_write(ns_g_lctx, category, module, level,
2521		      "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2522}
2523
2524void
2525ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2526	   isc_logmodule_t *module, int level, const char *fmt, ...)
2527{
2528	va_list ap;
2529
2530	if (! isc_log_wouldlog(ns_g_lctx, level))
2531		return;
2532
2533	va_start(ap, fmt);
2534	ns_client_logv(client, category, module, level, fmt, ap);
2535	va_end(ap);
2536}
2537
2538void
2539ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2540		 dns_rdataclass_t rdclass, char *buf, size_t len)
2541{
2542        char namebuf[DNS_NAME_FORMATSIZE];
2543        char typebuf[DNS_RDATATYPE_FORMATSIZE];
2544        char classbuf[DNS_RDATACLASS_FORMATSIZE];
2545
2546        dns_name_format(name, namebuf, sizeof(namebuf));
2547        dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2548        dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2549        (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2550		       classbuf);
2551}
2552
2553static void
2554ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2555	isc_buffer_t buffer;
2556	char *buf = NULL;
2557	int len = 1024;
2558	isc_result_t result;
2559
2560	/*
2561	 * Note that these are multiline debug messages.  We want a newline
2562	 * to appear in the log after each message.
2563	 */
2564
2565	do {
2566		buf = isc_mem_get(client->mctx, len);
2567		if (buf == NULL)
2568			break;
2569		isc_buffer_init(&buffer, buf, len);
2570		result = dns_message_totext(client->message,
2571					    &dns_master_style_debug,
2572					    0, &buffer);
2573		if (result == ISC_R_NOSPACE) {
2574			isc_mem_put(client->mctx, buf, len);
2575			len += 1024;
2576		} else if (result == ISC_R_SUCCESS)
2577		        ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2578				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2579				      "%s\n%.*s", reason,
2580				       (int)isc_buffer_usedlength(&buffer),
2581				       buf);
2582	} while (result == ISC_R_NOSPACE);
2583
2584	if (buf != NULL)
2585		isc_mem_put(client->mctx, buf, len);
2586}
2587
2588void
2589ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2590	ns_client_t *client;
2591	char namebuf[DNS_NAME_FORMATSIZE];
2592	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2593	const char *name;
2594	const char *sep;
2595
2596	REQUIRE(VALID_MANAGER(manager));
2597
2598	LOCK(&manager->lock);
2599	client = ISC_LIST_HEAD(manager->recursing);
2600	while (client != NULL) {
2601		ns_client_name(client, peerbuf, sizeof(peerbuf));
2602		if (client->view != NULL &&
2603		    strcmp(client->view->name, "_bind") != 0 &&
2604		    strcmp(client->view->name, "_default") != 0) {
2605			name = client->view->name;
2606			sep = ": view ";
2607		} else {
2608			name = "";
2609			sep = "";
2610		}
2611		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2612		fprintf(f, "; client %s%s%s: '%s' requesttime %d\n",
2613			peerbuf, sep, name, namebuf, client->requesttime);
2614		client = ISC_LIST_NEXT(client, link);
2615	}
2616	UNLOCK(&manager->lock);
2617}
2618
2619void
2620ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2621
2622	if (client->manager != NULL)
2623		LOCK(&client->manager->lock);
2624	if (client->query.restarts > 0) {
2625		/*
2626		 * client->query.qname was dynamically allocated.
2627		 */
2628		dns_message_puttempname(client->message,
2629					&client->query.qname);
2630	}
2631	client->query.qname = name;
2632	if (client->manager != NULL)
2633		UNLOCK(&client->manager->lock);
2634}
2635