1<?xml version="1.0" encoding="utf-8" ?>
2<!DOCTYPE erlref SYSTEM "erlref.dtd">
3
4<erlref>
5  <header>
6    <copyright>
7      <year>2009</year><year>2021</year>
8      <holder>Ericsson AB. All Rights Reserved.</holder>
9    </copyright>
10    <legalnotice>
11      Licensed under the Apache License, Version 2.0 (the "License");
12      you may not use this file except in compliance with the License.
13      You may obtain a copy of the License at
14
15          http://www.apache.org/licenses/LICENSE-2.0
16
17      Unless required by applicable law or agreed to in writing, software
18      distributed under the License is distributed on an "AS IS" BASIS,
19      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20      See the License for the specific language governing permissions and
21      limitations under the License.
22
23    </legalnotice>
24
25    <title>inet_res</title>
26    <prepared>raimo@erix.ericsson.se</prepared>
27    <docno></docno>
28    <date>2009-09-11</date>
29    <rev>A</rev>
30  </header>
31  <module since="">inet_res</module>
32  <modulesummary>A rudimentary DNS client.</modulesummary>
33  <description>
34    <p>This module performs DNS name resolving to recursive name servers.</p>
35    <p>See also
36      <seeguide marker="erts:inet_cfg">ERTS User's Guide: Inet Configuration</seeguide>
37      for more information about how to configure an Erlang runtime system
38      for IP communication, and how to enable this DNS client by defining
39      <c><![CDATA['dns']]></c> as a lookup method.
40      The DNS client then acts as a backend for the resolving functions in
41      <seeerl marker="kernel:inet"><c>inet</c></seeerl>.</p>
42    <p>This DNS client can resolve DNS records even if it
43      is not used for normal name resolving in the node.</p>
44    <p>This is not a full-fledged resolver, only a
45      DNS client that relies on asking trusted recursive name servers.</p>
46  </description>
47
48  <section>
49    <title>Name Resolving</title>
50    <p>UDP queries are used unless resolver option
51    <c>usevc</c> is <c>true</c>, which forces TCP queries.
52    If the query is too large for UDP, TCP is used instead.
53    For regular DNS queries, 512 bytes is the size limit.</p>
54
55    <p>When EDNS is enabled (resolver option
56    <c>edns</c> is set to the EDNS version (that is, <c>0</c>
57    instead of <c>false</c>), resolver option
58    <c>udp_payload_size</c> sets the limit. If a name server
59    replies with the TC bit set (truncation), indicating that
60    the answer is incomplete, the query is retried
61    to that name server using TCP. Resolver option
62    <c>udp_payload_size</c> also sets the advertised
63    size for the maximum allowed reply size, if EDNS is
64    enabled, otherwise the name server uses the limit
65    512 bytes. If the reply is larger, it gets truncated,
66    forcing a TCP requery.</p>
67
68    <p>For UDP queries, resolver options <c>timeout</c>
69    and <c>retry</c> control retransmission.
70    Each name server in the <c>nameservers</c> list is
71    tried with a time-out of <c>timeout</c>/<c>retry</c>.
72    Then all name servers are tried again, doubling the
73    time-out, for a total of <c>retry</c> times.</p>
74
75    <marker id="servfail_retry_timeout"/>
76    <p>But before all name servers are tried again, there is a
77    (user configurable) timeout, <c>servfail_retry_timeout</c>.
78    The point of this is to prevent the new query to be handled by
79    a server's servfail cache (a client that is to eager will
80    actually only get what is in the servfail cache).
81    If there is too little time left
82    of the resolver call's timeout to do a retry,
83    the resolver call may return
84    before the call's timeout has expired. </p>
85
86    <p>For queries not using the <c>search</c> list,
87    if the query to all <c>nameservers</c> results in
88    <c>{error,nxdomain}</c> or an empty answer, the same
89    query is tried for <c>alt_nameservers</c>.</p>
90  </section>
91
92  <section>
93    <title>Resolver Types</title>
94    <p>The following data types concern the resolver:</p>
95  </section>
96  <datatypes>
97    <datatype>
98      <name name="res_option"/>
99    </datatype>
100    <datatype>
101      <name name="nameserver"/>
102    </datatype>
103    <datatype>
104      <name name="res_error"/>
105    </datatype>
106  </datatypes>
107
108  <section>
109    <title>DNS Types</title>
110    <p><marker id="dns_types"/>
111      The following data types concern the DNS client:</p>
112  </section>
113
114  <datatypes>
115    <datatype>
116      <name name="dns_name"/>
117      <desc><p>A string with no adjacent dots.</p></desc>
118    </datatype>
119    <datatype>
120      <name name="rr_type"/>
121    </datatype>
122    <datatype>
123      <name name="dns_class"/>
124    </datatype>
125    <datatype>
126      <name name="dns_msg"/>
127      <desc>
128        <p>This is the start of a hiearchy of opaque data structures
129          that can be examined with access functions in <c>inet_dns</c>, which
130          return lists of <c>{Field,Value}</c> tuples. The arity 2 functions
131          only return the value for a specified field.</p>
132        <pre>
133dns_msg() = DnsMsg
134    inet_dns:msg(DnsMsg) ->
135        [ {header, dns_header()}
136        | {qdlist, dns_query()}
137        | {anlist, dns_rr()}
138        | {nslist, dns_rr()}
139        | {arlist, dns_rr()} ]
140    inet_dns:msg(DnsMsg, header) -> dns_header() % for example
141    inet_dns:msg(DnsMsg, Field) -> Value
142
143dns_header() = DnsHeader
144    inet_dns:header(DnsHeader) ->
145        [ {id, integer()}
146        | {qr, boolean()}
147        | {opcode, query | iquery | status | integer()}
148        | {aa, boolean()}
149        | {tc, boolean()}
150        | {rd, boolean()}
151        | {ra, boolean()}
152        | {pr, boolean()}
153        | {rcode, integer(0..16)} ]
154    inet_dns:header(DnsHeader, Field) -> Value
155
156query_type() = axfr | mailb | maila | any | rr_type()
157
158dns_query() = DnsQuery
159    inet_dns:dns_query(DnsQuery) ->
160        [ {domain, dns_name()}
161        | {type, query_type()}
162        | {class, dns_class()} ]
163    inet_dns:dns_query(DnsQuery, Field) -> Value
164
165dns_rr() = DnsRr
166    inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields
167    DnsRrFields = [ {domain, dns_name()}
168                  | {type, rr_type()}
169                  | {class, dns_class()}
170                  | {ttl, integer()}
171                  | {data, dns_data()} ]
172    DnsRrOptFields = [ {domain, dns_name()}
173                     | {type, opt}
174                     | {udp_payload_size, integer()}
175                     | {ext_rcode, integer()}
176                     | {version, integer()}
177                     | {z, integer()}
178                     | {data, dns_data()} ]
179    inet_dns:rr(DnsRr, Field) -> Value</pre>
180        <p>There is an information function for the types above:</p>
181        <pre>
182inet_dns:record_type(dns_msg()) -> msg;
183inet_dns:record_type(dns_header()) -> header;
184inet_dns:record_type(dns_query()) -> dns_query;
185inet_dns:record_type(dns_rr()) -> rr;
186inet_dns:record_type(_) -> undefined.</pre>
187        <p>So, <c>inet_dns:(inet_dns:record_type(X))(X)</c> converts
188          any of these data structures into a <c>{Field,Value}</c> list.</p>
189      </desc>
190    </datatype>
191    <datatype>
192      <name name="dns_data"/>
193      <desc>
194        <p><c><anno>Regexp</anno></c> is a string with characters encoded
195          in the UTF-8 coding standard.</p>
196      </desc>
197    </datatype>
198  </datatypes>
199
200  <funcs>
201    <func>
202      <name name="getbyname" arity="2" since=""/>
203      <name name="getbyname" arity="3" since=""/>
204      <fsummary>Resolve a DNS record of the specified type for the specified
205      host.</fsummary>
206      <desc>
207        <p>Resolves a DNS record of the specified type for the specified host,
208          of class <c>in</c>. Returns, on success, a <c>hostent()</c> record
209          with <c>dns_data()</c> elements in the address list field.</p>
210        <p>This function uses resolver option <c>search</c> that
211          is a list of domain names. If the name to resolve contains
212          no dots, it is prepended to each domain name in the
213          search list, and they are tried in order. If the name
214          contains dots, it is first tried as an absolute name
215          and if that fails, the search list is used. If the name
216          has a trailing dot, it is supposed to be
217          an absolute name and the search list is not used.</p>
218      </desc>
219    </func>
220
221    <func>
222      <name name="gethostbyaddr" arity="1" since=""/>
223      <name name="gethostbyaddr" arity="2" since=""/>
224      <fsummary>Return a hostent record for the host with the specified
225        address.</fsummary>
226      <desc>
227        <p>Backend functions used by
228          <seemfa marker="kernel:inet#gethostbyaddr/1"><c>inet:gethostbyaddr/1</c></seemfa>.
229        </p>
230      </desc>
231    </func>
232
233    <func>
234      <name name="gethostbyname" arity="1" since=""/>
235      <name name="gethostbyname" arity="2" since=""/>
236      <name name="gethostbyname" arity="3" since=""/>
237      <fsummary>Return a hostent record for the host with the specified name.
238      </fsummary>
239      <desc>
240        <p>Backend functions used by
241          <seemfa marker="kernel:inet#gethostbyname/1"><c>inet:gethostbyname/1,2</c></seemfa>.
242        </p>
243        <p>This function uses resolver option <c>search</c> just like
244          <seemfa marker="#getbyname/2"><c>getbyname/2,3</c></seemfa>.
245        </p>
246        <p>If resolver option <c>inet6</c> is <c>true</c>,
247          an IPv6 address is looked up.</p>
248      </desc>
249    </func>
250
251    <func>
252      <name name="lookup" arity="3" since=""/>
253      <name name="lookup" arity="4" since=""/>
254      <name name="lookup" arity="5" since=""/>
255      <fsummary>Resolve the DNS data for the record of the specified type
256        and class for the specified name.</fsummary>
257      <desc>
258        <p>Resolves the DNS data for the record of the specified type and class
259          for the specified name. On success, filters out the answer records
260          with the correct <c><anno>Class</anno></c> and
261          <c><anno>Type</anno></c>, and returns
262          a list of their data fields. So, a lookup for type <c>any</c>
263          gives an empty answer, as the answer records have
264          specific types that are not <c>any</c>. An empty answer
265          or a failed lookup returns an empty list.</p>
266        <p>Calls
267          <seemfa marker="#resolve/3"><c>resolve/*</c></seemfa>
268          with the same arguments and filters the result, so
269          <c><anno>Opts</anno></c> is described for those functions.</p>
270      </desc>
271    </func>
272
273    <func>
274      <name name="resolve" arity="3" since=""/>
275      <name name="resolve" arity="4" since=""/>
276      <name name="resolve" arity="5" since=""/>
277      <fsummary>Resolve a DNS record of the specified type and class
278        for the specified name.</fsummary>
279      <desc>
280        <p>Resolves a DNS record of the specified type and class for the
281          specified name. The returned <c>dns_msg()</c> can be examined using
282          access functions in <c>inet_db</c>, as described in section
283          in <seeerl marker="#dns_types">DNS Types</seeerl>.</p>
284        <p>If <c><anno>Name</anno></c> is an <c>ip_address()</c>, the domain
285          name to query for is generated as the standard reverse
286          <c>".IN-ADDR.ARPA."</c> name for an IPv4 address, or the
287          <c>".IP6.ARPA."</c> name for an IPv6 address.
288          In this case, you most probably want to use
289          <c><anno>Class</anno> = in</c> and <c><anno>Type</anno> = ptr</c>,
290          but it is not done automatically.</p>
291        <p><c><anno>Opts</anno></c> overrides the corresponding resolver
292          options. If option <c>nameservers</c> is specified, it is
293          assumed that it is the complete list of name serves,
294          so resolver option <c>alt_nameserves</c> is ignored.
295          However, if option <c>alt_nameserves</c> is also specified to this
296          function, it is used.</p>
297        <p>Option <c>verbose</c> (or rather <c>{verbose,true}</c>)
298          causes diagnostics printout through
299          <seemfa marker="stdlib:io#format/3"><c>io:format/2</c></seemfa>
300          of queries, replies retransmissions, and so on, similar
301          to from utilities, such as <c>dig</c> and <c>nslookup</c>.</p>
302        <p>If <c><anno>Opt</anno></c> is any atom, it is interpreted
303          as <c>{<anno>Opt</anno>,true}</c> unless the atom string starts with
304          <c>"no"</c>, making the
305          interpretation <c>{<anno>Opt</anno>,false}</c>.
306          For example, <c>usevc</c> is an alias for <c>{usevc,true}</c>
307          and <c>nousevc</c> is an alias for <c>{usevc,false}</c>.</p>
308        <p>Option <c>inet6</c> has no effect on this function. You
309          probably want to use <c><anno>Type</anno> = a | aaaa</c> instead.</p>
310      </desc>
311    </func>
312  </funcs>
313
314  <section>
315    <title>Example</title>
316    <p>This access functions example shows how
317      <seemfa marker="#lookup/3"><c>lookup/3</c></seemfa>
318      can be implemented using
319      <seemfa marker="#resolve/3"><c>resolve/3</c></seemfa>
320      from outside the module:</p>
321    <code type="none">
322example_lookup(Name, Class, Type) ->
323    case inet_res:resolve(Name, Class, Type) of
324        {ok,Msg} ->
325            [inet_dns:rr(RR, data)
326             || RR &lt;- inet_dns:msg(Msg, anlist),
327                 inet_dns:rr(RR, type) =:= Type,
328                 inet_dns:rr(RR, class) =:= Class];
329        {error,_} ->
330            []
331     end.</code>
332  </section>
333
334
335
336  <funcs>
337    <fsdescription>
338      <title>Legacy Functions</title>
339      <p>These are deprecated because the annoying double
340        meaning of the name servers/time-out argument, and
341        because they have no decent place for a resolver options list.</p>
342    </fsdescription>
343    <func>
344      <name name="nslookup" arity="3" since=""/>
345      <name name="nslookup" arity="4" clause_i="1" since=""/>
346      <name name="nslookup" arity="4" clause_i="2" since=""/>
347      <fsummary>Resolve a DNS record of the specified type and class for the
348        specified name.</fsummary>
349      <type variable="Name"/>
350      <type variable="Class"/>
351      <type variable="Type"/>
352      <type variable="Timeout" name_i="2"/>
353      <type variable="Nameservers"/>
354      <type variable="Reason"/>
355      <desc>
356        <p>Resolves a DNS record of the specified type and class for the
357          specified name.</p>
358      </desc>
359    </func>
360
361    <func>
362      <name name="nnslookup" arity="4" since=""/>
363      <name name="nnslookup" arity="5" since=""/>
364      <fsummary>Resolve a DNS record of the specified type and class
365        for the specified name.</fsummary>
366      <desc>
367        <p>Resolves a DNS record of the specified type and class for the
368          specified name.</p>
369      </desc>
370    </func>
371  </funcs>
372</erlref>
373