* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
* This module implements an address database (ADB) for mapping a name
* to an isc_sockaddr_t. It also provides statistical information on
* how good that address might be.
* A client will pass in a dns_name_t, and the ADB will walk through
* the rdataset looking up addresses associated with the name. If it
* is found on the internal lists, a structure is filled in with the
* address information and stats for found addresses.
* If the name cannot be found on the internal lists, a new entry will
* be created for a name if all the information needed can be found
* in the zone table or cache. This new address will then be returned.
* If a request must be made to remote servers to satisfy a name lookup,
* this module will start fetches to try to complete these addresses. When
* at least one more completes, an event is sent to the caller. If none of
* them resolve before the fetch times out, an event indicating this is
* Records are stored internally until a timer expires. The timer is the
* smaller of the TTL or signature validity period.
* Lameness is stored per <qname,qtype> tuple, and this data hangs off each
* address field. When an address is marked lame for a given tuple the address
* will not be returned to a caller.
*\li The ADB takes care of all necessary locking.
*\li Only the task which initiated the name lookup can cancel the lookup.
*\li None, since all data stored is required to be pre-filtered.
* (Cache needs to be sane, fetches return bounds-checked and sanity-
* checked data, caller passes a good dns_name_t for the zone, etc)
#include <isc/sockaddr.h>
#define DNS_ADBFIND_MAGIC ISC_MAGIC('a','d','b','H')
#define DNS_ADBFIND_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFIND_MAGIC)
#define DNS_ADBADDRINFO_MAGIC ISC_MAGIC('a','d','A','I')
#define DNS_ADBADDRINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBADDRINFO_MAGIC)
typedef struct dns_adbname dns_adbname_t;
* Represents a lookup for a single name.
* On return, the client can safely use "list", and can reorder the list.
* Items may not be _deleted_ from this list, however, or added to it
* other than by using the dns_adb_*() API.
unsigned int magic; /*%< RO: magic */
dns_adbaddrinfolist_t list; /*%< RO: list of addrs */
unsigned int query_pending; /*%< RO: partial list */
unsigned int partial_result; /*%< RO: addrs missing */
unsigned int options; /*%< RO: options */
isc_result_t result_v4; /*%< RO: v4 result */
isc_result_t result_v6; /*%< RO: v6 result */
ISC_LINK(dns_adbfind_t) publink; /*%< RW: client use */
isc_mutex_t lock; /* locks all below */
ISC_LINK(dns_adbfind_t) plink;
* return addresses of that type.
* Only schedule an event if no addresses are known.
* Must set _WANTEVENT for this to be meaningful.
* An event is desired. Check this bit in the returned find to see
* if one will actually be generated.
* If set, fetches will not be generated unless no addresses are
* available in any of the address families requested.
* Fetches will start using the closest zone data or use the root servers.
* This is useful for reestablishing glue that has expired.
* Glue or hints are ok. These are used when matching names already
* in the adb, and when dns databases are searched.
* Return lame servers in a find, so that all addresses are returned.
* At least one address was omitted from the list because it was lame.
* This bit will NEVER be set if _RETURNLAME is set in the createfind().
/*% Return addresses of type INET. */
#define DNS_ADBFIND_INET 0x00000001
/*% Return addresses of type INET6. */
#define DNS_ADBFIND_INET6 0x00000002
#define DNS_ADBFIND_ADDRESSMASK 0x00000003
* Only schedule an event if no addresses are known.
* Must set _WANTEVENT for this to be meaningful.
#define DNS_ADBFIND_EMPTYEVENT 0x00000004
* An event is desired. Check this bit in the returned find to see
* if one will actually be generated.
#define DNS_ADBFIND_WANTEVENT 0x00000008
* If set, fetches will not be generated unless no addresses are
* available in any of the address families requested.
#define DNS_ADBFIND_AVOIDFETCHES 0x00000010
* Fetches will start using the closest zone data or use the root servers.
* This is useful for reestablishing glue that has expired.
#define DNS_ADBFIND_STARTATZONE 0x00000020
* Glue or hints are ok. These are used when matching names already
* in the adb, and when dns databases are searched.
#define DNS_ADBFIND_GLUEOK 0x00000040
* Glue or hints are ok. These are used when matching names already
* in the adb, and when dns databases are searched.
#define DNS_ADBFIND_HINTOK 0x00000080
* Return lame servers in a find, so that all addresses are returned.
#define DNS_ADBFIND_RETURNLAME 0x00000100
* Only schedule an event if no addresses are known.
* Must set _WANTEVENT for this to be meaningful.
#define DNS_ADBFIND_LAMEPRUNED 0x00000200
* The server's fetch quota is exceeded; it will be treated as
#define DNS_ADBFIND_OVERQUOTA 0x00000400
* Don't perform a fetch even if there are no address records available.
#define DNS_ADBFIND_NOFETCH 0x00000800
* The answers to queries come back as a list of these.
unsigned int magic; /*%< private */
isc_sockaddr_t sockaddr; /*%< [rw] */
unsigned int srtt; /*%< [rw] microsecs */
unsigned int flags; /*%< [rw] */
dns_adbentry_t *entry; /*%< private */
ISC_LINK(dns_adbaddrinfo_t) publink;
* The event sent to the caller task is just a plain old isc_event_t. It
* contains no data other than a simple status, passed in the "type" field
* to indicate that another address resolved, or all partially resolved
* addresses have failed to resolve.
* "sender" is the dns_adbfind_t used to issue this query.
* This is simply a standard event, with the "type" set to:
*\li #DNS_EVENT_ADBMOREADDRESSES -- another address resolved.
*\li #DNS_EVENT_ADBNOMOREADDRESSES -- all pending addresses failed,
* were canceled, or otherwise will
*\li #DNS_EVENT_ADBCANCELED -- The request was canceled by a
*\li #DNS_EVENT_ADBNAMEDELETED -- The name was deleted, so this request
* In each of these cases, the addresses returned by the initial call
* to dns_adb_createfind() can still be used until they are no longer needed.
dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *tmgr,
isc_taskmgr_t *taskmgr, dns_adb_t **newadb);
*\li Generally, applications should not create an ADB directly, but
* should instead call dns_view_createresolver().
*\li 'mem' must be a valid memory context.
*\li 'view' be a pointer to a valid view.
*\li 'tmgr' be a pointer to a valid timer manager.
*\li 'taskmgr' be a pointer to a valid task manager.
*\li 'newadb' != NULL && '*newadb' == NULL.
*\li #ISC_R_SUCCESS after happiness.
*\li #ISC_R_NOMEMORY after resource allocation failure.
dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbp);
* Attach to an 'adb' to 'adbp'.
*\li 'adb' to be a valid dns_adb_t, created via dns_adb_create().
*\li 'adbp' to be a valid pointer to a *dns_adb_t which is initialized
dns_adb_detach(dns_adb_t **adb);
* Delete the ADB. Sets *ADB to NULL. Cancels any outstanding requests.
*\li 'adb' be non-NULL and '*adb' be a valid dns_adb_t, created via
dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp);
* Send '*eventp' to 'task' when 'adb' has shutdown.
*\li '*adb' is a valid dns_adb_t.
*\li eventp != NULL && *eventp is a valid event.
*\li The event's sender field is set to the value of adb when the event
dns_adb_shutdown(dns_adb_t *adb);
* \li '*adb' is a valid dns_adb_t.
dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
void *arg, dns_name_t *name, dns_name_t *qname,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, dns_adbfind_t **find);
dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
void *arg, dns_name_t *name, dns_name_t *qname,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target, in_port_t port,
unsigned int depth, isc_counter_t *qc,
* Main interface for clients. The adb will look up the name given in
* "name" and will build up a list of found addresses, and perhaps start
* internal fetches to resolve names that are unknown currently.
* If other addresses resolve after this call completes, an event will
* be sent to the <task, taskaction, arg> with the sender of that event
* set to a pointer to the dns_adbfind_t returned by this function.
* If no events will be generated, the *find->result_v4 and/or result_v6
* members may be examined for address lookup status. The usual #ISC_R_SUCCESS,
* #ISC_R_FAILURE, #DNS_R_NXDOMAIN, and #DNS_R_NXRRSET are returned, along with
* #ISC_R_NOTFOUND meaning the ADB has not _yet_ found the values. In this
* latter case, retrying may produce more addresses.
* If events will be returned, the result_v[46] members are only valid
* when that event is actually returned.
* The list of addresses returned is unordered. The caller must impose
* any ordering required. The list will not contain "known bad" addresses,
* however. For instance, it will not return hosts that are known to be
* lame for the zone in question.
* The caller cannot (directly) modify the contents of the address list's
* fields other than the "link" field. All values can be read at any
* The "now" parameter is used only for determining which entries that
* have a specific time to live or expire time should be removed from
* the running database. If specified as zero, the current time will
* If 'target' is not NULL and 'name' is an alias (i.e. the name is
* CNAME'd or DNAME'd to another name), then 'target' will be updated with
* the domain name that 'name' is aliased to.
* All addresses returned will have the sockaddr's port set to 'port.'
* The caller may change them directly in the dns_adbaddrinfo_t since
* they are copies of the internal address only.
* XXXMLG Document options, especially the flags which control how
*\li *adb be a valid isc_adb_t object.
*\li If events are to be sent, *task be a valid task,
* and isc_taskaction_t != NULL.
*\li *name is a valid dns_name_t.
*\li qname != NULL and *qname be a valid dns_name_t.
*\li target == NULL or target is a valid name with a buffer.
*\li find != NULL && *find == NULL.
*\li #ISC_R_SUCCESS Addresses might have been returned, and events will be
* delivered for unresolved addresses.
*\li #ISC_R_NOMORE Addresses might have been returned, but no events
* will ever be posted for this context. This is only
* returned if task != NULL.
*\li #ISC_R_NOMEMORY insufficient resources
*\li #DNS_R_ALIAS 'name' is an alias for another name.
* Calls, and returns error codes from:
*\li No internal reference to "name" exists after this function
dns_adb_cancelfind(dns_adbfind_t *find);
* Cancels the find, and sends the event off to the caller.
* It is an error to call dns_adb_cancelfind() on a find where
* no event is wanted, or will ever be sent.
*\li It is possible that the real completion event was posted just
* before the dns_adb_cancelfind() call was made. In this case,
* dns_adb_cancelfind() will do nothing. The event callback needs
* to be prepared to find this situation (i.e. result is valid but
* the caller expects it to be canceled).
*\li 'find' be a valid dns_adbfind_t pointer.
*\li events would have been posted to the task. This can be checked
* with (find->options & DNS_ADBFIND_WANTEVENT).
*\li The event was posted to the task.
dns_adb_destroyfind(dns_adbfind_t **find);
* Destroys the find reference.
*\li This can only be called after the event was delivered for a
* find. Additionally, the event MUST have been freed via
* isc_event_free() BEFORE this function is called.
*\li 'find' != NULL and *find be valid dns_adbfind_t pointer.
*\li No "address found" events will be posted to the originating task
* after this function returns.
dns_adb_dump(dns_adb_t *adb, FILE *f);
* This function is only used for debugging. It will dump as much of the
* state of the running system as possible.
*\li f != NULL, and is a file open for writing.
dns_adb_dumpfind(dns_adbfind_t *find, FILE *f);
* This function is only used for debugging. Dump the data associated