s6-dns: the s6dns_hosts library interface
Keywords: s6-dns dns s6dns_hosts library libs6dns /etc/hosts

libs6dns
s6-dns
Software
skarnet.org

# The `s6dns_hosts` library interface

The following functions are declared in the `s6-dns/hosts.h` header, and implemented in the `libs6dns.a` or `libs6dns.so` library.

## General information

`s6dns_hosts` provides functions and macros - mostly macros - to perform name-to-IP or IP-to-name resolution according to the local `/etc/hosts` file.

Most of the functions declared here are variations of another, more generic function. Typically, a foobar_r function is the generic one, and will take additional arguments such as: a pointer to a local hosts database (compiled to an efficient format), and/or a list and number of rules for qualification. The corresponding foobar function is the same, except that it uses global variables to fill these additional arguments: for instance, the hosts database made from `/etc/hosts`, or the qualification rules computed from `/etc/resolv.conf`. We document the simpler functions — even though they're macros, we pretend they're functions; please refer to the s6-dns/hosts.h file for the exact prototypes or if you want to use the generic functions.

- `s6dns_engine_here`: a global s6dns_engine_t storing the current query, for sequential queries.
- `s6dns_debughook_zero`: a global `s6dns_debughook_t` meaning no debugging is needed.
- `s6dns_rci_here`: a global s6dns_rci_t containing the current resolv.conf information.

## Global variables

`cdb s6dns_hosts_here`
`s6dns_hosts_here` is the global `cdb` database containing the compiled data from `/etc/hosts`. You normally do not need to use it manually because it is implicitly supplied to functions when you use the macros without a `_r` suffix.

## Functions

### Compilation

`int s6dns_hosts_compile (int fdr, int fdw)`
Compiles the text file data from file descriptor `fdr`, which should be in `/etc/hosts` format, into a cdb file written to file descriptor `fdw`. `fdr` must be open for reading, and `fdw` must be open for writing and seekable. The function returns 1 on success and 0 (and sets errno) on failure. A syntax error in the text file results in failure, but link-local addresses are silently ignored.

You normally don't need to use this function yourself. To compile the hosts database prior to use, you can call the s6-dns-hosts-compile program (which uses this function). Alternatively, at initialization time, the hosts database will be compiled automatically if there isn't a more recent compiled version.

### Initialization

`int s6dns_hosts_init (cdb *c, char const *txtfile, char const *cdbfile, char const *prefix)`
Initializes the compiled hosts database in *c. If there's a pre-compiled cdbfile file that is more recent than `/etc/hosts`, then it is used; else, the txtfile file is compiled into a temporary file starting with prefix, which is used and immediately unlinked. The function returns -1 (and sets errno) on failure, 1 on success, and 0 if it can find neither a suitable cdbfile nor a suitable txtfile.

`void s6dns_hosts_free (cdb *c)`
Frees the compiled hosts database in c.

You probably don't need to use these functions yourself: instead, the higher-level `s6dns_init()` and `s6dns_finish()` functions perform all the necessary initialization and cleanup, including the hosts database one.

### IP to name resolution

`int s6dns_hosts_name (char const *ip, stralloc *storage, genalloc *indices, int is6)`
Gets the list of names for IP address ip from the hosts database. The names are stored in the stralloc *storage; for each name, its index in storage→s is appended, as a `size_t`, to the genalloc *indices. If is6 is nonzero, ip is interpreted as an IPv6 address, i.e. a network byte order sequence of 16 bytes; otherwise it is interpreted as an IPv4 address, i.e. a network byte order sequence of 4 bytes. The function returns -1 (and sets errno) in case of failure, 0 if no match could be found (which includes no existing hosts database), or the number of names it found. Names listed as the first name on a line in `/etc/hosts` are always given as fully qualified, i.e. with a terminating dot; other names are given as they were input in `/etc/hosts`.

`int s6dns_hosts_name4 (char const *ip, stralloc *storage, genalloc *indices)`
Same, but ip is assumed to be an IPv4.

`int s6dns_hosts_name6 (char const *ip, stralloc *storage, genalloc *indices)`
Same, but ip is assumed to be an IPv6.

### Name to IP resolution

#### Fully qualified names

`extern int s6dns_hosts_a_noq (char const *name, stralloc *ip4s)`
Gets the list of IPv4 addresses for name name from the hosts database. The addresses are stored in the stralloc *ip4s, in network byte order, 4 bytes per item. name is assumed to be fully qualified: `skarnet.org` will yield the same results as `skarnet.org.`, and `blah` will yield the same results as `blah.` with the ending dot. The function returns -1 (and sets errno) in case of failure, 0 if no match (including no valid hosts database), or the number of IP addresses appended to *ip4s (i.e. the length increase divided by 4).

`extern int s6dns_hosts_aaaa_noq (char const *name, stralloc *ip6s)`
Same as above, but gets the list of IPv6 addresses for name; there are 16 bytes per address instead of 4.

`extern int s6dns_hosts_aaaaa_noq (char const *name, genalloc *ips)`
Same as above, but gets the list of all IP addresses for name, v4 or v6 indiscriminately. Every address is stored in the genalloc *ips as an `ip46full` structure.

#### Aliases

`extern int s6dns_hosts_a_unq (char const *name, stralloc *ip4s)`
Gets the list of IPv4 addresses for name name from the hosts database. The addresses are stored in the stralloc *ip4s, in network byte order, 4 bytes per item. name is assumed to be unqualified: `blah` is interpreted as a local alias that will only match a `blah` entry in `/etc/hosts` that does not appear as a first entry. The function returns -1 (and sets errno) in case of failure, 0 if no match (including no valid hosts database), or the number of IP addresses appended to *ip4s (i.e. the length increase divided by 4).

`extern int s6dns_hosts_aaaa_unq (char const *name, stralloc *ip6s)`
Same as above, but gets the list of IPv6 addresses for name; there are 16 bytes per address instead of 4.

`extern int s6dns_hosts_aaaaa_unq (char const *name, genalloc *ips)`
Same as above, but gets the list of all IP addresses for name, v4 or v6 indiscriminately. Every address is stored in the genalloc *ips as an `ip46full` structure.

#### With qualification

`extern int s6dns_hosts_a_q (char const *name, stralloc *ip4s)`
Gets the list of IPv4 addresses, from the hosts database, for all possible qualifications for name name. The addresses are stored in the stralloc *ip4s, in network byte order, 4 bytes per item. The function returns -1 (and sets errno) in case of failure, 0 if no match (including no valid hosts database), or the number of IP addresses appended to *ip4s (i.e. the length increase divided by 4).

First, name is looked up in the hosts database as a simple unqualified names. Then, name is qualified with all the suffixes read from `/etc/resolv.conf`, and all of the resulting FQDNs are looked up in the hosts database. All the results are concatenated and appended to the *ip4s stralloc.

`extern int s6dns_hosts_aaaa_q (char const *name, stralloc *ip6s)`
Same as above, but gets the list of IPv6 addresses for name; there are 16 bytes per address instead of 4.

`extern int s6dns_hosts_aaaaa_q (char const *name, genalloc *ips)`
Same as above, but gets the list of all IP addresses for name, v4 or v6 indiscriminately. Every address is stored in the genalloc *ips as an `ip46full` structure.