PageRenderTime 154ms CodeModel.GetById 66ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/bin/named/client.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2856 lines | 1992 code | 376 blank | 488 comment | 567 complexity | 6ca06a0de244edc47bd898a31b205e8c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
   3 * Copyright (C) 1999-2003  Internet Software Consortium.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   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.271.10.4 2012/01/31 23:46:39 tbox 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/stats.h>
  28#include <isc/stdio.h>
  29#include <isc/string.h>
  30#include <isc/task.h>
  31#include <isc/timer.h>
  32#include <isc/util.h>
  33
  34#include <dns/db.h>
  35#include <dns/dispatch.h>
  36#include <dns/events.h>
  37#include <dns/message.h>
  38#include <dns/peer.h>
  39#include <dns/rcode.h>
  40#include <dns/rdata.h>
  41#include <dns/rdataclass.h>
  42#include <dns/rdatalist.h>
  43#include <dns/rdataset.h>
  44#include <dns/resolver.h>
  45#include <dns/stats.h>
  46#include <dns/tsig.h>
  47#include <dns/view.h>
  48#include <dns/zone.h>
  49
  50#include <named/interfacemgr.h>
  51#include <named/log.h>
  52#include <named/notify.h>
  53#include <named/os.h>
  54#include <named/server.h>
  55#include <named/update.h>
  56
  57/***
  58 *** Client
  59 ***/
  60
  61/*! \file
  62 * Client Routines
  63 *
  64 * Important note!
  65 *
  66 * All client state changes, other than that from idle to listening, occur
  67 * as a result of events.  This guarantees serialization and avoids the
  68 * need for locking.
  69 *
  70 * If a routine is ever created that allows someone other than the client's
  71 * task to change the client, then the client will have to be locked.
  72 */
  73
  74#define NS_CLIENT_TRACE
  75#ifdef NS_CLIENT_TRACE
  76#define CTRACE(m)	ns_client_log(client, \
  77				      NS_LOGCATEGORY_CLIENT, \
  78				      NS_LOGMODULE_CLIENT, \
  79				      ISC_LOG_DEBUG(3), \
  80				      "%s", (m))
  81#define MTRACE(m)	isc_log_write(ns_g_lctx, \
  82				      NS_LOGCATEGORY_GENERAL, \
  83				      NS_LOGMODULE_CLIENT, \
  84				      ISC_LOG_DEBUG(3), \
  85				      "clientmgr @%p: %s", manager, (m))
  86#else
  87#define CTRACE(m)	((void)(m))
  88#define MTRACE(m)	((void)(m))
  89#endif
  90
  91#define TCP_CLIENT(c)	(((c)->attributes & NS_CLIENTATTR_TCP) != 0)
  92
  93#define TCP_BUFFER_SIZE			(65535 + 2)
  94#define SEND_BUFFER_SIZE		4096
  95#define RECV_BUFFER_SIZE		4096
  96
  97#ifdef ISC_PLATFORM_USETHREADS
  98#define NMCTXS				100
  99/*%<
 100 * Number of 'mctx pools' for clients. (Should this be configurable?)
 101 * When enabling threads, we use a pool of memory contexts shared by
 102 * client objects, since concurrent access to a shared context would cause
 103 * heavy contentions.  The above constant is expected to be enough for
 104 * completely avoiding contentions among threads for an authoritative-only
 105 * server.
 106 */
 107#else
 108#define NMCTXS				0
 109/*%<
 110 * If named with built without thread, simply share manager's context.  Using
 111 * a separate context in this case would simply waste memory.
 112 */
 113#endif
 114
 115/*% nameserver client manager structure */
 116struct ns_clientmgr {
 117	/* Unlocked. */
 118	unsigned int			magic;
 119	isc_mem_t *			mctx;
 120	isc_taskmgr_t *			taskmgr;
 121	isc_timermgr_t *		timermgr;
 122	isc_mutex_t			lock;
 123	/* Locked by lock. */
 124	isc_boolean_t			exiting;
 125	client_list_t			active;		/*%< Active clients */
 126	client_list_t			recursing;	/*%< Recursing clients */
 127	client_list_t			inactive;	/*%< To be recycled */
 128#if NMCTXS > 0
 129	/*%< mctx pool for clients. */
 130	unsigned int			nextmctx;
 131	isc_mem_t *			mctxpool[NMCTXS];
 132#endif
 133};
 134
 135#define MANAGER_MAGIC			ISC_MAGIC('N', 'S', 'C', 'm')
 136#define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, MANAGER_MAGIC)
 137
 138/*!
 139 * Client object states.  Ordering is significant: higher-numbered
 140 * states are generally "more active", meaning that the client can
 141 * have more dynamically allocated data, outstanding events, etc.
 142 * In the list below, any such properties listed for state N
 143 * also apply to any state > N.
 144 *
 145 * To force the client into a less active state, set client->newstate
 146 * to that state and call exit_check().  This will cause any
 147 * activities defined for higher-numbered states to be aborted.
 148 */
 149
 150#define NS_CLIENTSTATE_FREED    0
 151/*%<
 152 * The client object no longer exists.
 153 */
 154
 155#define NS_CLIENTSTATE_INACTIVE 1
 156/*%<
 157 * The client object exists and has a task and timer.
 158 * Its "query" struct and sendbuf are initialized.
 159 * It is on the client manager's list of inactive clients.
 160 * It has a message and OPT, both in the reset state.
 161 */
 162
 163#define NS_CLIENTSTATE_READY    2
 164/*%<
 165 * The client object is either a TCP or a UDP one, and
 166 * it is associated with a network interface.  It is on the
 167 * client manager's list of active clients.
 168 *
 169 * If it is a TCP client object, it has a TCP listener socket
 170 * and an outstanding TCP listen request.
 171 *
 172 * If it is a UDP client object, it has a UDP listener socket
 173 * and an outstanding UDP receive request.
 174 */
 175
 176#define NS_CLIENTSTATE_READING  3
 177/*%<
 178 * The client object is a TCP client object that has received
 179 * a connection.  It has a tcpsocket, tcpmsg, TCP quota, and an
 180 * outstanding TCP read request.  This state is not used for
 181 * UDP client objects.
 182 */
 183
 184#define NS_CLIENTSTATE_WORKING  4
 185/*%<
 186 * The client object has received a request and is working
 187 * on it.  It has a view, and it may have any of a non-reset OPT,
 188 * recursion quota, and an outstanding write request.
 189 */
 190
 191#define NS_CLIENTSTATE_MAX      9
 192/*%<
 193 * Sentinel value used to indicate "no state".  When client->newstate
 194 * has this value, we are not attempting to exit the current state.
 195 * Must be greater than any valid state.
 196 */
 197
 198/*
 199 * Enable ns_client_dropport() by default.
 200 */
 201#ifndef NS_CLIENT_DROPPORT
 202#define NS_CLIENT_DROPPORT 1
 203#endif
 204
 205unsigned int ns_client_requests;
 206
 207static void client_read(ns_client_t *client);
 208static void client_accept(ns_client_t *client);
 209static void client_udprecv(ns_client_t *client);
 210static void clientmgr_destroy(ns_clientmgr_t *manager);
 211static isc_boolean_t exit_check(ns_client_t *client);
 212static void ns_client_endrequest(ns_client_t *client);
 213static void ns_client_checkactive(ns_client_t *client);
 214static void client_start(isc_task_t *task, isc_event_t *event);
 215static void client_request(isc_task_t *task, isc_event_t *event);
 216static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
 217
 218void
 219ns_client_recursing(ns_client_t *client) {
 220	REQUIRE(NS_CLIENT_VALID(client));
 221
 222	LOCK(&client->manager->lock);
 223	ISC_LIST_UNLINK(*client->list, client, link);
 224	ISC_LIST_APPEND(client->manager->recursing, client, link);
 225	client->list = &client->manager->recursing;
 226	UNLOCK(&client->manager->lock);
 227}
 228
 229void
 230ns_client_killoldestquery(ns_client_t *client) {
 231	ns_client_t *oldest;
 232	REQUIRE(NS_CLIENT_VALID(client));
 233
 234	LOCK(&client->manager->lock);
 235	oldest = ISC_LIST_HEAD(client->manager->recursing);
 236	if (oldest != NULL) {
 237		ns_query_cancel(oldest);
 238		ISC_LIST_UNLINK(*oldest->list, oldest, link);
 239		ISC_LIST_APPEND(client->manager->active, oldest, link);
 240		oldest->list = &client->manager->active;
 241	}
 242	UNLOCK(&client->manager->lock);
 243}
 244
 245void
 246ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
 247	isc_result_t result;
 248	isc_interval_t interval;
 249
 250	isc_interval_set(&interval, seconds, 0);
 251	result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
 252				 &interval, ISC_FALSE);
 253	client->timerset = ISC_TRUE;
 254	if (result != ISC_R_SUCCESS) {
 255		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 256			      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
 257			      "setting timeout: %s",
 258			      isc_result_totext(result));
 259		/* Continue anyway. */
 260	}
 261}
 262
 263/*%
 264 * Check for a deactivation or shutdown request and take appropriate
 265 * action.  Returns ISC_TRUE if either is in progress; in this case
 266 * the caller must no longer use the client object as it may have been
 267 * freed.
 268 */
 269static isc_boolean_t
 270exit_check(ns_client_t *client) {
 271	ns_clientmgr_t *locked_manager = NULL;
 272	ns_clientmgr_t *destroy_manager = NULL;
 273
 274	REQUIRE(NS_CLIENT_VALID(client));
 275
 276	if (client->state <= client->newstate)
 277		return (ISC_FALSE); /* Business as usual. */
 278
 279	INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
 280
 281	/*
 282	 * We need to detach from the view early when shutting down
 283	 * the server to break the following vicious circle:
 284	 *
 285	 *  - The resolver will not shut down until the view refcount is zero
 286	 *  - The view refcount does not go to zero until all clients detach
 287	 *  - The client does not detach from the view until references is zero
 288	 *  - references does not go to zero until the resolver has shut down
 289	 *
 290	 * Keep the view attached until any outstanding updates complete.
 291	 */
 292	if (client->nupdates == 0 &&
 293	    client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
 294		dns_view_detach(&client->view);
 295
 296	if (client->state == NS_CLIENTSTATE_WORKING) {
 297		INSIST(client->newstate <= NS_CLIENTSTATE_READING);
 298		/*
 299		 * Let the update processing complete.
 300		 */
 301		if (client->nupdates > 0)
 302			return (ISC_TRUE);
 303		/*
 304		 * We are trying to abort request processing.
 305		 */
 306		if (client->nsends > 0) {
 307			isc_socket_t *socket;
 308			if (TCP_CLIENT(client))
 309				socket = client->tcpsocket;
 310			else
 311				socket = client->udpsocket;
 312			isc_socket_cancel(socket, client->task,
 313					  ISC_SOCKCANCEL_SEND);
 314		}
 315
 316		if (! (client->nsends == 0 && client->nrecvs == 0 &&
 317		       client->references == 0))
 318		{
 319			/*
 320			 * Still waiting for I/O cancel completion.
 321			 * or lingering references.
 322			 */
 323			return (ISC_TRUE);
 324		}
 325		/*
 326		 * I/O cancel is complete.  Burn down all state
 327		 * related to the current request.  Ensure that
 328		 * the client is on the active list and not the
 329		 * recursing list.
 330		 */
 331		LOCK(&client->manager->lock);
 332		if (client->list == &client->manager->recursing) {
 333			ISC_LIST_UNLINK(*client->list, client, link);
 334			ISC_LIST_APPEND(client->manager->active, client, link);
 335			client->list = &client->manager->active;
 336		}
 337		UNLOCK(&client->manager->lock);
 338		ns_client_endrequest(client);
 339
 340		client->state = NS_CLIENTSTATE_READING;
 341		INSIST(client->recursionquota == NULL);
 342		if (NS_CLIENTSTATE_READING == client->newstate) {
 343			client_read(client);
 344			client->newstate = NS_CLIENTSTATE_MAX;
 345			return (ISC_TRUE); /* We're done. */
 346		}
 347	}
 348
 349	if (client->state == NS_CLIENTSTATE_READING) {
 350		/*
 351		 * We are trying to abort the current TCP connection,
 352		 * if any.
 353		 */
 354		INSIST(client->recursionquota == NULL);
 355		INSIST(client->newstate <= NS_CLIENTSTATE_READY);
 356		if (client->nreads > 0)
 357			dns_tcpmsg_cancelread(&client->tcpmsg);
 358		if (! client->nreads == 0) {
 359			/* Still waiting for read cancel completion. */
 360			return (ISC_TRUE);
 361		}
 362
 363		if (client->tcpmsg_valid) {
 364			dns_tcpmsg_invalidate(&client->tcpmsg);
 365			client->tcpmsg_valid = ISC_FALSE;
 366		}
 367		if (client->tcpsocket != NULL) {
 368			CTRACE("closetcp");
 369			isc_socket_detach(&client->tcpsocket);
 370		}
 371
 372		if (client->tcpquota != NULL)
 373			isc_quota_detach(&client->tcpquota);
 374
 375		if (client->timerset) {
 376			(void)isc_timer_reset(client->timer,
 377					      isc_timertype_inactive,
 378					      NULL, NULL, ISC_TRUE);
 379			client->timerset = ISC_FALSE;
 380		}
 381
 382		client->peeraddr_valid = ISC_FALSE;
 383
 384		client->state = NS_CLIENTSTATE_READY;
 385		INSIST(client->recursionquota == NULL);
 386
 387		/*
 388		 * Now the client is ready to accept a new TCP connection
 389		 * or UDP request, but we may have enough clients doing
 390		 * that already.  Check whether this client needs to remain
 391		 * active and force it to go inactive if not.
 392		 */
 393		ns_client_checkactive(client);
 394
 395		if (NS_CLIENTSTATE_READY == client->newstate) {
 396			if (TCP_CLIENT(client)) {
 397				client_accept(client);
 398			} else
 399				client_udprecv(client);
 400			client->newstate = NS_CLIENTSTATE_MAX;
 401			return (ISC_TRUE);
 402		}
 403	}
 404
 405	if (client->state == NS_CLIENTSTATE_READY) {
 406		INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
 407		/*
 408		 * We are trying to enter the inactive state.
 409		 */
 410		if (client->naccepts > 0)
 411			isc_socket_cancel(client->tcplistener, client->task,
 412					  ISC_SOCKCANCEL_ACCEPT);
 413
 414		if (! (client->naccepts == 0)) {
 415			/* Still waiting for accept cancel completion. */
 416			return (ISC_TRUE);
 417		}
 418		/* Accept cancel is complete. */
 419
 420		if (client->nrecvs > 0)
 421			isc_socket_cancel(client->udpsocket, client->task,
 422					  ISC_SOCKCANCEL_RECV);
 423		if (! (client->nrecvs == 0)) {
 424			/* Still waiting for recv cancel completion. */
 425			return (ISC_TRUE);
 426		}
 427		/* Recv cancel is complete. */
 428
 429		if (client->nctls > 0) {
 430			/* Still waiting for control event to be delivered */
 431			return (ISC_TRUE);
 432		}
 433
 434		/* Deactivate the client. */
 435		if (client->interface)
 436			ns_interface_detach(&client->interface);
 437
 438		INSIST(client->naccepts == 0);
 439		INSIST(client->recursionquota == NULL);
 440		if (client->tcplistener != NULL)
 441			isc_socket_detach(&client->tcplistener);
 442
 443		if (client->udpsocket != NULL)
 444			isc_socket_detach(&client->udpsocket);
 445
 446		if (client->dispatch != NULL)
 447			dns_dispatch_detach(&client->dispatch);
 448
 449		client->attributes = 0;
 450		client->mortal = ISC_FALSE;
 451
 452		LOCK(&client->manager->lock);
 453		/*
 454		 * Put the client on the inactive list.  If we are aiming for
 455		 * the "freed" state, it will be removed from the inactive
 456		 * list shortly, and we need to keep the manager locked until
 457		 * that has been done, lest the manager decide to reactivate
 458		 * the dying client inbetween.
 459		 */
 460		locked_manager = client->manager;
 461		ISC_LIST_UNLINK(*client->list, client, link);
 462		ISC_LIST_APPEND(client->manager->inactive, client, link);
 463		client->list = &client->manager->inactive;
 464		client->state = NS_CLIENTSTATE_INACTIVE;
 465		INSIST(client->recursionquota == NULL);
 466
 467		if (client->state == client->newstate) {
 468			client->newstate = NS_CLIENTSTATE_MAX;
 469			if (client->needshutdown)
 470				isc_task_shutdown(client->task);
 471			goto unlock;
 472		}
 473	}
 474
 475	if (client->state == NS_CLIENTSTATE_INACTIVE) {
 476		INSIST(client->newstate == NS_CLIENTSTATE_FREED);
 477		/*
 478		 * We are trying to free the client.
 479		 *
 480		 * When "shuttingdown" is true, either the task has received
 481		 * its shutdown event or no shutdown event has ever been
 482		 * set up.  Thus, we have no outstanding shutdown
 483		 * event at this point.
 484		 */
 485		REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
 486
 487		INSIST(client->recursionquota == NULL);
 488
 489		ns_query_free(client);
 490		isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
 491		isc_event_free((isc_event_t **)&client->sendevent);
 492		isc_event_free((isc_event_t **)&client->recvevent);
 493		isc_timer_detach(&client->timer);
 494
 495		if (client->tcpbuf != NULL)
 496			isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
 497		if (client->opt != NULL) {
 498			INSIST(dns_rdataset_isassociated(client->opt));
 499			dns_rdataset_disassociate(client->opt);
 500			dns_message_puttemprdataset(client->message, &client->opt);
 501		}
 502		dns_message_destroy(&client->message);
 503		if (client->manager != NULL) {
 504			ns_clientmgr_t *manager = client->manager;
 505			if (locked_manager == NULL) {
 506				LOCK(&manager->lock);
 507				locked_manager = manager;
 508			}
 509			ISC_LIST_UNLINK(*client->list, client, link);
 510			client->list = NULL;
 511			if (manager->exiting &&
 512			    ISC_LIST_EMPTY(manager->active) &&
 513			    ISC_LIST_EMPTY(manager->inactive) &&
 514			    ISC_LIST_EMPTY(manager->recursing))
 515				destroy_manager = manager;
 516		}
 517		/*
 518		 * Detaching the task must be done after unlinking from
 519		 * the manager's lists because the manager accesses
 520		 * client->task.
 521		 */
 522		if (client->task != NULL)
 523			isc_task_detach(&client->task);
 524
 525		CTRACE("free");
 526		client->magic = 0;
 527		/*
 528		 * Check that there are no other external references to
 529		 * the memory context.
 530		 */
 531		if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
 532			isc_mem_stats(client->mctx, stderr);
 533			INSIST(0);
 534		}
 535		isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
 536
 537		goto unlock;
 538	}
 539
 540 unlock:
 541	if (locked_manager != NULL) {
 542		UNLOCK(&locked_manager->lock);
 543		locked_manager = NULL;
 544	}
 545
 546	/*
 547	 * Only now is it safe to destroy the client manager (if needed),
 548	 * because we have accessed its lock for the last time.
 549	 */
 550	if (destroy_manager != NULL)
 551		clientmgr_destroy(destroy_manager);
 552
 553	return (ISC_TRUE);
 554}
 555
 556/*%
 557 * The client's task has received the client's control event
 558 * as part of the startup process.
 559 */
 560static void
 561client_start(isc_task_t *task, isc_event_t *event) {
 562	ns_client_t *client = (ns_client_t *) event->ev_arg;
 563
 564	INSIST(task == client->task);
 565
 566	UNUSED(task);
 567
 568	INSIST(client->nctls == 1);
 569	client->nctls--;
 570
 571	if (exit_check(client))
 572		return;
 573
 574	if (TCP_CLIENT(client)) {
 575		client_accept(client);
 576	} else {
 577		client_udprecv(client);
 578	}
 579}
 580
 581
 582/*%
 583 * The client's task has received a shutdown event.
 584 */
 585static void
 586client_shutdown(isc_task_t *task, isc_event_t *event) {
 587	ns_client_t *client;
 588
 589	REQUIRE(event != NULL);
 590	REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
 591	client = event->ev_arg;
 592	REQUIRE(NS_CLIENT_VALID(client));
 593	REQUIRE(task == client->task);
 594
 595	UNUSED(task);
 596
 597	CTRACE("shutdown");
 598
 599	isc_event_free(&event);
 600
 601	if (client->shutdown != NULL) {
 602		(client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
 603		client->shutdown = NULL;
 604		client->shutdown_arg = NULL;
 605	}
 606
 607	client->newstate = NS_CLIENTSTATE_FREED;
 608	client->needshutdown = ISC_FALSE;
 609	(void)exit_check(client);
 610}
 611
 612static void
 613ns_client_endrequest(ns_client_t *client) {
 614	INSIST(client->naccepts == 0);
 615	INSIST(client->nreads == 0);
 616	INSIST(client->nsends == 0);
 617	INSIST(client->nrecvs == 0);
 618	INSIST(client->nupdates == 0);
 619	INSIST(client->state == NS_CLIENTSTATE_WORKING);
 620
 621	CTRACE("endrequest");
 622
 623	if (client->next != NULL) {
 624		(client->next)(client);
 625		client->next = NULL;
 626	}
 627
 628	if (client->view != NULL)
 629		dns_view_detach(&client->view);
 630	if (client->opt != NULL) {
 631		INSIST(dns_rdataset_isassociated(client->opt));
 632		dns_rdataset_disassociate(client->opt);
 633		dns_message_puttemprdataset(client->message, &client->opt);
 634	}
 635
 636	client->signer = NULL;
 637	client->udpsize = 512;
 638	client->extflags = 0;
 639	client->ednsversion = -1;
 640	dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
 641
 642	if (client->recursionquota != NULL)
 643		isc_quota_detach(&client->recursionquota);
 644
 645	/*
 646	 * Clear all client attributes that are specific to
 647	 * the request; that's all except the TCP flag.
 648	 */
 649	client->attributes &= NS_CLIENTATTR_TCP;
 650}
 651
 652static void
 653ns_client_checkactive(ns_client_t *client) {
 654	if (client->mortal) {
 655		/*
 656		 * This client object should normally go inactive
 657		 * at this point, but if we have fewer active client
 658		 * objects than desired due to earlier quota exhaustion,
 659		 * keep it active to make up for the shortage.
 660		 */
 661		isc_boolean_t need_another_client = ISC_FALSE;
 662		if (TCP_CLIENT(client) && !ns_g_clienttest) {
 663			LOCK(&client->interface->lock);
 664			if (client->interface->ntcpcurrent <
 665			    client->interface->ntcptarget)
 666				need_another_client = ISC_TRUE;
 667			UNLOCK(&client->interface->lock);
 668		} else {
 669			/*
 670			 * The UDP client quota is enforced by making
 671			 * requests fail rather than by not listening
 672			 * for new ones.  Therefore, there is always a
 673			 * full set of UDP clients listening.
 674			 */
 675		}
 676		if (! need_another_client) {
 677			/*
 678			 * We don't need this client object.  Recycle it.
 679			 */
 680			if (client->newstate >= NS_CLIENTSTATE_INACTIVE)
 681				client->newstate = NS_CLIENTSTATE_INACTIVE;
 682		}
 683	}
 684}
 685
 686void
 687ns_client_next(ns_client_t *client, isc_result_t result) {
 688	int newstate;
 689
 690	REQUIRE(NS_CLIENT_VALID(client));
 691	REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
 692		client->state == NS_CLIENTSTATE_READING);
 693
 694	CTRACE("next");
 695
 696	if (result != ISC_R_SUCCESS)
 697		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 698			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 699			      "request failed: %s", isc_result_totext(result));
 700
 701	/*
 702	 * An error processing a TCP request may have left
 703	 * the connection out of sync.  To be safe, we always
 704	 * sever the connection when result != ISC_R_SUCCESS.
 705	 */
 706	if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
 707		newstate = NS_CLIENTSTATE_READING;
 708	else
 709		newstate = NS_CLIENTSTATE_READY;
 710
 711	if (client->newstate > newstate)
 712		client->newstate = newstate;
 713	(void)exit_check(client);
 714}
 715
 716
 717static void
 718client_senddone(isc_task_t *task, isc_event_t *event) {
 719	ns_client_t *client;
 720	isc_socketevent_t *sevent = (isc_socketevent_t *) event;
 721
 722	REQUIRE(sevent != NULL);
 723	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
 724	client = sevent->ev_arg;
 725	REQUIRE(NS_CLIENT_VALID(client));
 726	REQUIRE(task == client->task);
 727	REQUIRE(sevent == client->sendevent);
 728
 729	UNUSED(task);
 730
 731	CTRACE("senddone");
 732
 733	if (sevent->result != ISC_R_SUCCESS)
 734		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 735			      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
 736			      "error sending response: %s",
 737			      isc_result_totext(sevent->result));
 738
 739	INSIST(client->nsends > 0);
 740	client->nsends--;
 741
 742	if (client->tcpbuf != NULL) {
 743		INSIST(TCP_CLIENT(client));
 744		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
 745		client->tcpbuf = NULL;
 746	}
 747
 748	if (exit_check(client))
 749		return;
 750
 751	ns_client_next(client, ISC_R_SUCCESS);
 752}
 753
 754/*%
 755 * We only want to fail with ISC_R_NOSPACE when called from
 756 * ns_client_sendraw() and not when called from ns_client_send(),
 757 * tcpbuffer is NULL when called from ns_client_sendraw() and
 758 * length != 0.  tcpbuffer != NULL when called from ns_client_send()
 759 * and length == 0.
 760 */
 761
 762static isc_result_t
 763client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
 764		    isc_buffer_t *tcpbuffer, isc_uint32_t length,
 765		    unsigned char *sendbuf, unsigned char **datap)
 766{
 767	unsigned char *data;
 768	isc_uint32_t bufsize;
 769	isc_result_t result;
 770
 771	INSIST(datap != NULL);
 772	INSIST((tcpbuffer == NULL && length != 0) ||
 773	       (tcpbuffer != NULL && length == 0));
 774
 775	if (TCP_CLIENT(client)) {
 776		INSIST(client->tcpbuf == NULL);
 777		if (length + 2 > TCP_BUFFER_SIZE) {
 778			result = ISC_R_NOSPACE;
 779			goto done;
 780		}
 781		client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
 782		if (client->tcpbuf == NULL) {
 783			result = ISC_R_NOMEMORY;
 784			goto done;
 785		}
 786		data = client->tcpbuf;
 787		if (tcpbuffer != NULL) {
 788			isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
 789			isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
 790		} else {
 791			isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
 792			INSIST(length <= 0xffff);
 793			isc_buffer_putuint16(buffer, (isc_uint16_t)length);
 794		}
 795	} else {
 796		data = sendbuf;
 797		if (client->udpsize < SEND_BUFFER_SIZE)
 798			bufsize = client->udpsize;
 799		else
 800			bufsize = SEND_BUFFER_SIZE;
 801		if (length > bufsize) {
 802			result = ISC_R_NOSPACE;
 803			goto done;
 804		}
 805		isc_buffer_init(buffer, data, bufsize);
 806	}
 807	*datap = data;
 808	result = ISC_R_SUCCESS;
 809
 810 done:
 811	return (result);
 812}
 813
 814static isc_result_t
 815client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
 816	struct in6_pktinfo *pktinfo;
 817	isc_result_t result;
 818	isc_region_t r;
 819	isc_sockaddr_t *address;
 820	isc_socket_t *socket;
 821	isc_netaddr_t netaddr;
 822	int match;
 823	unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
 824
 825	if (TCP_CLIENT(client)) {
 826		socket = client->tcpsocket;
 827		address = NULL;
 828	} else {
 829		socket = client->udpsocket;
 830		address = &client->peeraddr;
 831
 832		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 833		if (ns_g_server->blackholeacl != NULL &&
 834		    dns_acl_match(&netaddr, NULL,
 835				  ns_g_server->blackholeacl,
 836				  &ns_g_server->aclenv,
 837				  &match, NULL) == ISC_R_SUCCESS &&
 838		    match > 0)
 839			return (DNS_R_BLACKHOLED);
 840		sockflags |= ISC_SOCKFLAG_NORETRY;
 841	}
 842
 843	if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
 844	    (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
 845		pktinfo = &client->pktinfo;
 846	else
 847		pktinfo = NULL;
 848
 849	isc_buffer_usedregion(buffer, &r);
 850
 851	CTRACE("sendto");
 852
 853	result = isc_socket_sendto2(socket, &r, client->task,
 854				    address, pktinfo,
 855				    client->sendevent, sockflags);
 856	if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
 857		client->nsends++;
 858		if (result == ISC_R_SUCCESS)
 859			client_senddone(client->task,
 860					(isc_event_t *)client->sendevent);
 861		result = ISC_R_SUCCESS;
 862	}
 863	return (result);
 864}
 865
 866void
 867ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
 868	isc_result_t result;
 869	unsigned char *data;
 870	isc_buffer_t buffer;
 871	isc_region_t r;
 872	isc_region_t *mr;
 873	unsigned char sendbuf[SEND_BUFFER_SIZE];
 874
 875	REQUIRE(NS_CLIENT_VALID(client));
 876
 877	CTRACE("sendraw");
 878
 879	mr = dns_message_getrawmessage(message);
 880	if (mr == NULL) {
 881		result = ISC_R_UNEXPECTEDEND;
 882		goto done;
 883	}
 884
 885	result = client_allocsendbuf(client, &buffer, NULL, mr->length,
 886				     sendbuf, &data);
 887	if (result != ISC_R_SUCCESS)
 888		goto done;
 889
 890	/*
 891	 * Copy message to buffer and fixup id.
 892	 */
 893	isc_buffer_availableregion(&buffer, &r);
 894	result = isc_buffer_copyregion(&buffer, mr);
 895	if (result != ISC_R_SUCCESS)
 896		goto done;
 897	r.base[0] = (client->message->id >> 8) & 0xff;
 898	r.base[1] = client->message->id & 0xff;
 899
 900	result = client_sendpkg(client, &buffer);
 901	if (result == ISC_R_SUCCESS)
 902		return;
 903
 904 done:
 905	if (client->tcpbuf != NULL) {
 906		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
 907		client->tcpbuf = NULL;
 908	}
 909	ns_client_next(client, result);
 910}
 911
 912void
 913ns_client_send(ns_client_t *client) {
 914	isc_result_t result;
 915	unsigned char *data;
 916	isc_buffer_t buffer;
 917	isc_buffer_t tcpbuffer;
 918	isc_region_t r;
 919	dns_compress_t cctx;
 920	isc_boolean_t cleanup_cctx = ISC_FALSE;
 921	unsigned char sendbuf[SEND_BUFFER_SIZE];
 922	unsigned int render_opts;
 923	unsigned int preferred_glue;
 924	isc_boolean_t opt_included = ISC_FALSE;
 925
 926	REQUIRE(NS_CLIENT_VALID(client));
 927
 928	CTRACE("send");
 929
 930	if ((client->attributes & NS_CLIENTATTR_RA) != 0)
 931		client->message->flags |= DNS_MESSAGEFLAG_RA;
 932
 933	if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
 934		render_opts = 0;
 935	else
 936		render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
 937
 938	preferred_glue = 0;
 939	if (client->view != NULL) {
 940		if (client->view->preferred_glue == dns_rdatatype_a)
 941			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
 942		else if (client->view->preferred_glue == dns_rdatatype_aaaa)
 943			preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
 944	}
 945
 946#ifdef ALLOW_FILTER_AAAA_ON_V4
 947	/*
 948	 * filter-aaaa-on-v4 yes or break-dnssec option to suppress
 949	 * AAAA records
 950	 * We already know that request came via IPv4,
 951	 * that we have both AAAA and A records,
 952	 * and that we either have no signatures that the client wants
 953	 * or we are supposed to break DNSSEC.
 954	 *
 955	 * Override preferred glue if necessary.
 956	 */
 957	if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
 958		render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
 959		if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
 960			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
 961	}
 962#endif
 963
 964	/*
 965	 * XXXRTH  The following doesn't deal with TCP buffer resizing.
 966	 */
 967	result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
 968				     sendbuf, &data);
 969	if (result != ISC_R_SUCCESS)
 970		goto done;
 971
 972	result = dns_compress_init(&cctx, -1, client->mctx);
 973	if (result != ISC_R_SUCCESS)
 974		goto done;
 975	cleanup_cctx = ISC_TRUE;
 976
 977	result = dns_message_renderbegin(client->message, &cctx, &buffer);
 978	if (result != ISC_R_SUCCESS)
 979		goto done;
 980
 981	if (client->opt != NULL) {
 982		result = dns_message_setopt(client->message, client->opt);
 983		opt_included = ISC_TRUE;
 984		client->opt = NULL;
 985		if (result != ISC_R_SUCCESS)
 986			goto done;
 987	}
 988	result = dns_message_rendersection(client->message,
 989					   DNS_SECTION_QUESTION, 0);
 990	if (result == ISC_R_NOSPACE) {
 991		client->message->flags |= DNS_MESSAGEFLAG_TC;
 992		goto renderend;
 993	}
 994	if (result != ISC_R_SUCCESS)
 995		goto done;
 996	result = dns_message_rendersection(client->message,
 997					   DNS_SECTION_ANSWER,
 998					   DNS_MESSAGERENDER_PARTIAL |
 999					   render_opts);
