Go to main content

man pages section 3: Extended Library Functions, Volume 1

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

inet_res (3erl)

Name

inet_res - A rudimentary DNS client.

Synopsis

Please see following description for synopsis

Description

inet_res(3)                Erlang Module Definition                inet_res(3)



NAME
       inet_res - A rudimentary DNS client.

DESCRIPTION
       This module performs DNS name resolving to recursive name servers.

       See  also  ERTS  User's  Guide: Inet Configuration for more information
       about how to configure an Erlang runtime system for  IP  communication,
       and how to enable this DNS client by defining 'dns' as a lookup method.
       The DNS client then acts as a backend for the  resolving  functions  in
       inet.

       This DNS client can resolve DNS records even if it is not used for nor-
       mal name resolving in the node.

       This is not a full-fledged resolver, only a DNS client that  relies  on
       asking trusted recursive name servers.

NAME RESOLVING
       UDP queries are used unless resolver option usevc is true, which forces
       TCP queries. If the query is too large for UDP, TCP  is  used  instead.
       For regular DNS queries, 512 bytes is the size limit.

       When  EDNS  is enabled (resolver option edns is set to the EDNS version
       (that is, 0 instead of false), resolver  option  udp_payload_size  sets
       the  limit.  If a name server replies with the TC bit set (truncation),
       indicating that the answer is incomplete, the query is retried to  that
       name  server  using TCP. Resolver option udp_payload_size also sets the
       advertised size for the maximum allowed reply size, if EDNS is enabled,
       otherwise  the  name  server  uses the limit 512 bytes. If the reply is
       larger, it gets truncated, forcing a TCP requery.

       For UDP queries, resolver options timeout and retry control retransmis-
       sion. Each name server in the nameservers list is tried with a time-out
       of timeout/retry. Then all name servers are tried again,  doubling  the
       time-out, for a total of retry times.

       But  before  all name servers are tried again, there is a (user config-
       urable) timeout, servfail_retry_timeout. The point of this is  to  pre-
       vent the new query to be handled by a server's servfail cache (a client
       that is to eager will actually only get what is in the servfail cache).
       If there is too little time left of the resolver call's timeout to do a
       retry, the resolver call may  return  before  the  call's  timeout  has
       expired.

       For  queries not using the search list, if the query to all nameservers
       results in {error,nxdomain} or an empty answer, the same query is tried
       for alt_nameservers.

RESOLVER TYPES
       The following data types concern the resolver:

DATA TYPES
       res_option() =
           {alt_nameservers, [nameserver()]} |
           {edns, 0 | false} |
           {inet6, boolean()} |
           {nameservers, [nameserver()]} |
           {recurse, boolean()} |
           {retry, integer()} |
           {timeout, integer()} |
           {udp_payload_size, integer()} |
           {usevc, boolean()} |
           {nxdomain_reply, boolean()}

       nameserver() = {inet:ip_address(), Port :: 1..65535}

       res_error() =
           formerr | qfmterror | servfail | nxdomain | notimp | refused |
           badvers | timeout

DNS TYPES
       The following data types concern the DNS client:

DATA TYPES
       dns_name() = string()

              A string with no adjacent dots.

       rr_type() =
           a | aaaa | caa | cname | gid | hinfo | ns | mb | md | mg |
           mf | minfo | mx | naptr | null | ptr | soa | spf | srv | txt |
           uid | uinfo | unspec | uri | wks

       dns_class() = in | chaos | hs | any

       dns_msg() = term()

              This  is  the start of a hiearchy of opaque data structures that
              can be examined with access functions in inet_dns, which  return
              lists of {Field,Value} tuples. The arity 2 functions only return
              the value for a specified field.

              dns_msg() = DnsMsg
                  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

              dns_header() = DnsHeader
                  inet_dns:header(DnsHeader) ->
                      [ {id, integer()}
                      | {qr, boolean()}
                      | {opcode, query | iquery | status | integer()}
                      | {aa, boolean()}
                      | {tc, boolean()}
                      | {rd, boolean()}
                      | {ra, boolean()}
                      | {pr, boolean()}
                      | {rcode, integer(0..16)} ]
                  inet_dns:header(DnsHeader, Field) -> Value

              query_type() = axfr | mailb | maila | any | rr_type()

              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

              There is an information 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) converts any of  these
              data structures into a {Field,Value} list.

       dns_data() =
           dns_name() |
           inet:ip4_address() |
           inet:ip6_address() |
           {MName :: dns_name(),
            RName :: dns_name(),
            Serial :: integer(),
            Refresh :: integer(),
            Retry :: integer(),
            Expiry :: integer(),
            Minimum :: integer()} |
           {inet:ip4_address(), Proto :: integer(), BitMap :: binary()} |
           {CpuString :: string(), OsString :: string()} |
           {RM :: dns_name(), EM :: dns_name()} |
           {Prio :: integer(), dns_name()} |
           {Prio :: integer(),
            Weight :: integer(),
            Port :: integer(),
            dns_name()} |
           {Order :: integer(),
            Preference :: integer(),
            Flags :: string(),
            Services :: string(),
            Regexp :: string(),
            dns_name()} |
           [string()] |
           binary()

              Regexp  is  a string with characters encoded in the UTF-8 coding
              standard.

