diff options
Diffstat (limited to 'lib/kernel/doc/src/inet_res.xml')
-rw-r--r-- | lib/kernel/doc/src/inet_res.xml | 482 |
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 <- 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> |