client.c revision bcb68be0a8f3c3eca58d6a6a869267e5c1841de2
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Copyright (C) 1999-2003 Internet Software Consortium.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Permission to use, copy, modify, and/or distribute this software for any
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * PERFORMANCE OF THIS SOFTWARE.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Client Routines
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Important note!
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * All client state changes, other than that from idle to listening, occur
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * as a result of events. This guarantees serialization and avoids the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * need for locking.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If a routine is ever created that allows someone other than the client's
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * task to change the client, then the client will have to be locked.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define MTRACE(m) isc_log_write(ns_g_lctx, \
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define CTRACE(m) ((void)(m))
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define MTRACE(m) ((void)(m))
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Number of 'mctx pools' for clients. (Should this be configurable?)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * When enabling threads, we use a pool of memory contexts shared by
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * client objects, since concurrent access to a shared context would cause
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * heavy contentions. The above constant is expected to be enough for
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * completely avoiding contentions among threads for an authoritative-only
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If named with built without thread, simply share manager's context. Using
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * a separate context in this case would simply waste memory.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define ECS_SIZE 20U /* 2 + 1 + 1 + [0..16] */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson/*% nameserver client manager structure */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Unlocked. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* The queue object has its own locks */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client_queue_t inactive; /*%< To be recycled */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Lock covers manager state. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Lock covers the clients list */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client_list_t clients; /*%< All active clients */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Lock covers the recursing list */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client_list_t recursing; /*%< Recursing clients */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /*%< mctx pool for clients. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Client object states. Ordering is significant: higher-numbered
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * states are generally "more active", meaning that the client can
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * have more dynamically allocated data, outstanding events, etc.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * In the list below, any such properties listed for state N
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * also apply to any state > N.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * To force the client into a less active state, set client->newstate
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * to that state and call exit_check(). This will cause any
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * activities defined for higher-numbered states to be aborted.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client object no longer exists.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client object exists and has a task and timer.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Its "query" struct and sendbuf are initialized.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * It is on the client manager's list of inactive clients.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * It has a message and OPT, both in the reset state.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client object is either a TCP or a UDP one, and
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * it is associated with a network interface. It is on the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * client manager's list of active clients.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If it is a TCP client object, it has a TCP listener socket
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * and an outstanding TCP listen request.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If it is a UDP client object, it has a UDP listener socket
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * and an outstanding UDP receive request.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client object is a TCP client object that has received
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * outstanding TCP read request. This state is not used for
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * UDP client objects.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client object has received a request and is working
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * on it. It has a view, and it may have any of a non-reset OPT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * recursion quota, and an outstanding write request.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client object is recursing. It will be on the 'recursing'
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Sentinel value used to indicate "no state". When client->newstate
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * has this value, we are not attempting to exit the current state.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Must be greater than any valid state.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Enable ns_client_dropport() by default.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void client_read(ns_client_t *client);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void client_accept(ns_client_t *client);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void client_udprecv(ns_client_t *client);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void clientmgr_destroy(ns_clientmgr_t *manager);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic isc_boolean_t exit_check(ns_client_t *client);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void ns_client_endrequest(ns_client_t *client);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void client_start(isc_task_t *task, isc_event_t *event);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void client_request(isc_task_t *task, isc_event_t *event);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void ns_client_dumpmessage(ns_client_t *client, const char *reason);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dns_dispatch_t *disp, isc_boolean_t tcp);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonallowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_uint8_t ecs_addrlen, isc_uint8_t *ecs_scope, dns_acl_t *acl);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic void compute_sit(ns_client_t *client, isc_uint32_t when,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_recursing(ns_client_t *client) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->newstate = client->state = NS_CLIENTSTATE_RECURSING;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley ISC_LIST_APPEND(client->manager->recursing, client, rlink);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_killoldestquery(ns_client_t *client) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson oldest = ISC_LIST_HEAD(client->manager->recursing);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_settimeout(ns_client_t *client, unsigned int seconds) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_log(client, NS_LOGCATEGORY_CLIENT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "setting timeout: %s",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Continue anyway. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Check for a deactivation or shutdown request and take appropriate
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * action. Returns ISC_TRUE if either is in progress; in this case
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the caller must no longer use the client object as it may have been
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_boolean_t destroy_manager = ISC_FALSE;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson return (ISC_FALSE); /* Business as usual. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(client->newstate < NS_CLIENTSTATE_RECURSING);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We need to detach from the view early when shutting down
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the server to break the following vicious circle:
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * - The resolver will not shut down until the view refcount is zero
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * - The view refcount does not go to zero until all clients detach
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * - The client does not detach from the view until references is zero
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * - references does not go to zero until the resolver has shut down
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Keep the view attached until any outstanding updates complete.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->state == NS_CLIENTSTATE_WORKING ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->state == NS_CLIENTSTATE_RECURSING)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(client->newstate <= NS_CLIENTSTATE_READING);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Let the update processing complete.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We are trying to abort request processing.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (! (client->nsends == 0 && client->nrecvs == 0 &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Still waiting for I/O cancel completion.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * or lingering references.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * I/O cancel is complete. Burn down all state
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley * related to the current request. Ensure that
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley * the client is no longer on the recursing list.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We need to check whether the client is still linked,
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley * because it may already have been removed from the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * recursing list by ns_client_killoldestquery()
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->state == NS_CLIENTSTATE_RECURSING) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (NS_CLIENTSTATE_READING == client->newstate) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->newstate = NS_CLIENTSTATE_INACTIVE;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->state == NS_CLIENTSTATE_READING) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We are trying to abort the current TCP connection,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(client->newstate <= NS_CLIENTSTATE_READY);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Still waiting for read cancel completion. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Now the client is ready to accept a new TCP connection
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * or UDP request, but we may have enough clients doing
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * that already. Check whether this client needs to remain
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * active and force it to go inactive if not.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * UDP clients go inactive at this point, but TCP clients
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * may remain active if we have fewer active TCP client
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * objects than desired due to an earlier quota exhaustion.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We don't need the client; send it to the inactive
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * queue for recycling.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->newstate > NS_CLIENTSTATE_INACTIVE)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->newstate = NS_CLIENTSTATE_INACTIVE;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (NS_CLIENTSTATE_READY == client->newstate) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->state == NS_CLIENTSTATE_READY) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We are trying to enter the inactive state.
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley isc_socket_cancel(client->tcplistener, client->task,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Still waiting for accept cancel completion. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Accept cancel is complete. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_socket_cancel(client->udpsocket, client->task,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Still waiting for recv cancel completion. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Still waiting for control event to be delivered */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Deactivate the client. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Put the client on the inactive list. If we are aiming for
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the "freed" state, it will be removed from the inactive
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * list shortly, and we need to keep the manager locked until
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * that has been done, lest the manager decide to reactivate
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the dying client inbetween.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (!ns_g_clienttest && manager != NULL &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ISC_QUEUE_PUSH(manager->inactive, client,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->state == NS_CLIENTSTATE_INACTIVE) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(client->newstate == NS_CLIENTSTATE_FREED);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We are trying to free the client.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * When "shuttingdown" is true, either the task has received
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * its shutdown event or no shutdown event has ever been
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * set up. Thus, we have no outstanding shutdown
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * event at this point.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(!ISC_QLINK_LINKED(client, ilink));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ISC_LIST_UNLINK(manager->clients, client, link);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_event_free((isc_event_t **)&client->sendevent);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_event_free((isc_event_t **)&client->recvevent);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_mem_put(client->mctx, client->tcpbuf,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(dns_rdataset_isassociated(client->opt));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dns_message_puttemprdataset(client->message,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Detaching the task must be done after unlinking from
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the manager's lists because the manager accesses
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * client->task.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Check that there are no other external references to
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the memory context.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Destroy the fetchlock mutex that was created in
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * ns_query_init().
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client's task has received the client's control event
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * as part of the startup process.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonclient_start(isc_task_t *task, isc_event_t *event) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_t *client = (ns_client_t *) event->ev_arg;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The client's task has received a shutdown event.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonclient_shutdown(isc_task_t *task, isc_event_t *event) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_endrequest(ns_client_t *client) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(client->state == NS_CLIENTSTATE_WORKING ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->state == NS_CLIENTSTATE_RECURSING);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(dns_rdataset_isassociated(client->opt));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dns_message_puttemprdataset(client->message, &client->opt);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_quota_detach(&client->recursionquota);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_decrement(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Clear all client attributes that are specific to
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the request; that's all except the TCP flag.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_next(ns_client_t *client, isc_result_t result) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->state == NS_CLIENTSTATE_RECURSING ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->state == NS_CLIENTSTATE_READING);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "request failed: %s", isc_result_totext(result));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * An error processing a TCP request may have left
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * the connection out of sync. To be safe, we always
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * sever the connection when result != ISC_R_SUCCESS.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonclient_senddone(isc_task_t *task, isc_event_t *event) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_socketevent_t *sevent = (isc_socketevent_t *) event;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_log(client, NS_LOGCATEGORY_CLIENT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "error sending response: %s",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We only want to fail with ISC_R_NOSPACE when called from
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * ns_client_sendraw() and not when called from ns_client_send(),
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * tcpbuffer is NULL when called from ns_client_sendraw() and
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * length != 0. tcpbuffer != NULL when called from ns_client_send()
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * and length == 0.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonclient_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_t *tcpbuffer, isc_uint32_t length,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned char *sendbuf, unsigned char **datap)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned char *data;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST((tcpbuffer == NULL && length != 0) ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_putuint16(buffer, (isc_uint16_t)length);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->attributes & NS_CLIENTATTR_HAVESIT) == 0) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonclient_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dispdscp = dns_dispatch_getdscp(client->dispatch);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = isc_socket_sendto2(sock, &r, client->task,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_sendraw(ns_client_t *client, dns_message_t *message) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned char *data;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = client_allocsendbuf(client, &buffer, NULL, mr->length,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Copy message to buffer and fixup id.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = isc_buffer_copyregion(&buffer, mr);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson r.base[0] = (client->message->id >> 8) & 0xff;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = client_sendpkg(client, &buffer);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned char *data;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->attributes & NS_CLIENTATTR_RA) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->view->preferred_glue == dns_rdatatype_a)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson preferred_glue = DNS_MESSAGERENDER_PREFER_A;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson else if (client->view->preferred_glue == dns_rdatatype_aaaa)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * filter-aaaa-on-v4 yes or break-dnssec option to suppress
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * AAAA records.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * We already know that request came via IPv4,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * that we have both AAAA and A records,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * and that we either have no signatures that the client wants
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * or we are supposed to break DNSSEC.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Override preferred glue if necessary.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson preferred_glue = DNS_MESSAGERENDER_PREFER_A;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Create an OPT for our reply.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = ns_client_addopt(client, client->message,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * XXXRTH The following doesn't deal with TCP buffer resizing.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_compress_init(&cctx, -1, client->mctx);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->peeraddr_valid && client->view != NULL) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (client->view->nocasecompress == NULL ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dns_compress_setsensitive(&cctx, ISC_TRUE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_renderbegin(client->message, &cctx, &buffer);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_setopt(client->message, client->opt);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_rendersection(client->message,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->message->flags |= DNS_MESSAGEFLAG_TC;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Stop after the question if TC was set for rate limiting.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_rendersection(client->message,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->message->flags |= DNS_MESSAGEFLAG_TC;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_rendersection(client->message,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->message->flags |= DNS_MESSAGEFLAG_TC;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_rendersection(client->message,
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_renderend(client->message);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = client_sendpkg(client, &tcpbuffer);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = client_sendpkg(client, &buffer);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Completes the sending of a delayed client response.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonclient_delay(isc_task_t *task, isc_event_t *event) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Delay the response by ns_g_delay ms.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Replace ourselves if we have not already been replaced.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_interval_set(&interval, ns_g_delay / 1000,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_interval_set(&interval, 0, ns_g_delay * 1000000);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = isc_timer_create(client->manager->timermgr,
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley * ns_client_dropport determines if certain requests / responses
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * should be dropped based on the port number.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * \li 0: Don't drop.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * \li 1: Drop request.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * \li 2: Drop (error) response.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonns_client_error(ns_client_t *client, isc_result_t result) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Don't send FORMERR to ports on the drop port list.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_buffer_init(&b, buf, sizeof(buf) - 1);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "dropped error (%.*s) response: suspicious port",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Try to rate limit error responses.
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley if (client->view != NULL && client->view->rrl != NULL) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson wouldlog = isc_log_wouldlog(ns_g_lctx, loglevel);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson rrl_result = dns_rrl(client->view, &client->peeraddr,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Log dropped errors in the query category
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * so that they are not lost in silence.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Starts of rate-limited bursts are logged in
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * NS_LOGCATEGORY_RRL.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Some error responses cannot be 'slipped',
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * so don't try to slip any error responses.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_stats_increment(ns_g_server->nsstats,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Message may be an in-progress reply that we had trouble
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * with, in which case QR will be set. We need to clear QR before
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * calling dns_message_reply() to avoid triggering an assertion.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * AA and AD shouldn't be set.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_reply(message, ISC_TRUE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * It could be that we've got a query with a good header,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * but a bad question section, so we try again with
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * want_question_section set to ISC_FALSE.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = dns_message_reply(message, ISC_FALSE);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * FORMERR loop avoidance: If we sent a FORMERR message
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * with the same ID to the same client less than two
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * seconds ago, assume that we are in an infinite error
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * packet dialog with a server for some protocol whose
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * error responses look enough like DNS queries to
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * elicit a FORMERR response. Drop a packet to break
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (isc_sockaddr_equal(&client->peeraddr,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson message->id == client->formerrcache.id &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->requesttime - client->formerrcache.time < 2) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Drop packet. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ns_client_log(client, NS_LOGCATEGORY_CLIENT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "possible error packet loop, "
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "FORMERR dropped");
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->formerrcache.addr = client->peeraddr;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->formerrcache.time = client->requesttime;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson } else if (rcode == dns_rcode_servfail && client->query.qname != NULL &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson client->view != NULL && client->view->fail_ttl != 0 &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0))
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * SERVFAIL caching: store qname/qtype of failed queries
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if ((message->flags & DNS_MESSAGEFLAG_CD) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_interval_set(&i, client->view->fail_ttl, 0);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson result = isc_time_nowplusinterval(&expire, &i);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson dns_badcache_add(client->view->failcache,
#ifdef ISC_PLATFORM_USESIT
int count = 0;
unsigned int flags;
goto no_nsid;
count++;
#ifdef ISC_PLATFORM_USESIT
count++;
count++;
for (i = 0; i < addrbytes; i++) {
unsigned char uc;
count++;
return (result);
static inline isc_boolean_t
int match;
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE);
if (!match)
#ifdef ISC_PLATFORM_USESIT
#ifdef AES_SIT
unsigned char *cp;
case AF_INET:
case AF_INET6:
#ifdef HMAC_SHA1_SIT
unsigned char *cp;
case AF_INET:
case AF_INET6:
#ifdef HMAC_SHA256_SIT
unsigned char *cp;
case AF_INET:
case AF_INET6:
unsigned char *old;
static isc_result_t
return (DNS_R_FORMERR);
if (scope != 0U) {
return (DNS_R_FORMERR);
switch (family) {
goto invalid_length;
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
for (i = 0; i < addrbytes; i++) {
optlen--;
return (ISC_R_SUCCESS);
static isc_result_t
goto cleanup;
switch (optcode) {
case DNS_OPT_NSID:
#ifdef ISC_PLATFORM_USESIT
case DNS_OPT_SIT:
case DNS_OPT_EXPIRE:
case DNS_OPT_CLIENT_SUBNET:
goto cleanup;
return (result);
int match;
unsigned int flags;
goto cleanup;
goto cleanup;
goto cleanup;
match > 0)
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
case dns_opcode_query:
case dns_opcode_update:
case dns_opcode_notify:
case dns_opcode_iquery:
if (ns_g_noedns)
if (ns_g_dropedns) {
goto cleanup;
goto cleanup;
goto cleanup;
&sockaddr);
goto cleanup;
view);
isc_buffer_t b;
isc_region_t *r;
sizeof(classname));
goto cleanup;
isc_buffer_t b;
goto cleanup;
case dns_opcode_query:
case dns_opcode_update:
case dns_opcode_notify:
case dns_opcode_iquery:
static isc_result_t
#if NMCTXS > 0
unsigned int nextmctx;
if (ns_g_clienttest) {
return (result);
#if NMCTXS > 0
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
return (result);
return (ISC_R_NOMEMORY);
goto cleanup_client;
goto cleanup_task;
goto cleanup_timer;
goto cleanup_message;
goto cleanup_sendevent;
goto cleanup_recvbuf;
#ifdef ALLOW_FILTER_AAAA
goto cleanup_recvevent;
goto cleanup_query;
return (ISC_R_SUCCESS);
return (result);
goto fail;
fail:
goto freeevent;
int match;
match > 0)
goto freeevent;
isc_region_t r;
return (result);
return (ISC_R_SUCCESS);
#if NMCTXS > 0
#if NMCTXS > 0
for (i = 0; i < NMCTXS; i++) {
#if NMCTXS > 0
return (ISC_R_NOMEMORY);
goto cleanup_manager;
goto cleanup_lock;
goto cleanup_listlock;
#if NMCTXS > 0
for (i = 0; i < NMCTXS; i++)
return (ISC_R_SUCCESS);
return (result);
if (unlock)
if (need_destroy)
static isc_result_t
return (ISC_R_SHUTTINGDOWN);
if (!ns_g_clienttest)
return (result);
if (tcp) {
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_SHUTTINGDOWN);
if (!ns_g_clienttest)
return (result);
return (ISC_R_SUCCESS);
unsigned int disp;
REQUIRE(n > 0);
return (result);
int match;
if (default_allow)
goto allow;
goto deny;
if (match > 0)
goto allow;
return (ISC_R_SUCCESS);
deny:
return (DNS_R_REFUSED);
return (result);
(unsigned int)len);
if (q != NULL) {
classbuf);
0, &buffer);
buf);
const char *name;
const char *sep;
const char *origfor;
sizeof(original));
sizeof(typebuf));
sizeof(classbuf));
return (ISC_R_SUCCESS);