/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* $Id: adb.h,v 1.66.2.5.2.4 2004/03/06 08:13:50 marka Exp $ */ #ifndef DNS_ADB_H #define DNS_ADB_H 1 /***** ***** Module Info *****/ /* * DNS Address Database * * 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 * sent instead. * * Records are stored internally until a timer expires. The timer is the * smaller of the TTL or signature validity period. * * Lameness is stored per-zone, and this data hangs off each address field. * When an address is marked lame for a given zone the address will not * be returned to a caller. * * * MP: * * The ADB takes care of all necessary locking. * * Only the task which initiated the name lookup can cancel the lookup. * * * Security: * * 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) */ /*** *** Imports ***/ #include #include #include #include #include #include ISC_LANG_BEGINDECLS /*** *** Magic number checks ***/ #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) /*** *** TYPES ***/ typedef struct dns_adbname dns_adbname_t; /* dns_adbfind_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. */ struct dns_adbfind { /* Public */ 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 */ /* Private */ isc_mutex_t lock; /* locks all below */ in_port_t port; int name_bucket; unsigned int flags; dns_adbname_t *adbname; dns_adb_t *adb; isc_event_t event; ISC_LINK(dns_adbfind_t) plink; }; /* * _INET: * _INET6: * return addresses of that type. * * _EMPTYEVENT: * Only schedule an event if no addresses are known. * Must set _WANTEVENT for this to be meaningful. * * _WANTEVENT: * An event is desired. Check this bit in the returned find to see * if one will actually be generated. * * _AVOIDFETCHES: * If set, fetches will not be generated unless no addresses are * available in any of the address families requested. * * _STARTATZONE: * Fetches will start using the closest zone data or use the root servers. * This is useful for reestablishing glue that has expired. * * _GLUEOK: * _HINTOK: * Glue or hints are ok. These are used when matching names already * in the adb, and when dns databases are searched. * * _RETURNLAME: * Return lame servers in a find, so that all addresses are returned. * * _LAMEPRUNED: * 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(). */ #define DNS_ADBFIND_INET 0x00000001 #define DNS_ADBFIND_INET6 0x00000002 #define DNS_ADBFIND_ADDRESSMASK 0x00000003 #define DNS_ADBFIND_EMPTYEVENT 0x00000004 #define DNS_ADBFIND_WANTEVENT 0x00000008 #define DNS_ADBFIND_AVOIDFETCHES 0x00000010 #define DNS_ADBFIND_STARTATZONE 0x00000020 #define DNS_ADBFIND_GLUEOK 0x00000040 #define DNS_ADBFIND_HINTOK 0x00000080 #define DNS_ADBFIND_RETURNLAME 0x00000100 #define DNS_ADBFIND_LAMEPRUNED 0x00000200 /* dns_adbaddrinfo_t * * The answers to queries come back as a list of these. */ struct dns_adbaddrinfo { unsigned int magic; /* private */ isc_sockaddr_t sockaddr; /* [rw] */ unsigned int srtt; /* [rw] microseconds */ 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: * * DNS_EVENT_ADBMOREADDRESSES -- another address resolved. * DNS_EVENT_ADBNOMOREADDRESSES -- all pending addresses failed, * were canceled, or otherwise will * not be usable. * DNS_EVENT_ADBCANCELED -- The request was canceled by a * 3rd party. * DNS_EVENT_ADBNAMEDELETED -- The name was deleted, so this request * was canceled. * * 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. */ /**** **** FUNCTIONS ****/ isc_result_t dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *tmgr, isc_taskmgr_t *taskmgr, dns_adb_t **newadb); /* * Create a new ADB. * * Notes: * * Generally, applications should not create an ADB directly, but * should instead call dns_view_createresolver(). * * Requires: * * 'mem' must be a valid memory context. * * 'view' be a pointer to a valid view. * * 'tmgr' be a pointer to a valid timer manager. * * 'taskmgr' be a pointer to a valid task manager. * * 'newadb' != NULL && '*newadb' == NULL. * * Returns: * * ISC_R_SUCCESS after happiness. * ISC_R_NOMEMORY after resource allocation failure. */ void dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbp); /* * Attach to an 'adb' to 'adbp'. * * Requires: * 'adb' to be a valid dns_adb_t, created via dns_adb_create(). * 'adbp' to be a valid pointer to a *dns_adb_t which is initialized * to NULL. */ void dns_adb_detach(dns_adb_t **adb); /* * Delete the ADB. Sets *ADB to NULL. Cancels any outstanding requests. * * Requires: * * 'adb' be non-NULL and '*adb' be a valid dns_adb_t, created via * dns_adb_create(). */ void dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp); /* * Send '*eventp' to 'task' when 'adb' has shutdown. * * Requires: * * '*adb' is a valid dns_adb_t. * * eventp != NULL && *eventp is a valid event. * * Ensures: * * *eventp == NULL * * The event's sender field is set to the value of adb when the event * is sent. */ void dns_adb_shutdown(dns_adb_t *adb); /* * Shutdown 'adb'. * * Requires: * * '*adb' is a valid dns_adb_t. */ isc_result_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 *zone, unsigned int options, isc_stdtime_t now, dns_name_t *target, in_port_t port, dns_adbfind_t **find); /* * 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 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, and DNS_R_NX{DOMAIN,RRSET} 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 * time, however. * * 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 * be retrieved and used. * * 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 * events are sent. * * Requires: * * *adb be a valid isc_adb_t object. * * If events are to be sent, *task be a valid task, * and isc_taskaction_t != NULL. * * *name is a valid dns_name_t. * * zone != NULL and *zone be a valid dns_name_t. * * target == NULL or target is a valid name with a buffer. * * find != NULL && *find == NULL. * * Returns: * * ISC_R_SUCCESS Addresses might have been returned, and events will be * delivered for unresolved addresses. * 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. * ISC_R_NOMEMORY insufficient resources * DNS_R_ALIAS 'name' is an alias for another name. * * Calls, and returns error codes from: * * isc_stdtime_get() * * Notes: * * No internal reference to "name" exists after this function * returns. */ void 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. * * Note: * * 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). * * Requires: * * 'find' be a valid dns_adbfind_t pointer. * * events would have been posted to the task. This can be checked * with (find->options & DNS_ADBFIND_WANTEVENT). * * Ensures: * * The event was posted to the task. */ void dns_adb_destroyfind(dns_adbfind_t **find); /* * Destroys the find reference. * * Note: * * 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. * * Requires: * * 'find' != NULL and *find be valid dns_adbfind_t pointer. * * Ensures: * * No "address found" events will be posted to the originating task * after this function returns. */ void 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. * * Requires: * * adb be valid. * * f != NULL, and is a file open for writing. */ void dns_adb_dumpfind(dns_adbfind_t *find, FILE *f); /* * This function is only used for debugging. Dump the data associated * with a find. * * Requires: * * find is valid. * * f != NULL, and is a file open for writing. */ isc_result_t dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *zone, isc_stdtime_t expire_time); /* * Mark the given address as lame for the zone "zone". expire_time should * be set to the time when the entry should expire. That is, if it is to * expire 10 minutes in the future, it should set it to (now + 10 * 60). * * Requires: * * adb be valid. * * addr be valid. * * zone be the zone used in the dns_adb_createfind() call. * * Returns: * * ISC_R_SUCCESS -- all is well. * ISC_R_NOMEMORY -- could not mark address as lame. */ /* * A reasonable default for RTT adjustments */ #define DNS_ADB_RTTADJDEFAULT 7 /* default scale */ #define DNS_ADB_RTTADJREPLACE 0 /* replace with our rtt */ #define DNS_ADB_RTTADJAGE 10 /* age this rtt */ void dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor); /* * Mix the round trip time into the existing smoothed rtt. The formula used * (where srtt is the existing rtt value, and rtt and factor are arguments to * this function): * * new_srtt = (old_srtt / 10 * factor) + (rtt / 10 * (10 - factor)); * * XXXRTH Do we want to publish the formula? What if we want to change how * this works later on? Recommend/require that the units are * microseconds? * * Requires: * * adb be valid. * * addr be valid. * * 0 <= factor <= 10 * * Note: * * The srtt in addr will be updated to reflect the new global * srtt value. This may include changes made by others. */ void dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits, unsigned int mask); /* * Set the flags as given by: * * newflags = (oldflags & ~mask) | (bits & mask); * * Requires: * * adb be valid. * * addr be valid. */ isc_result_t dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa, dns_adbaddrinfo_t **addrp, isc_stdtime_t now); /* * Return a dns_adbaddrinfo_t that is associated with address 'sa'. * * Requires: * * adb is valid. * * sa is valid. * * addrp != NULL && *addrp == NULL * * Returns: * ISC_R_SUCCESS * ISC_R_NOMEMORY * ISC_R_SHUTTINGDOWN */ void dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp); /* * Free a dns_adbaddrinfo_t allocated by dns_adb_findaddrinfo(). * * Requires: * * adb is valid. * * *addrp is a valid dns_adbaddrinfo_t *. */ void dns_adb_flush(dns_adb_t *adb); /* * Flushes all cached data from the adb. * * Requires: * adb is valid. */ void dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size); /* * Set a target memory size. If memory usage exceeds the target * size entries will be removed before they would have expired on * a random basis. * * If 'size' is 0 then memory usage is unlimited. * * Requires: * 'adb' is valid. */ void dns_adb_flushname(dns_adb_t *adb, dns_name_t *name); /* * Flush 'name' from the adb cache. * * Requires: * 'adb' is valid. * 'name' is valid. */ ISC_LANG_ENDDECLS #endif /* DNS_ADB_H */