summaryrefslogtreecommitdiff
path: root/doc/getaddrinfo.html
blob: d0fd1ac65c956ae8c4bbb12d8da25abb75da0ca9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Language" content="en" />
    <title>s6-dns: the problem with getaddrinfo()</title>
    <meta name="Description" content="s6-dns: the problem with getaddrinfo()" />
    <meta name="Keywords" content="s6-dns client library getaddrinfo API interface" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">s6-dns</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> The problem with getaddrinfo() </h1>

<p>
 The standard C library provides an API to perform name
resolution:
<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html">getaddrinfo()</a>,
formerly <tt>gethostbyname()</tt>. However, for DNS resolution as well as
implementation in the libc, this interface is very impractical, to the point of
being unusable. Here are a few reasons why.
</p>

<h2> getaddrinfo() performs NSS resolution, not DNS resolution. </h2>

<p>
 I explained this point in a message to the
<a href="http://busybox.net/">Busybox</a> mailing-list. You can
<a href="http://lists.busybox.net/pipermail/busybox/2012-July/078123.html">read
the post here</a>.
(There is a mistake in that post about <tt>/etc/nsswitch.conf</tt> and
<tt>/etc/host.conf</tt> syntax; the following two messages in the thread
correct that mistake.)
</p>

<p>
 TLDR: depending on the machine configuration, it is possible that
<tt>getaddrinfo()</tt> will not use DNS at all.
</p>

<h2> It is unboundedly synchronous. </h2>

<p>
 DNS resolution performs network I/O, which can take a non-negligible
amount of time. <tt>getaddrinfo()</tt> is a blocking call and there is
no way to specify a timeout to make it return early, so it may block
indefinitely. This is bad design.
</p>

<p>
 Also, network operations being asynchronous by nature, even a
synchronous API should provide a way to perform several queries at
once and return when one of them, or all of them, get an answer.
<tt>getaddrinfo()</tt> does not even offer that.
</p>

<h2> It focuses on the wrong details. </h2>

<p>
 Because it's generic, <tt>getaddrinfo()</tt> is cumbersome to use.
 The data structures are impractical, requiring the user to fill in
information that is irrelevant to DNS resolution. The details of the
network transport protocols are of no interest to the user who just
wants answers to his DNS queries!
</p>

<p>
 But at the same time, <tt>getaddrinfo()</tt> does not allow the
user to provide the details he wants or refine his search. It's a very
basic and monolithic entry point, with no DNS-specific knobs. For
instance, only A and AAAA queries are supported, which is clearly
insufficient.
</p>

<h2> Conclusion </h2>

<p>
<tt>getaddrinfo()</tt> is a toy interface. For any half-serious DNS work,
another API must be used.
</p>

<p>
 Most people who need a real DNS client library use BIND's libresolv.
<a href="libresolv.html">This page</a> explains what is wrong with it,
and what s6-dns tries to do better.
</p>

</body>
</html>