1000	if (result == ISC_R_NOSPACE) {
1001		client->message->flags |= DNS_MESSAGEFLAG_TC;
1002		goto renderend;
1003	}
1004	if (result != ISC_R_SUCCESS)
1005		goto done;
1006	result = dns_message_rendersection(client->message,
1007					   DNS_SECTION_AUTHORITY,
1008					   DNS_MESSAGERENDER_PARTIAL |
1009					   render_opts);
1010	if (result == ISC_R_NOSPACE) {
1011		client->message->flags |= DNS_MESSAGEFLAG_TC;
1012		goto renderend;
1013	}
1014	if (result != ISC_R_SUCCESS)
1015		goto done;
1016	result = dns_message_rendersection(client->message,
1017					   DNS_SECTION_ADDITIONAL,
1018					   preferred_glue | render_opts);
1019	if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1020		goto done;
1021 renderend:
1022	result = dns_message_renderend(client->message);
1023
1024	if (result != ISC_R_SUCCESS)
1025		goto done;
1026
1027	if (cleanup_cctx) {
1028		dns_compress_invalidate(&cctx);
1029		cleanup_cctx = ISC_FALSE;
1030	}
1031
1032	if (TCP_CLIENT(client)) {
1033		isc_buffer_usedregion(&buffer, &r);
1034		isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1035		isc_buffer_add(&tcpbuffer, r.length);
1036		result = client_sendpkg(client, &tcpbuffer);
1037	} else
1038		result = client_sendpkg(client, &buffer);
1039
1040	/* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1041	isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1042	if (opt_included) {
1043		isc_stats_increment(ns_g_server->nsstats,
1044				    dns_nsstatscounter_edns0out);
1045	}
1046	if (client->message->tsigkey != NULL) {
1047		isc_stats_increment(ns_g_server->nsstats,
1048				    dns_nsstatscounter_tsigout);
1049	}
1050	if (client->message->sig0key != NULL) {
1051		isc_stats_increment(ns_g_server->nsstats,
1052				    dns_nsstatscounter_sig0out);
1053	}
1054	if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1055		isc_stats_increment(ns_g_server->nsstats,
1056				    dns_nsstatscounter_truncatedresp);
1057
1058	if (result == ISC_R_SUCCESS)
1059		return;
1060
1061 done:
1062	if (client->tcpbuf != NULL) {
1063		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1064		client->tcpbuf = NULL;
1065	}
1066
1067	if (cleanup_cctx)
1068		dns_compress_invalidate(&cctx);
1069
1070	ns_client_next(client, result);
1071}
1072
1073#if NS_CLIENT_DROPPORT
1074#define DROPPORT_NO		0
1075#define DROPPORT_REQUEST	1
1076#define DROPPORT_RESPONSE	2
1077/*%
1078 * ns_client_dropport determines if certain requests / responses
1079 * should be dropped based on the port number.
1080 *
1081 * Returns:
1082 * \li	0:	Don't drop.
1083 * \li	1:	Drop request.
1084 * \li	2:	Drop (error) response.
1085 */
1086static int
1087ns_client_dropport(in_port_t port) {
1088	switch (port) {
1089	case 7: /* echo */
1090	case 13: /* daytime */
1091	case 19: /* chargen */
1092	case 37: /* time */
1093		return (DROPPORT_REQUEST);
1094	case 464: /* kpasswd */
1095		return (DROPPORT_RESPONSE);
1096	}
1097	return (DROPPORT_NO);
1098}
1099#endif
1100
1101void
1102ns_client_error(ns_client_t *client, isc_result_t result) {
1103	dns_rcode_t rcode;
1104	dns_message_t *message;
1105
1106	REQUIRE(NS_CLIENT_VALID(client));
1107
1108	CTRACE("error");
1109
1110	message = client->message;
1111	rcode = dns_result_torcode(result);
1112
1113#if NS_CLIENT_DROPPORT
1114	/*
1115	 * Don't send FORMERR to ports on the drop port list.
1116	 */
1117	if (rcode == dns_rcode_formerr &&
1118	    ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1119	    DROPPORT_NO) {
1120		char buf[64];
1121		isc_buffer_t b;
1122
1123		isc_buffer_init(&b, buf, sizeof(buf) - 1);
1124		if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1125			isc_buffer_putstr(&b, "UNKNOWN RCODE");
1126		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1127			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1128			      "dropped error (%.*s) response: suspicious port",
1129			      (int)isc_buffer_usedlength(&b), buf);
1130		ns_client_next(client, ISC_R_SUCCESS);
1131		return;
1132	}
1133#endif
1134
1135	/*
1136	 * Message may be an in-progress reply that we had trouble
1137	 * with, in which case QR will be set.  We need to clear QR before
1138	 * calling dns_message_reply() to avoid triggering an assertion.
1139	 */
1140	message->flags &= ~DNS_MESSAGEFLAG_QR;
1141	/*
1142	 * AA and AD shouldn't be set.
1143	 */
1144	message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1145	result = dns_message_reply(message, ISC_TRUE);
1146	if (result != ISC_R_SUCCESS) {
1147		/*
1148		 * It could be that we've got a query with a good header,
1149		 * but a bad question section, so we try again with
1150		 * want_question_section set to ISC_FALSE.
1151		 */
1152		result = dns_message_reply(message, ISC_FALSE);
1153		if (result != ISC_R_SUCCESS) {
1154			ns_client_next(client, result);
1155			return;
1156		}
1157	}
1158	message->rcode = rcode;
1159
1160	/*
1161	 * FORMERR loop avoidance:  If we sent a FORMERR message
1162	 * with the same ID to the same client less than two
1163	 * seconds ago, assume that we are in an infinite error
1164	 * packet dialog with a server for some protocol whose
1165	 * error responses look enough like DNS queries to
1166	 * elicit a FORMERR response.  Drop a packet to break
1167	 * the loop.
1168	 */
1169	if (rcode == dns_rcode_formerr) {
1170		if (isc_sockaddr_equal(&client->peeraddr,
1171				       &client->formerrcache.addr) &&
1172		    message->id == client->formerrcache.id &&
1173		    client->requesttime - client->formerrcache.time < 2) {
1174			/* Drop packet. */
1175			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1176				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1177				      "possible error packet loop, "
1178				      "FORMERR dropped");
1179			ns_client_next(client, result);
1180			return;
1181		}
1182		client->formerrcache.addr = client->peeraddr;
1183		client->formerrcache.time = client->requesttime;
1184		client->formerrcache.id = message->id;
1185	}
1186	ns_client_send(client);
1187}
1188
1189static inline isc_result_t
1190client_addopt(ns_client_t *client) {
1191	dns_rdataset_t *rdataset;
1192	dns_rdatalist_t *rdatalist;
1193	dns_rdata_t *rdata;
1194	isc_result_t result;
1195	dns_view_t *view;
1196	dns_resolver_t *resolver;
1197	isc_uint16_t udpsize;
1198
1199	REQUIRE(client->opt == NULL);	/* XXXRTH free old. */
1200
1201	rdatalist = NULL;
1202	result = dns_message_gettemprdatalist(client->message, &rdatalist);
1203	if (result != ISC_R_SUCCESS)
1204		return (result);
1205	rdata = NULL;
1206	result = dns_message_gettemprdata(client->message, &rdata);
1207	if (result != ISC_R_SUCCESS)
1208		return (result);
1209	rdataset = NULL;
1210	result = dns_message_gettemprdataset(client->message, &rdataset);
1211	if (result != ISC_R_SUCCESS)
1212		return (result);
1213	dns_rdataset_init(rdataset);
1214
1215	rdatalist->type = dns_rdatatype_opt;
1216	rdatalist->covers = 0;
1217
1218	/*
1219	 * Set the maximum UDP buffer size.
1220	 */
1221	view = client->view;
1222	resolver = (view != NULL) ? view->resolver : NULL;
1223	if (resolver != NULL)
1224		udpsize = dns_resolver_getudpsize(resolver);
1225	else
1226		udpsize = ns_g_udpsize;
1227	rdatalist->rdclass = udpsize;
1228
1229	/*
1230	 * Set EXTENDED-RCODE, VERSION and Z to 0.
1231	 */
1232	rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1233
1234	/* Set EDNS options if applicable */
1235	if (client->attributes & NS_CLIENTATTR_WANTNSID &&
1236	    (ns_g_server->server_id != NULL ||
1237	     ns_g_server->server_usehostname)) {
1238		/*
1239		 * Space required for NSID data:
1240		 *   2 bytes for opt code
1241		 * + 2 bytes for NSID length
1242		 * + NSID itself
1243		 */
1244		char nsid[BUFSIZ], *nsidp;
1245		isc_buffer_t *buffer = NULL;
1246
1247		if (ns_g_server->server_usehostname) {
1248			isc_result_t result;
1249			result = ns_os_gethostname(nsid, sizeof(nsid));
1250			if (result != ISC_R_SUCCESS) {
1251				goto no_nsid;
1252			}
1253			nsidp = nsid;
1254		} else
1255			nsidp = ns_g_server->server_id;
1256
1257		rdata->length = strlen(nsidp) + 4;
1258		result = isc_buffer_allocate(client->mctx, &buffer,
1259					     rdata->length);
1260		if (result != ISC_R_SUCCESS)
1261			goto no_nsid;
1262
1263		isc_buffer_putuint16(buffer, DNS_OPT_NSID);
1264		isc_buffer_putuint16(buffer, strlen(nsidp));
1265		isc_buffer_putstr(buffer, nsidp);
1266		rdata->data = buffer->base;
1267		dns_message_takebuffer(client->message, &buffer);
1268	} else {
1269no_nsid:
1270		rdata->data = NULL;
1271		rdata->length = 0;
1272	}
1273
1274	rdata->rdclass = rdatalist->rdclass;
1275	rdata->type = rdatalist->type;
1276	rdata->flags = 0;
1277
1278	ISC_LIST_INIT(rdatalist->rdata);
1279	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1280	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1281		      == ISC_R_SUCCESS);
1282
1283	client->opt = rdataset;
1284
1285	return (ISC_R_SUCCESS);
1286}
1287
1288static inline isc_boolean_t
1289allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1290	int match;
1291	isc_result_t result;
1292
1293	if (acl == NULL)
1294		return (ISC_TRUE);
1295	result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1296			       &match, NULL);
1297	if (result == ISC_R_SUCCESS && match > 0)
1298		return (ISC_TRUE);
1299	return (ISC_FALSE);
1300}
1301
1302/*
1303 * Callback to see if a non-recursive query coming from 'srcaddr' to
1304 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1305 * delivered to 'myview'.
1306 *
1307 * We run this unlocked as both the view list and the interface list
1308 * are updated when the appropriate task has exclusivity.
1309 */
1310isc_boolean_t
1311ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1312		 isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1313		 dns_rdataclass_t rdclass, void *arg)
1314{
1315	dns_view_t *view;
1316	dns_tsigkey_t *key = NULL;
1317	dns_name_t *tsig = NULL;
1318	isc_netaddr_t netsrc;
1319	isc_netaddr_t netdst;
1320
1321	UNUSED(arg);
1322
1323	/*
1324	 * ns_g_server->interfacemgr is task exclusive locked.
1325	 */
1326	if (ns_g_server->interfacemgr == NULL)
1327		return (ISC_TRUE);
1328
1329	if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1330		return (ISC_FALSE);
1331
1332	isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1333	isc_netaddr_fromsockaddr(&netdst, dstaddr);
1334
1335	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1336	     view != NULL;
1337	     view = ISC_LIST_NEXT(view, link)) {
1338
1339		if (view->matchrecursiveonly)
1340			continue;
1341
1342		if (rdclass != view->rdclass)
1343			continue;
1344
1345		if (mykey != NULL) {
1346			isc_boolean_t match;
1347			isc_result_t result;
1348
1349			result = dns_view_gettsig(view, &mykey->name, &key);
1350			if (result != ISC_R_SUCCESS)
1351				continue;
1352			match = dst_key_compare(mykey->key, key->key);
1353			dns_tsigkey_detach(&key);
1354			if (!match)
1355				continue;
1356			tsig = dns_tsigkey_identity(mykey);
1357		}
1358
1359		if (allowed(&netsrc, tsig, view->matchclients) &&
1360		    allowed(&netdst, tsig, view->matchdestinations))
1361			break;
1362	}
1363	return (ISC_TF(view == myview));
1364}
1365
1366/*
1367 * Handle an incoming request event from the socket (UDP case)
1368 * or tcpmsg (TCP case).
1369 */
1370static void
1371client_request(isc_task_t *task, isc_event_t *event) {
1372	ns_client_t *client;
1373	isc_socketevent_t *sevent;
1374	isc_result_t result;
1375	isc_result_t sigresult = ISC_R_SUCCESS;
1376	isc_buffer_t *buffer;
1377	isc_buffer_t tbuffer;
1378	dns_view_t *view;
1379	dns_rdataset_t *opt;
1380	dns_name_t *signame;
1381	isc_boolean_t ra;	/* Recursion available. */
1382	isc_netaddr_t netaddr;
1383	int match;
1384	dns_messageid_t id;
1385	unsigned int flags;
1386	isc_boolean_t notimp;
1387	dns_rdata_t rdata;
1388	isc_uint16_t optcode;
1389
1390	REQUIRE(event != NULL);
1391	client = event->ev_arg;
1392	REQUIRE(NS_CLIENT_VALID(client));
1393	REQUIRE(task == client->task);
1394
1395	INSIST(client->recursionquota == NULL);
1396
1397	INSIST(client->state ==
1398	       TCP_CLIENT(client) ?
1399	       NS_CLIENTSTATE_READING :
1400	       NS_CLIENTSTATE_READY);
1401
1402	ns_client_requests++;
1403
1404	if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1405		INSIST(!TCP_CLIENT(client));
1406		sevent = (isc_socketevent_t *)event;
1407		REQUIRE(sevent == client->recvevent);
1408		isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1409		isc_buffer_add(&tbuffer, sevent->n);
1410		buffer = &tbuffer;
1411		result = sevent->result;
1412		if (result == ISC_R_SUCCESS) {
1413			client->peeraddr = sevent->address;
1414			client->peeraddr_valid = ISC_TRUE;
1415		}
1416		if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1417			client->attributes |= NS_CLIENTATTR_PKTINFO;
1418			client->pktinfo = sevent->pktinfo;
1419		}
1420		if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1421			client->attributes |= NS_CLIENTATTR_MULTICAST;
1422		client->nrecvs--;
1423	} else {
1424		INSIST(TCP_CLIENT(client));
1425		REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1426		REQUIRE(event->ev_sender == &client->tcpmsg);
1427		buffer = &client->tcpmsg.buffer;
1428		result = client->tcpmsg.result;
1429		INSIST(client->nreads == 1);
1430		/*
1431		 * client->peeraddr was set when the connection was accepted.
1432		 */
1433		client->nreads--;
1434	}
1435
1436	if (exit_check(client))
1437		goto cleanup;
1438	client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1439
1440	isc_task_getcurrenttime(task, &client->requesttime);
1441	client->now = client->requesttime;
1442
1443	if (result != ISC_R_SUCCESS) {
1444		if (TCP_CLIENT(client)) {
1445			ns_client_next(client, result);
1446		} else {
1447			if  (result != ISC_R_CANCELED)
1448				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1449					      NS_LOGMODULE_CLIENT,
1450					      ISC_LOG_ERROR,
1451					      "UDP client handler shutting "
1452					      "down due to fatal receive "
1453					      "error: %s",
1454					      isc_result_totext(result));
1455			isc_task_shutdown(client->task);
1456		}
1457		goto cleanup;
1458	}
1459
1460	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1461
1462#if NS_CLIENT_DROPPORT
1463	if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1464	    DROPPORT_REQUEST) {
1465		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1466			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1467			      "dropped request: suspicious port");
1468		ns_client_next(client, ISC_R_SUCCESS);
1469		goto cleanup;
1470	}
1471#endif
1472
1473	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1474		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1475		      "%s request",
1476		      TCP_CLIENT(client) ? "TCP" : "UDP");
1477
1478	/*
1479	 * Check the blackhole ACL for UDP only, since TCP is done in
1480	 * client_newconn.
1481	 */
1482	if (!TCP_CLIENT(client)) {
1483
1484		if (ns_g_server->blackholeacl != NULL &&
1485		    dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1486				  &ns_g_server->aclenv,
1487				  &match, NULL) == ISC_R_SUCCESS &&
1488		    match > 0)
1489		{
1490			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1491				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1492				      "blackholed UDP datagram");
1493			ns_client_next(client, ISC_R_SUCCESS);
1494			goto cleanup;
1495		}
1496	}
1497
1498	/*
1499	 * Silently drop multicast requests for the present.
1500	 * XXXMPA revisit this as mDNS spec was published.
1501	 */
1502	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1503		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1504			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1505			      "dropping multicast request");
1506		ns_client_next(client, DNS_R_REFUSED);
1507		goto cleanup;
1508	}
1509
1510	result = dns_message_peekheader(buffer, &id, &flags);
1511	if (result != ISC_R_SUCCESS) {
1512		/*
1513		 * There isn't enough header to determine whether
1514		 * this was a request or a response.  Drop it.
1515		 */
1516		ns_client_next(client, result);
1517		goto cleanup;
1518	}
1519
1520	/*
1521	 * The client object handles requests, not responses.
1522	 * If this is a UDP response, forward it to the dispatcher.
1523	 * If it's a TCP response, discard it here.
1524	 */
1525	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1526		if (TCP_CLIENT(client)) {
1527			CTRACE("unexpected response");
1528			ns_client_next(client, DNS_R_FORMERR);
1529			goto cleanup;
1530		} else {
1531			dns_dispatch_importrecv(client->dispatch, event);
1532			ns_client_next(client, ISC_R_SUCCESS);
1533			goto cleanup;
1534		}
1535	}
1536
1537	/*
1538	 * Update some statistics counters.  Don't count responses.
1539	 */
1540	if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1541		isc_stats_increment(ns_g_server->nsstats,
1542				    dns_nsstatscounter_requestv4);
1543	} else {
1544		isc_stats_increment(ns_g_server->nsstats,
1545				    dns_nsstatscounter_requestv6);
1546	}
1547	if (TCP_CLIENT(client))
1548		isc_stats_increment(ns_g_server->nsstats,
1549				    dns_nsstatscounter_tcp);
1550
1551	/*
1552	 * It's a request.  Parse it.
1553	 */
1554	result = dns_message_parse(client->message, buffer, 0);
1555	if (result != ISC_R_SUCCESS) {
1556		/*
1557		 * Parsing the request failed.  Send a response
1558		 * (typically FORMERR or SERVFAIL).
1559		 */
1560		ns_client_error(client, result);
1561		goto cleanup;
1562	}
1563
1564	dns_opcodestats_increment(ns_g_server->opcodestats,
1565				  client->message->opcode);
1566	switch (client->message->opcode) {
1567	case dns_opcode_query:
1568	case dns_opcode_update:
1569	case dns_opcode_notify:
1570		notimp = ISC_FALSE;
1571		break;
1572	case dns_opcode_iquery:
1573	default:
1574		notimp = ISC_TRUE;
1575		break;
1576	}
1577
1578	client->message->rcode = dns_rcode_noerror;
1579
1580	/* RFC1123 section 6.1.3.2 */
1581	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1582		client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1583
1584	/*
1585	 * Deal with EDNS.
1586	 */
1587	opt = dns_message_getopt(client->message);
1588	if (opt != NULL) {
1589		/*
1590		 * Set the client's UDP buffer size.
1591		 */
1592		client->udpsize = opt->rdclass;
1593
1594		/*
1595		 * If the requested UDP buffer size is less than 512,
1596		 * ignore it and use 512.
1597		 */
1598		if (client->udpsize < 512)
1599			client->udpsize = 512;
1600
1601		/*
1602		 * Get the flags out of the OPT record.
1603		 */
1604		client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1605
1606		/*
1607		 * Do we understand this version of EDNS?
1608		 *
1609		 * XXXRTH need library support for this!
1610		 */
1611		client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1612		if (client->ednsversion > 0) {
1613			isc_stats_increment(ns_g_server->nsstats,
1614					    dns_nsstatscounter_badednsver);
1615			result = client_addopt(client);
1616			if (result == ISC_R_SUCCESS)
1617				result = DNS_R_BADVERS;
1618			ns_client_error(client, result);
1619			goto cleanup;
1620		}
1621
1622		/* Check for NSID request */
1623		result = dns_rdataset_first(opt);
1624		if (result == ISC_R_SUCCESS) {
1625			dns_rdata_init(&rdata);
1626			dns_rdataset_current(opt, &rdata);
1627			if (rdata.length >= 2) {
1628				isc_buffer_t nsidbuf;
1629				isc_buffer_init(&nsidbuf,
1630						rdata.data, rdata.length);
1631				isc_buffer_add(&nsidbuf, rdata.length);
1632				optcode = isc_buffer_getuint16(&nsidbuf);
1633				if (optcode == DNS_OPT_NSID)
1634					client->attributes |=
1635						NS_CLIENTATTR_WANTNSID;
1636			}
1637		}
1638
1639		isc_stats_increment(ns_g_server->nsstats,
1640				    dns_nsstatscounter_edns0in);
1641
1642		/*
1643		 * Create an OPT for our reply.
1644		 */
1645		result = client_addopt(client);
1646		if (result != ISC_R_SUCCESS) {
1647			ns_client_error(client, result);
1648			goto cleanup;
1649		}
1650	}
1651
1652	if (client->message->rdclass == 0) {
1653		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1654			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1655			      "message class could not be determined");
1656		ns_client_dumpmessage(client,
1657				      "message class could not be determined");
1658		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1659		goto cleanup;
1660	}
1661
1662	/*
1663	 * Determine the destination address.  If the receiving interface is
1664	 * bound to a specific address, we simply use it regardless of the
1665	 * address family.  All IPv4 queries should fall into this case.
1666	 * Otherwise, if this is a TCP query, get the address from the
1667	 * receiving socket (this needs a system call and can be heavy).
1668	 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1669	 * supported).
1670	 * If all the attempts fail (this can happen due to memory shortage,
1671	 * etc), we regard this as an error for safety.
1672	 */
1673	if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1674		isc_netaddr_fromsockaddr(&client->destaddr,
1675					 &client->interface->addr);
1676	else {
1677		isc_sockaddr_t sockaddr;
1678		result = ISC_R_FAILURE;
1679
1680		if (TCP_CLIENT(client))
1681			result = isc_socket_getsockname(client->tcpsocket,
1682							&sockaddr);
1683		if (result == ISC_R_SUCCESS)
1684			isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1685		if (result != ISC_R_SUCCESS &&
1686		    client->interface->addr.type.sa.sa_family == AF_INET6 &&
1687		    (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1688			/*
1689			 * XXXJT technically, we should convert the receiving
1690			 * interface ID to a proper scope zone ID.  However,
1691			 * due to the fact there is no standard API for this,
1692			 * we only handle link-local addresses and use the
1693			 * interface index as link ID.  Despite the assumption,
1694			 * it should cover most typical cases.
1695			 */
1696			isc_netaddr_fromin6(&client->destaddr,
1697					    &client->pktinfo.ipi6_addr);
1698			if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1699				isc_netaddr_setzone(&client->destaddr,
1700						client->pktinfo.ipi6_ifindex);
1701			result = ISC_R_SUCCESS;
1702		}
1703		if (result != ISC_R_SUCCESS) {
1704			UNEXPECTED_ERROR(__FILE__, __LINE__,
1705					 "failed to get request's "
1706					 "destination: %s",
1707					 isc_result_totext(result));
1708			ns_client_next(client, ISC_R_SUCCESS);
1709			goto cleanup;
1710		}
1711	}
1712
1713	/*
1714	 * Find a view that matches the client's source address.
1715	 */
1716	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1717	     view != NULL;
1718	     view = ISC_LIST_NEXT(view, link)) {
1719		if (client->message->rdclass == view->rdclass ||
1720		    client->message->rdclass == dns_rdataclass_any)
1721		{
1722			dns_name_t *tsig = NULL;
1723
1724			sigresult = dns_message_rechecksig(client->message,
1725							   view);
1726			if (sigresult == ISC_R_SUCCESS)
1727				tsig = dns_tsigkey_identity(client->message->tsigkey);
1728
1729			if (allowed(&netaddr, tsig, view->matchclients) &&
1730			    allowed(&client->destaddr, tsig,
1731				    view->matchdestinations) &&
1732			    !((client->message->flags & DNS_MESSAGEFLAG_RD)
1733			      == 0 && view->matchrecursiveonly))
1734			{
1735				dns_view_attach(view, &client->view);
1736				break;
1737			}
1738		}
1739	}
1740
1741	if (view == NULL) {
1742		char classname[DNS_RDATACLASS_FORMATSIZE];
1743
1744		/*
1745		 * Do a dummy TSIG verification attempt so that the
1746		 * response will have a TSIG if the query did, as
1747		 * required by RFC2845.
1748		 */
1749		isc_buffer_t b;
1750		isc_region_t *r;
1751
1752		dns_message_resetsig(client->message);
1753
1754		r = dns_message_getrawmessage(client->message);
1755		isc_buffer_init(&b, r->base, r->length);
1756		isc_buffer_add(&b, r->length);
1757		(void)dns_tsig_verify(&b, client->message, NULL, NULL);
1758
1759		dns_rdataclass_format(client->message->rdclass, classname,
1760				      sizeof(classname));
1761		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1762			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1763			      "no matching view in class '%s'", classname);
1764		ns_client_dumpmessage(client, "no matching view in class");
1765		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1766		goto cleanup;
1767	}
1768
1769	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1770		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1771		      "using view '%s'", view->name);
1772
1773	/*
1774	 * Check for a signature.  We log bad signatures regardless of
1775	 * whether they ultimately cause the request to be rejected or
1776	 * not.  We do not log the lack of a signature unless we are
1777	 * debugging.
1778	 */
1779	client->signer = NULL;
1780	dns_name_init(&client->signername, NULL);
1781	result = dns_message_signer(client->message, &client->signername);
1782	if (result != ISC_R_NOTFOUND) {
1783		signame = NULL;
1784		if (dns_message_gettsig(client->message, &signame) != NULL) {
1785			isc_stats_increment(ns_g_server->nsstats,
1786					    dns_nsstatscounter_tsigin);
1787		} else {
1788			isc_stats_increment(ns_g_server->nsstats,
1789					    dns_nsstatscounter_sig0in);
1790		}
1791
1792	}
1793	if (result == ISC_R_SUCCESS) {
1794		char namebuf[DNS_NAME_FORMATSIZE];
1795		dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1796		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1797			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1798			      "request has valid signature: %s", namebuf);
1799		client->signer = &client->signername;
1800	} else if (result == ISC_R_NOTFOUND) {
1801		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1802			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(

Large files files are truncated, but you can click here to view the full file