s6-dns: the problem with libresolv
Keywords: s6-dns client library libresolv BIND API interface

s6-dns
Software
skarnet.org

# The problem with libresolv

The BIND name server software comes with its own client library, named libresolv.

As can be expected from an ISC product, libresolv is not good software. Here are a few reasons why.

## libresolv's security model is flawed.

The same people who wrote BIND wrote libresolv. That is the amount of trust you can place in libresolv. Ten years ago, the security status of libresolv looked like this. I am not confident that is has improved: bugs in the software may have been fixed, but new ones will appear, and most importantly, the security management policy at ISC is still the same: security holes will be denied instead of acknowledged and worked upon.

If you find a bug, and a fortiori a security hole, in s6-dns, you can be sure it will be fixed promptly with apologies from the author. skarnet.org doesn't do obfuscation, and never lets politics get in the way of technical quality.

## libresolv is unboundedly synchronous.

You'd expect a real DNS client library to do better in this aspect than getaddrinfo(), but no: libresolv's function calls are still purely synchronous and may uncontrollably block if the network is unresponsive.

Additionally, libresolv only provides a synchronous interface to clients. Despite the fundamentally asynchronous nature of DNS, and the need to implement asynchronous primitives internally, only blocking calls are made available in the API. This forces users to stack yet another piece of software on top of their dependencies if they need asynchronous DNS resolution.

libs6dns provides several layers of asynchronous interfaces. The user has access to low-level packet sending and receiving, to synchronous resolution of several queries at once, and to a real high-level asynchronous DNS library.

## It is too big for what it does.

The `libresolv-2.13.so` binary file compiled for an x86_64 Debian Linux system is roughly 79k bytes. The `libs6dns.so.2.0` file, for the same system, is a little bit smaller, while offering more functionality: high-level answer parsing, user-friendly formatting, and in-depth tracing of the DNS resolution process. What is all that code in libresolv for ?

## The API is cumbersome to use.

Some examples of less-than-ideal interfaces for the users:

- There is a flag in libresolv's global state structure that determines if queries are to be sent recursive or iterative. Which means that a program that needs to make both recursive and iterative queries must duplicate this state structure and use one for recursive queries, one for iterative queries. Why this complexity ? The recursive flag should be given for every query, not be a part of the resolver state.
- When a libresolv answer arrives but doesn't fit into the user-supplied buffer, the query is discarded and has to be retried. Does "network efficiency" ring a bell ? Also, the length of the original answer is returned by the first call, which is a good thing: the user can now provide a large enough buffer so the call succeeds the next time, right ? Wrong. The next answer can be different from the first, and in particular, longer, which means that the next query can still fail.

There is a reason why system calls and local functions take user-supplied buffers as arguments. They are relatively fast, it is not too costly to call them again if the buffer is too small the first time, and the result is consistent, i.e. after the first call, the right buffer length is known. But functions making network exchanges with variable-length results from one call to another ? Those need heap-allocated storage. It is good design to avoid using the heap whenever possible, but it is not good design to waste network round-trips to save a `malloc()`.

## Conclusion

Like many other "standards", and C library interfaces in particular, `libresolv` is at best a mediocre one, that people use because there has been nothing better so far.

s6-dns tries to be an alternative solution, based on solid design principles and a reliable code base. It just works, and it makes DNS resolution nice and easy for users.