aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/doc/src/inet_res.xml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/doc/src/inet_res.xml')
-rw-r--r--lib/kernel/doc/src/inet_res.xml482
1 files changed, 482 insertions, 0 deletions
diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml
new file mode 100644
index 0000000000..d8fe23544b
--- /dev/null
+++ b/lib/kernel/doc/src/inet_res.xml
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2009</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>inet_res</title>
+ <prepared>[email protected]</prepared>
+ <docno></docno>
+ <date>2009-09-11</date>
+ <rev>A</rev>
+ </header>
+ <module>inet_res</module>
+ <modulesummary>A Rudimentary DNS Client</modulesummary>
+ <description>
+ <p>Performs DNS name resolving towards recursive name servers</p>
+ <p>See also
+ <seealso marker="erts:inet_cfg">
+ ERTS User's Guide: Inet configuration
+ </seealso> for more
+ information on how to configure an Erlang runtime system for IP
+ communication and how to enable this DNS client by defining
+ <c><![CDATA['dns']]></c> as a lookup method. It then acts
+ as a backend for the resolving functions in
+ <seealso marker="kernel:inet">inet</seealso>.</p>
+ <p>This DNS client can resolve DNS records even if it
+ is not used for normal name resolving in the node.</p>
+ <p>This is not a full-fledged resolver. It is just a
+ DNS client that relies on asking trusted recursive nameservers.</p>
+ </description>
+
+ <section>
+ <title>Name Resolving</title>
+ <p>UDP queries are used unless resolver option
+ <c>usevc</c> is <c>true</c>, which forces TCP queries.
+ If the query is to large for UDP, TCP is used instead.
+ For regular DNS queries 512 bytes is the size limit.
+ When EDNS is enabled (resolver option
+ <c>edns</c> is set to the EDNS version i.e <c>0</c>
+ instead of <c>false</c>), resolver option
+ <c>udp_payload_size</c> sets the limit. If a nameserver
+ replies with the TC bit set (truncation), indicating
+ the answer is incomplete, the query is retried
+ to that nameserver using TCP. The resolver option
+ <c>udp_payload_size</c> also sets the advertised
+ size for the max allowed reply size, if EDNS is
+ enabled, otherwise the nameserver uses the limit
+ 512 byte. If the reply is larger it gets truncated,
+ forcing a TCP re-query.</p>
+ <p>For UDP queries, the resolver options <c>timeout</c>
+ and <c>retry</c> control retransmission.
+ Each nameserver in the <c>nameservers</c> list is
+ tried with a timeout of <c>timeout</c> / <c>retry</c>.
+ Then all nameservers are tried again doubling the
+ timeout, for a total of <c>retry</c> times.</p>
+ <p>For queries that not use the <c>search</c> list,
+ if the query to all <c>nameservers</c> results in
+ <c>{error,nxdomain}</c>or an empty answer, the same
+ query is tried for the <c>alt_nameservers</c>.</p>
+ </section>
+
+
+
+
+ <section>
+ <title>DATA TYPES</title>
+ <p>As defined in the module
+ <seealso marker="kernel:inet">inet</seealso>:</p>
+ <code type="none">
+hostent() = #hostent{}
+posix() = some atom()s
+ip_address() = tuple of integers of arity 4 or 8</code>
+
+ <p>Resolver types:</p>
+ <code type="none">These correspond to resolver options:
+
+res_option() =
+ [ {alt_nameservers, [ nameserver() ]}
+ | {edns, 0 | false} % Use EDNS
+ | {inet6, bool()} % Return IPv6 addresses
+ | {nameservers, [ nameserver() ]} % List of nameservers
+ | {recurse, bool()} % Request server recursion
+ | {retry, integer()} % UDP retries
+ | {timeout, integer()} % UDP query timeout
+ | {udp_payload_size, integer()} % EDNS payload size
+ | {usevc, bool()} ] % Use TCP (Virtual Circuit)
+
+nameserver() = {ip_address(),Port}
+ Port = integer(1..65535)
+
+res_error() =
+ formerr |
+ qfmterror |
+ servfail |
+ nxdomain |
+ notimp |
+ refused |
+ badvers |
+ timeout
+</code>
+
+ <p>DNS types:</p>
+ <marker id="dns_types"/>
+ <code type="none">dns_name() = string() with no adjacent dots
+
+rr_type() = a | aaaa | cname | gid | hinfo | ns | mb | md | mg | mf
+ | minfo | mx | naptr | null | ptr | soa | spf | srv | txt
+ | uid | uinfo | unspec | wks
+
+query_type() = axfr | mailb | maila | any | rr_type()
+
+dns_class() = in | chaos | hs | any
+
+dns_msg() = DnsMsg
+ This is the start of a hiearchy of opaque data structures
+ that can be examined with access functions in inet_dns
+ that return lists of {Field,Value} tuples. The arity 2
+ functions just return the value for a given field.
+
+ inet_dns:msg(DnsMsg) ->
+ [ {header, dns_header()}
+ | {qdlist, dns_query()}
+ | {anlist, dns_rr()}
+ | {nslist, dns_rr()}
+ | {arlist, dns_rr()} ]
+ inet_dns:msg(DnsMsg, header) -> dns_header() % for example
+ inet_dns:msg(DnsMsg, Field) -> Value
+
+dhs_header() = DnsHeader
+ inet_dns:header(DnsHeader) ->
+ [ {id, integer()}
+ | {qr, bool()}
+ | {opcode, 'query' | iquery | status | integer()}
+ | {aa, bool()}
+ | {tc, bool()}
+ | {rd, bool()}
+ | {ra, bool()}
+ | {pr, bool()}
+ | {rcode, integer(0..16)} ]
+ inet_dns:header(DnsHeader, Field) -> Value
+
+dns_query() = DnsQuery
+ inet_dns:dns_query(DnsQuery) ->
+ [ {domain, dns_name()}
+ | {type, query_type()}
+ | {class, dns_class()} ]
+ inet_dns:dns_query(DnsQuery, Field) -> Value
+
+dns_rr() = DnsRr
+ inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields
+ DnsRrFields = [ {domain, dns_name()}
+ | {type, rr_type()}
+ | {class, dns_class()}
+ | {ttl, integer()}
+ | {data, dns_data()} ]
+ DnsRrOptFields = [ {domain, dns_name()}
+ | {type, opt}
+ | {udp_payload_size, integer()}
+ | {ext_rcode, integer()}
+ | {version, integer()}
+ | {z, integer()}
+ | {data, dns_data()} ]
+ inet_dns:rr(DnsRr, Field) -> Value
+
+dns_data() = % for dns_type()
+ [ dns_name() % ns, md, mf, cname, mb, mg, mr, ptr
+ | ip_address(v4) % a
+ | ip_address(v6) % aaaa
+ | {MName,RName,Serial,Refresh,Retry,Expiry,Minimum} % soa
+ | {ip_address(v4),Proto,BitMap} % wks
+ | {CpuString,OsString} % hinfo
+ | {RM,EM} % minfo
+ | {Prio,dns_name()} % mx
+ | {Prio,Weight,Port,dns_name()} % srv
+ | {Order,Preference,Flags,Services,Regexp,dns_name()} % naptr
+ | [ string() ] % txt, spf
+ | binary() ] % null, integer()
+MName, RName = dns_name()
+Serial, Refresh, Retry, Expiry, Minimum = integer(),
+Proto = integer()
+BitMap = binary()
+CpuString, OsString = string()
+RM = EM = dns_name()
+Prio, Weight, Port = integer()
+Order, Preference = integer()
+Flags, Services = string(),
+Regexp = string(utf8)
+
+
+
+There is an info function for the types above:
+
+inet_dns:record_type(dns_msg()) -> msg;
+inet_dns:record_type(dns_header()) -> header;
+inet_dns:record_type(dns_query()) -> dns_query;
+inet_dns:record_type(dns_rr()) -> rr;
+inet_dns:record_type(_) -> undefined.
+
+So; inet_dns:(inet_dns:record_type(X))(X) will convert
+any of these data structures into a {Field,Value} list.</code>
+ </section>
+
+
+
+ <funcs>
+
+ <func>
+ <name>getbyname(Name, Type) -> {ok,hostent()} | {error,Reason}</name>
+ <name>getbyname(Name, Type, Timeout) ->
+ {ok,hostent()} | {error,Reason}
+ </name>
+ <fsummary>Resolve a DNS record of the given type for the given host
+ </fsummary>
+ <type>
+ <v>Name = dns_name()</v>
+ <v>Type = rr_type()</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Resolve a DNS record of the given type for the given host,
+ of class <c>in</c>. On success returns a <c>hostent()</c> record with
+ <c>dns_data()</c> elements in the address list field.
+ </p><p>
+ This function uses the resolver option <c>search</c> that
+ is a list of domain names. If the name to resolve contains
+ no dots, it is prepended to each domain name in the
+ search list, and they are tried in order. If the name
+ contains dots, it is first tried as an absolute name
+ and if that fails the search list is used. If the name
+ has a trailing dot it is simply supposed to be
+ an absolute name and the search list is not used.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>gethostbyaddr(Address) -> {ok,hostent()} | {error,Reason}</name>
+ <name>gethostbyaddr(Address, Timeout) ->
+ {ok,hostent()} | {error,Reason}
+ </name>
+ <fsummary>Return a hostent record for the host with the given address
+ </fsummary>
+ <type>
+ <v>Address = ip_address()</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Backend functions used by
+ <seealso marker="kernel:inet#gethostbyaddr/1">
+ inet:gethostbyaddr/1
+ </seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>gethostbyname(Name) -> {ok,hostent()} | Reason}</name>
+ <name>gethostbyname(Name, Family) ->
+ {ok,hostent()} | {error,Reason}}
+ </name>
+ <name>gethostbyname(Name, Family, Timeout) ->
+ {ok,hostent()} | {error,Reason}
+ </name>
+ <fsummary>Return a hostent record for the host with the given name
+ </fsummary>
+ <type>
+ <v>Name = dns_name()</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Backend functions used by
+ <seealso marker="kernel:inet#gethostbyname/1">
+ inet:gethostbyname/1,2
+ </seealso>.
+ </p><p>
+ This function uses the resolver option <c>search</c> just like
+ <seealso marker="#getbyname/2">getbyname/2,3</seealso>.
+ </p><p>
+ If the resolver option <c>inet6</c> is <c>true</c>,
+ an IPv6 address is looked up, and if that fails
+ the IPv4 address is looked up and returned on
+ IPv6 mapped IPv4 format.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>lookup(Name, Class, Type) -> [ dns_data() ]
+ </name>
+ <name>lookup(Name, Class, Type, Opts) -> [ dns_data() ]
+ </name>
+ <name>lookup(Name, Class, Type, Opts, Timeout) -> [ dns_data() ]
+ </name>
+ <fsummary>Resolve the DNS data for the record of the given type and class
+ for the given name
+ </fsummary>
+ <type>
+ <v>Name = dns_name() | ip_address()</v>
+ <v>Type = rr_type()</v>
+ <v>Opts = res_option() | verbose</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Resolve the DNS data for the record of the given type and class
+ for the given name. On success filters out the answer records
+ with the correct <c>Class</c> and <c>Type</c> and returns
+ a list of their data fields. So a lookup for type <c>any</c>
+ will give an empty answer since the answer records have
+ specific types that are not <c>any</c>. An empty answer
+ as well as a failed lookup returns an empty list.
+ </p><p>
+ Calls <seealso marker="#resolve/3">resolve/2..4</seealso>
+ with the same arguments and filters the result, so
+ <c>Opts</c> is explained there.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>resolve(Name, Class, Type) -> {ok,dns_msg()} | Error
+ </name>
+ <name>resolve(Name, Class, Type, Opts) -> {ok,dns_msg()} | Error
+ </name>
+ <name>resolve(Name, Class, Type, Opts, Timeout) -> {ok,dns_msg()} | Error
+ </name>
+ <fsummary>Resolve a DNS record of the given type and class
+ for the given name
+ </fsummary>
+ <type>
+ <v>Name = dns_name() | ip_address()</v>
+ <v>Type = rr_type()</v>
+ <v>Opts = res_option() | verbose | atom()</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Error = {error,Reason} | {error,{Reason,dns_msg()}}</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Resolve a DNS record of the given type and class for the given name.
+ The returned <c>dns_msg()</c> can be examined using
+ access functions in <c>inet_db</c> as described
+ in <seealso marker="#dns_types">DNS types</seealso>.
+ </p><p>
+ If <c>Name</c> is an <c>ip_address()</c>, the domain name
+ to query for is generated as the standard reverse
+ ".IN-ADDR.ARPA." name for an IPv4 address, or the
+ ".IP6.ARPA." name for an IPv6 address.
+ In this case you most probably want to use
+ <c>Class = in</c> and <c>Type = ptr</c> but it
+ is not done automatically.
+ </p><p>
+ <c>Opts</c> override the corresponding resolver options.
+ If the option <c>nameservers</c> is given, it is
+ also assumed that it is the complete list of nameserves,
+ so the resolver option <c>alt_nameserves</c> is ignored.
+ Of course, if that option is also given to this function,
+ it is used.
+ </p><p>
+ The <c>verbose</c> option (or rather <c>{verbose,true}</c>),
+ causes diagnostics printout through
+ <seealso marker="stdlib:io#format/3">io:format/2</seealso>
+ of queries, replies retransmissions, etc, similar
+ to from utilities like <c>dig</c>, <c>nslookup</c> et.al.
+ </p><p>
+ If <c>Opt</c> is an arbitrary atom it is interpreted
+ as <c>{Opt,true}</c> unless the atom string starts with
+ <c>"no"</c> making the interpretation <c>{Opt,false}</c>.
+ For example: <c>usevc</c> is an alias for <c>{usevc,true}</c>,
+ and <c>nousevc</c> an alias for <c>{usevc,false}</c>.
+ </p><p>
+ The <c>inet6</c> option currently has no effect on this function.
+ You probably want to use <c>Type = a | aaaa</c> instead.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+
+
+ <section>
+ <title>Examples</title>
+ <p>Access functions example: how
+ <seealso marker="#lookup/3">lookup/3</seealso>
+ could have been implemented using
+ <seealso marker="#resolve/3">resolve/3</seealso>
+ from outside the module.
+ </p><code type="none">
+ example_lookup(Name, Class, Type) ->
+ case inet_res:resolve(Name, Class, Type) of
+ {ok,Msg} ->
+ [inet_dns:rr(RR, data)
+ || RR &lt;- inet_dns:msg(Msg, anlist),
+ inet_dns:rr(RR, type) =:= Type,
+ inet_dns:rr(RR, class) =:= Class];
+ {error,_} ->
+ []
+ end.</code>
+ </section>
+
+
+
+ <section>
+ <title>Legacy Functions</title>
+ <p>These have been deprecated due to the annoying double
+ meaning of the nameservers/timeout argument, and
+ because they had no decent place for a resolver options list.</p>
+ </section>
+
+ <funcs>
+
+ <func>
+ <name>nslookup(Name, Class, Type) -> {ok,dns_msg()} | {error,Reason}
+ </name>
+ <name>nslookup(Name, Class, Type, Timeout) ->
+ {ok,dns_msg()} | {error,Reason}
+ </name>
+ <name>nslookup(Name, Class, Type, Nameservers) ->
+ {ok,dns_msg()} | {error,Reason}
+ </name>
+ <fsummary>Resolve a DNS record of the given type and class
+ for the given name
+ </fsummary>
+ <type>
+ <v>Name = dns_name() | ip_address()</v>
+ <v>Type = rr_type()</v>
+ <v>Nameservers = [ nameserver() ]</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Resolve a DNS record of the given type and class for the given name.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>nnslookup(Name, Class, Type, Nameservers) ->
+ {ok,dns_msg()} | {error,posix()}
+ </name>
+ <name>nnslookup(Name, Class, Type, Nameservers, Timeout) ->
+ {ok,dns_msg()} | {error,posix()}
+ </name>
+ <fsummary>Resolve a DNS record of the given type and class
+ for the given name
+ </fsummary>
+ <type>
+ <v>Name = dns_name() | ip_address()</v>
+ <v>Type = rr_type()</v>
+ <v>Nameservers = [ nameserver() ]</v>
+ <v>Timeout = integer() >= 0 | infinity</v>
+ <v>Reason = posix() | res_error()</v>
+ </type>
+ <desc>
+ <p>Resolve a DNS record of the given type and class for the given name.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>