EXPORTS
       getbyname(Name, Type) -> {ok, Hostent} | {error, Reason}

       getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason}

              Types:

                 Name = dns_name()
                 Type = rr_type()
                 Timeout = timeout()
                 Hostent = inet:hostent()
                 Reason = inet:posix() | res_error()

              Resolves a DNS record of the specified type  for  the  specified
              host,  of class in. Returns, on success, a hostent() record with
              dns_data() elements in the address list field.

              This function uses resolver option search  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 supposed to be an absolute
              name and the search list is not used.

       gethostbyaddr(Address) -> {ok, Hostent} | {error, Reason}

       gethostbyaddr(Address, Timeout) -> {ok, Hostent} | {error, Reason}

              Types:

                 Address = inet:ip_address()
                 Timeout = timeout()
                 Hostent = inet:hostent()
                 Reason = inet:posix() | res_error()

              Backend functions used by inet:gethostbyaddr/1.

       gethostbyname(Name) -> {ok, Hostent} | {error, Reason}

       gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason}

       gethostbyname(Name, Family, Timeout) ->
                        {ok, Hostent} | {error, Reason}

              Types:

                 Name = dns_name()
                 Hostent = inet:hostent()
                 Timeout = timeout()
                 Family = inet:address_family()
                 Reason = inet:posix() | res_error()

              Backend functions used by inet:gethostbyname/1,2.

              This function uses  resolver  option  search  just  like  getby-
              name/2,3.

              If resolver option inet6 is true, an IPv6 address is looked up.

       lookup(Name, Class, Type) -> [dns_data()]

       lookup(Name, Class, Type, Opts) -> [dns_data()]

       lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()]

              Types:

                 Name = dns_name() | inet:ip_address()
                 Class = dns_class()
                 Type = rr_type()
                 Opts = [res_option() | verbose]
                 Timeout = timeout()

              Resolves  the  DNS data for the record of the specified type and
              class for the specified name. On success, filters out the answer
              records  with  the correct Class and Type, and returns a list of
              their data fields. So, a lookup for  type  any  gives  an  empty
              answer,  as  the answer records have specific types that are not
              any. An empty answer or a failed lookup returns an empty list.

              Calls resolve/* with the same arguments and filters the  result,
              so Opts is described for those functions.

       resolve(Name, Class, Type) -> {ok, dns_msg()} | Error

       resolve(Name, Class, Type, Opts) -> {ok, dns_msg()} | Error

       resolve(Name, Class, Type, Opts, Timeout) ->
                  {ok, dns_msg()} | Error

              Types:

                 Name = dns_name() | inet:ip_address()
                 Class = dns_class()
                 Type = rr_type()
                 Opts = [Opt]
                 Opt = res_option() | verbose | atom()
                 Timeout = timeout()
                 Error = {error, Reason} | {error, {Reason, dns_msg()}}
                 Reason = inet:posix() | res_error()

              Resolves  a  DNS  record of the specified type and class for the
              specified name. The returned dns_msg()  can  be  examined  using
              access  functions  in  inet_db,  as  described in section in DNS
              Types.

              If Name is an ip_address(), the domain name to query for is gen-
              erated 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 Class = in and Type = ptr,
              but it is not done automatically.

              Opts overrides the corresponding  resolver  options.  If  option
              nameservers  is specified, it is assumed that it is the complete
              list of  name  serves,  so  resolver  option  alt_nameserves  is
              ignored.  However, if option alt_nameserves is also specified to
              this function, it is used.

              Option verbose (or  rather  {verbose,true})  causes  diagnostics
              printout  through  io:format/2  of  queries, replies retransmis-
              sions, and so on, similar to from utilities,  such  as  dig  and
              nslookup.

              Option  nxdomain_reply  (or rather {nxdomain_reply,true}) causes
              nxdomain errors from DNS  servers  to  be  returned  as  {error,
              {nxdomain,  dns_msg()}}.  dns_msg() contains the additional sec-
              tions that where included  by  the  answering  server.  This  is
              mainly useful to inspect the SOA record to get the TTL for nega-
              tive caching.

              If Opt is any atom, it is interpreted as {Opt,true}  unless  the
              atom   string   starts  with  "no",  making  the  interpretation
              {Opt,false}. For example, usevc is an alias for {usevc,true} and
              nousevc is an alias for {usevc,false}.

              Option  inet6  has no effect on this function. You probably want
              to use Type = a | aaaa instead.

EXAMPLE
       This access functions example shows how  lookup/3  can  be  implemented
       using resolve/3 from outside the module:

       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.

LEGACY FUNCTIONS
       These  are  deprecated  because the annoying double meaning of the name
       servers/time-out argument, and because they have no decent place for  a
       resolver options list.

EXPORTS
       nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason}

       nslookup(Name, Class, Type, Timeout) ->
                   {ok, dns_msg()} | {error, Reason}

       nslookup(Name, Class, Type, Nameservers) ->
                   {ok, dns_msg()} | {error, Reason}

              Types:

                 Name = dns_name() | inet:ip_address()
                 Class = dns_class()
                 Type = rr_type()
                 Timeout = timeout()
                 Nameservers = [nameserver()]
                 Reason = inet:posix() | res_error()

              Resolves  a  DNS  record of the specified type and class for the
              specified name.

       nnslookup(Name, Class, Type, Nameservers) ->
                    {ok, dns_msg()} | {error, Reason}

       nnslookup(Name, Class, Type, Nameservers, Timeout) ->
                    {ok, dns_msg()} | {error, Reason}

              Types:

                 Name = dns_name() | inet:ip_address()
                 Class = dns_class()
                 Type = rr_type()
                 Timeout = timeout()
                 Nameservers = [nameserver()]
                 Reason = inet:posix()

              Resolves a DNS record of the specified type and  class  for  the
              specified name.



Ericsson AB                       kernel 8.2                       inet_res(3)