Welcome, gentle reader.
Async DNS lookups are really a whole lot harder than they should
be, mostly stemming from the fact that the libc resolver has never been very
good at them. Before you use this library you should see if libc can do the
job for you with the modern async call getaddrinfo_a (see
http://www.imperialviolet.org/page25.html#e498). Otherwise, please
continue.
The library keeps track of the state of nameservers and will avoid
them when they go down. Otherwise it will round robin between them.
Quick start guide: #include 'evdns.h' void callback(int result,
char type, int count, int ttl, void *addresses, void *arg);
evdns_resolv_conf_parse(DNS_OPTIONS_ALL, '/etc/resolv.conf');
evdns_resolve('www.hostname.com', 0, callback, NULL);
When the lookup is complete the callback function is called. The
first argument will be one of the DNS_ERR_* defines in evdns.h. Hopefully it
will be DNS_ERR_NONE, in which case type will be DNS_IPv4_A, count will be
the number of IP addresses, ttl is the time which the data can be cached for
(in seconds), addresses will point to an array of uint32_t's and arg will be
whatever you passed to evdns_resolve.
Searching:
In order for this library to be a good replacement for glibc's
resolver it supports searching. This involves setting a list of default
domains, in which names will be queried for. The number of dots in the query
name determines the order in which this list is used.
Searching appears to be a single lookup from the point of view of
the API, although many DNS queries may be generated from a single call to
evdns_resolve. Searching can also drastically slow down the resolution of
names.
To disable searching:
- 1.
- Never set it up. If you never call evdns_resolv_conf_parse or
evdns_search_add then no searching will occur.
- 2.
- If you do call evdns_resolv_conf_parse then don't pass DNS_OPTION_SEARCH
(or DNS_OPTIONS_ALL, which implies it).
- 3.
- When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag.
The order of searches depends on the number of dots in the name.
If the number is greater than the ndots setting then the names is first
tried globally. Otherwise each search domain is appended in turn.
The ndots setting can either be set from a resolv.conf, or by
calling evdns_search_ndots_set.
For example, with ndots set to 1 (the default) and a search domain
list of ['myhome.net']: Query: www Order: www.myhome.net, www.
Query: www.abc Order: www.abc., www.abc.myhome.net
Internals:
Requests are kept in two queues. The first is the inflight queue.
In this queue requests have an allocated transaction id and nameserver. They
will soon be transmitted if they haven't already been.
The second is the waiting queue. The size of the inflight ring is
limited and all other requests wait in waiting queue for space. This bounds
the number of concurrent requests so that we don't flood the nameserver.
Several algorithms require a full walk of the inflight queue and so bounding
its size keeps thing going nicely under huge (many thousands of requests)
loads.
If a nameserver loses too many requests it is considered down and
we try not to use it. After a while we send a probe to that nameserver (a
lookup for google.com) and, if it replies, we consider it working again. If
the nameserver fails a probe we wait longer to try again with the next
probe.
Create a new DNS server port.
Parameters:
base The event base to handle events for the
server port.
socket A UDP socket to accept DNS requests.
flags Always 0 for now.
callback A function to invoke whenever we get a DNS request on the
socket.
user_data Data to pass to the callback.
Returns:
an evdns_server_port structure for this server
port.
Remove all hosts entries that have been loaded into the event_base via
evdns_base_load_hosts or via event_base_resolv_conf_parse.
Parameters:
evdns_base the evdns base to remove outdated host
addresses from
Remove all configured nameservers, and suspend all pending resolves. Resolves
will not necessarily be re-attempted until evdns_base_resume() is
called.
Parameters:
base the evdns_base to which to apply this
operation
Returns:
0 if successful, or -1 if an error occurred
See also:
evdns_base_resume()
Get the number of configured nameservers. This returns the number of configured
nameservers (not necessarily the number of running nameservers). This is
useful for double-checking whether our calls to the various nameserver
configuration functions have been successful.
Parameters:
base the evdns_base to which to apply this
operation
Returns:
the number of configured nameservers
See also:
evdns_base_nameserver_add()
Shut down the asynchronous DNS resolver and terminate all active requests. If
the 'fail_requests' option is enabled, all active requests will return an
empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, the
requests will be silently discarded.
Parameters:
evdns_base the evdns base to free
fail_requests if zero, active requests will be aborted; if non-zero,
active requests will return DNS_ERR_SHUTDOWN.
See also:
evdns_base_new()
Retrieve the address of the 'idx'th configured nameserver.
Parameters:
base The evdns_base to examine.
idx The index of the nameserver to get the address of.
sa A location to receive the server's address.
len The number of bytes available at sa.
Returns:
the number of bytes written into sa on success. On
failure, returns -1 if idx is greater than the number of configured
nameservers, or a value greater than 'len' if len was not high enough.
Load an /etc/hosts-style file from 'hosts_fname' into 'base'. If hosts_fname is
NULL, add minimal entries for localhost, and nothing else.
Note that only evdns_getaddrinfo uses the /etc/hosts entries.
This function does not replace previously loaded hosts entries; to
do that, call evdns_base_clear_host_addresses first.
Return 0 on success, negative on failure.
Add a nameserver. The address should be an IPv4 address in network byte order.
The type of address is chosen so that it matches in_addr.s_addr.
Parameters:
base the evdns_base to which to add the name
server
address an IP address in network byte order
Returns:
0 if successful, or -1 if an error occurred
See also:
evdns_base_nameserver_ip_add()
Add a nameserver by string address. This function parses a n IPv4 or IPv6
address from a string and adds it as a nameserver. It supports the following
formats:
- [IPv6Address]:port
- [IPv6Address]
- IPv6Address
- IPv4Address:port
- IPv4Address
If no port is specified, it defaults to 53.
Parameters:
base the evdns_base to which to apply this
operation
Returns:
0 if successful, or -1 if an error occurred
See also:
evdns_base_nameserver_add()
Initialize the asynchronous DNS library. This function initializes support for
non-blocking name resolution by calling evdns_resolv_conf_parse() on
UNIX and evdns_config_windows_nameservers() on Windows.
Parameters:
event_base the event base to
associate the dns client with
flags any of EVDNS_BASE_INITIALIZE_NAMESERVERS|
EVDNS_BASE_DISABLE_WHEN_INACTIVE
Returns:
evdns_base object if successful, or NULL if an error
occurred.
See also:
evdns_base_free()
Parse a resolv.conf file. The 'flags' parameter determines what information is
parsed from the resolv.conf file. See the man page for resolv.conf for the
format of this file.
The following directives are not parsed from the file: sortlist,
rotate, no-check-names, inet6, debug.
If this function encounters an error, the possible return values
are: 1 = failed to open file, 2 = failed to stat file, 3 = file too large, 4
= out of memory, 5 = short read from file, 6 = no nameservers listed in the
file
Parameters:
base the evdns_base to which to apply this
operation
flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL
filename the path to the resolv.conf file
Returns:
0 if successful, or various positive error codes if an
error occurred (see above)
See also:
resolv.conf(3), evdns_config_windows_nameservers()
Lookup an A record for a given name.
Parameters:
base the evdns_base to which to apply this
operation
name a DNS hostname
flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this
query.
callback a callback function to invoke when the request is completed
ptr an argument to pass to the callback function
Returns:
an evdns_request object if successful, or NULL if an
error occurred.
See also:
evdns_resolve_ipv6(),
evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(),
evdns_cancel_request()
Lookup an AAAA record for a given name.
Parameters:
base the evdns_base to which to apply this
operation
name a DNS hostname
flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this
query.
callback a callback function to invoke when the request is completed
ptr an argument to pass to the callback function
Returns:
an evdns_request object if successful, or NULL if an
error occurred.
See also:
evdns_resolve_ipv4(),
evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(),
evdns_cancel_request()
Lookup a PTR record for a given IP address.
Parameters:
base the evdns_base to which to apply this
operation
in an IPv4 address
flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this
query.
callback a callback function to invoke when the request is completed
ptr an argument to pass to the callback function
Returns:
an evdns_request object if successful, or NULL if an
error occurred.
See also:
evdns_resolve_reverse_ipv6(),
evdns_cancel_request()
Lookup a PTR record for a given IPv6 address.
Parameters:
base the evdns_base to which to apply this
operation
in an IPv6 address
flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this
query.
callback a callback function to invoke when the request is completed
ptr an argument to pass to the callback function
Returns:
an evdns_request object if successful, or NULL if an
error occurred.
See also:
evdns_resolve_reverse_ipv6(),
evdns_cancel_request()
Resume normal operation and continue any suspended resolve requests. Re-attempt
resolves left in limbo after an earlier call to
evdns_base_clear_nameservers_and_suspend().
Parameters:
base the evdns_base to which to apply this
operation
Returns:
0 if successful, or -1 if an error occurred
See also:
evdns_base_clear_nameservers_and_suspend()
Add a domain to the list of search domains.
Parameters:
domain the domain to be added to the search
list
Obtain nameserver information using the Windows API. Attempt to configure a set
of nameservers based on platform settings on a win32 host. Preferentially
tries to use GetNetworkParams; if that fails, looks in the registry.
Returns:
0 if successful, or -1 if an error occurred
See also:
evdns_resolv_conf_parse() Clear the list of search
domains.
Set the 'ndots' parameter for searches. Sets the number of dots which, when
found in a name, causes the first query to be without any search domain.
Parameters:
ndots the new ndots parameter
Set the value of a configuration option. The currently available configuration
options are:
ndots, timeout, max-timeouts, max-inflight, attempts,
randomize-case, bind-to, initial-probe-timeout, getaddrinfo-allow-skew.
In versions before Libevent 2.0.3-alpha, the option name needed to
end with a colon.
Parameters:
base the evdns_base to which to apply this
operation
option the name of the configuration option to be modified
val the value to be set
Returns:
0 if successful, or -1 if an error occurred
Cancels a pending DNS resolution request.
Parameters:
base the evdns_base that was used to make the
request
req the evdns_request that was returned by calling a resolve
function
See also:
evdns_base_resolve_ipv4(),
evdns_base_resolve_ipv6, evdns_base_resolve_reverse
Close down a DNS server port, and free associated structures.
Convert a DNS error code to a string.
Parameters:
err the DNS error code
Returns:
a string containing an explanation of the error
code
Make a non-blocking getaddrinfo request using the dns_base in 'dns_base'. If we
can answer the request immediately (with an error or not!), then we invoke cb
immediately and return NULL. Otherwise we return an evdns_getaddrinfo_request
and invoke cb later.
When the callback is invoked, we pass as its first argument the
error code that getaddrinfo would return (or 0 for no error). As its second
argument, we pass the evutil_addrinfo structures we found (or NULL on
error). We pass 'arg' as the third argument.
Limitations:
- The AI_V4MAPPED and AI_ALL flags are not currently implemented.
- For ai_socktype, we only handle SOCKTYPE_STREAM, SOCKTYPE_UDP, and 0.
- For ai_protocol, we only handle IPPROTO_TCP, IPPROTO_UDP, and 0.
Sets some flags in a reply we're building. Allows setting of the AA or RD flags
Set the callback function to handle DNS log messages. If this callback is not
set, evdns log messages are handled with the regular Libevent logging system.
Parameters:
fn the callback to be invoked when a log message
is generated
Set a callback used to generate random bytes. By default, we use the same
function as passed to evdns_set_transaction_id_fn to generate bytes two at a
time. If a function is provided here, it's also used to generate transaction
IDs.
NOTE: This function has no effect in Libevent 2.0.4-alpha and
later, since Libevent now provides its own secure RNG.
Set a callback that will be invoked to generate transaction IDs. By default, we
pick transaction IDs based on the current clock time, which is bad for
security.
Parameters:
fn the new callback, or NULL to use the
default.
NOTE: This function has no effect in Libevent 2.0.4-alpha and
later, since Libevent now provides its own secure RNG.