查看源代码 inet_res (内核 v10.2)
一个基本的 DNS 客户端。
此模块执行向递归名称服务器的 DNS 名称解析。
另请参阅 ERTS 用户指南:Inet 配置,以获取有关如何为 IP 通信配置 Erlang 运行时系统,以及如何通过将 'dns'
定义为查找方法来启用此 DNS 客户端的更多信息。然后,DNS 客户端充当 inet
中解析函数的后端。
即使此 DNS 客户端未用于节点中的常规名称解析,它也可以解析 DNS 记录。
这不是一个功能齐全的解析器,只是一个依赖于询问受信任的递归名称服务器的 DNS 客户端。
名称解析
除非解析器选项 usevc
为 true
(强制使用 TCP 查询),否则使用 UDP 查询。如果查询对于 UDP 来说太大,则会改用 TCP。对于常规 DNS 查询,大小限制为 512 字节。
当启用 EDNS 时(解析器选项 edns
设置为 EDNS 版本,即:0
而不是 false
),解析器选项 udp_payload_size
设置有效负载大小限制。如果名称服务器回复时设置了 TC 位(截断),表示答案不完整,则会使用 TCP 向同一名称服务器重试查询。如果启用了 EDNS,解析器选项 udp_payload_size
还会设置允许的最大回复大小的通告大小,否则名称服务器会使用 512 字节的限制。如果回复较大,则会被截断,从而强制进行 TCP 重新查询。
对于 UDP 查询,解析器选项 timeout
和 retry
控制重传。nameservers
列表中的每个名称服务器都会尝试使用 timeout
/retry
的超时时间。然后,所有名称服务器都会再次尝试,超时时间加倍,总共尝试 retry
次。
但是在再次尝试所有名称服务器之前,有一个(用户可配置的)超时时间 servfail_retry_timeout
。这样做的目的是防止新查询被服务器的 servfail 缓存处理(一个太急切的客户端实际上只会得到 servfail 缓存中的内容)。如果解析器调用的超时时间剩余太少而无法进行重试,则解析器调用可能会在调用超时时间过期之前返回。
对于不使用 search
列表的查询,如果对所有 nameservers
的查询结果为 {error,nxdomain}
或空答案,则会为 alt_nameservers
尝试相同的查询。
解析器类型
以下数据类型与解析器有关
DNS 类型
以下数据类型与 DNS 客户端有关
示例
此访问函数示例显示了如何使用模块外部的 resolve/3
实现 lookup/3
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.
摘要
旧函数
解析 DNS 查询。
类型
-type dns_class() :: in | chaos | hs | any.
-type 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().
DNS 记录数据(内容)
此类型中指定了每个数据元素的基本类型。
-type dns_msg() :: term().
DNS 消息。
这是一个不透明数据结构层次结构的开始,可以使用 inet_dns
中的访问函数检查,这些函数返回 {Field,Value}
元组的列表。arity 2 函数返回指定字段的值。
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 | dns_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, dns_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
上述类型有一个信息函数
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.
因此,inet_dns:(inet_dns:record_type(X))(X)
将任何这些数据结构转换为 {Field,Value}
列表。
-type dns_name() :: string().
一个没有相邻点的字符串。
-type dns_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.
-type hostent() :: inet:hostent() | {hostent, H_name :: inet:hostname(), H_aliases :: [inet:hostname()], H_addrtype :: dns_rr_type(), H_length :: non_neg_integer(), H_addr_list :: [dns_data()]}.
inet:hostent/0
的扩展变体。
允许 dns_rr_type/0
用于 #hostent{}.h_addrtype
字段,以及 [
dns_data/0
]
用于 #hostent{}.h_addr_list
字段。
-type nameserver() :: {inet:ip_address(), Port :: 1..65535}.
-type res_error() :: formerr | qfmterror | servfail | nxdomain | notimp | refused | badvers | timeout.
-type res_option() :: {alt_nameservers, [nameserver()]} | {edns, 0 | false} | {inet6, boolean()} | {nameservers, [nameserver()]} | {recurse, boolean()} | {retry, integer()} | {timeout, integer()} | {udp_payload_size, integer()} | {dnssec_ok, boolean()} | {usevc, boolean()} | {nxdomain_reply, boolean()}.
旧函数
-spec nnslookup(Name, Class, Type, Nameservers) -> {ok, dns_msg()} | {error, Reason} when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Nameservers :: [nameserver()], Reason :: inet:posix().
-spec nnslookup(Name, Class, Type, Nameservers, Timeout) -> {ok, dns_msg()} | {error, Reason} when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Timeout :: timeout(), Nameservers :: [nameserver()], Reason :: inet:posix().
解析 DNS 查询。
与 nslookup/4
类似,但使用参数 Opts = [{nameservers, Nameservers}]
和 Timeout
调用 resolve/5
。
-spec nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason} when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Reason :: inet:posix() | res_error().
-spec nslookup(Name, Class, Type, Timeout) -> {ok, dns_msg()} | {error, Reason} when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Timeout :: timeout(), Reason :: inet:posix() | res_error(); (Name, Class, Type, Nameservers) -> {ok, dns_msg()} | {error, Reason} when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Nameservers :: [nameserver()], Reason :: inet:posix() | res_error().
解析 DNS 查询。
此函数是 resolve/5
的旧包装器,可简化将错误 {error, {Reason, _}}
匹配为 {error, Reason}
或 {error, einval}
。
使用参数 Timeout
调用 resolve/5
,其中 Opts = []
。
使用参数 Nameservers
调用 resolve/5
,其中 Opts = [{nameservers, Nameservers}]
和 Timeout = infinity
。
函数
-spec getbyname(Name, Type) -> {ok, Hostent} | {error, Reason} when Name :: dns_name(), Type :: dns_rr_type(), Hostent :: inet:hostent() | hostent(), Reason :: inet:posix() | res_error().
-spec getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason} when Name :: dns_name(), Type :: dns_rr_type(), Timeout :: timeout(), Hostent :: inet:hostent() | hostent(), Reason :: inet:posix() | res_error().
解析 DNS 查询。
解析指定主机的指定 Type
的 DNS 查询,类为 in
。成功时,解析 Type = a|aaaa
DNS 记录时,返回一个 #hostent{}
记录,其中 #hostent.h_addrtype = inet|inet6
,分别;请参阅 inet:hostent/0
。
当解析其他 Type = dns_rr_type()
:s(类为 in
)时,也会返回一个 #hostent{}
记录,但在 #hostent.h_addrtype
中使用 dns_rr_type/0
,并在 #hostent.h_addr_list
中使用已解析的 dns_data/0
;请参阅 hostent/0
。
此函数使用解析器选项 search
,它是一个域名列表。如果要解析的名称不包含点,则会将其前置到搜索列表中的每个域名,并按顺序尝试。如果名称包含点,则首先将其作为绝对名称尝试,如果失败,则使用搜索列表。如果名称带有尾点,则应将其视为绝对名称,并且不使用搜索列表。
-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, Reason} when Address :: inet:ip_address(), Hostent :: inet:hostent(), Reason :: inet:posix() | res_error().
-spec gethostbyaddr(Address, Timeout) -> {ok, Hostent} | {error, Reason} when Address :: inet:ip_address(), Timeout :: timeout(), Hostent :: inet:hostent(), Reason :: inet:posix() | res_error().
inet:gethostbyaddr/1
使用的后端函数。
-spec gethostbyname(Name) -> {ok, Hostent} | {error, Reason} when Name :: dns_name(), Hostent :: inet:hostent(), Reason :: inet:posix() | res_error().
inet:gethostbyname/1,2
使用的后端函数。
如果解析器选项 inet6
为 true
,则等效于 gethostbyname(Name, inet6, infinity)
,否则等效于 gethostbyname(Name, inet, infinity)
。
-spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason} when Name :: dns_name(), Hostent :: inet:hostent(), Family :: inet:address_family(), Reason :: inet:posix() | res_error().
-spec gethostbyname(Name, Family, Timeout) -> {ok, Hostent} | {error, Reason} when Name :: dns_name(), Hostent :: inet:hostent(), Timeout :: timeout(), Family :: inet:address_family(), Reason :: inet:posix() | res_error().
inet:gethostbyname/1,2
使用的后端函数。
此函数像 getbyname/2,3
一样使用解析器选项 search
。
-spec lookup(Name, Class, Type) -> [dns_data()] when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type().
-spec lookup(Name, Class, Type, Opts) -> [dns_data()] when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Opts :: [res_option() | verbose].
-spec lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()] when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Opts :: [res_option() | verbose], Timeout :: timeout().
查找 DNS 数据。
解析指定 Class
和 Type
的记录 Name
的 DNS 数据。成功时,会筛选出具有正确 Class
和 Type
的应答记录,并返回其数据字段的列表。因此,对 any
类型的查找会返回一个空答案,因为应答记录具有不是 any
的特定类型。空答案或失败的查找会返回一个空列表。
使用相同的参数调用 resolve/*
并筛选结果,因此 Opts
在这些函数中描述。
-spec resolve(Name, Class, Type) -> {ok, dns_msg()} | Error when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Error :: {error, Reason} | {error, {Reason, dns_msg()}}, Reason :: inet:posix() | res_error().
-spec resolve(Name, Class, Type, Opts) -> {ok, dns_msg()} | Error when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Opts :: [Opt], Opt :: res_option() | verbose | atom(), Error :: {error, Reason} | {error, {Reason, dns_msg()}}, Reason :: inet:posix() | res_error().
-spec resolve(Name, Class, Type, Opts, Timeout) -> {ok, dns_msg()} | Error when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type(), Opts :: [Opt], Opt :: res_option() | verbose | atom(), Timeout :: timeout(), Error :: {error, Reason} | {error, {Reason, dns_msg()}}, Reason :: inet:posix() | res_error().
解析 DNS 查询。
将指定 Type
、Class
和 Name
的 DNS 查询解析为可能包含资源记录的 DNS 消息。可以使用 inet_db
中的访问函数来检查返回的 dns_msg/0
,如DNS 类型部分所述。
如果 Name
是 ip_address()
,则要查询的域名将生成为 IPv4 地址的标准反向 ".IN-ADDR.ARPA."
名称,或 IPv6 地址的 ".IP6.ARPA."
名称。在这种情况下,你很可能想使用 Class = in
和 Type = ptr
,但这不是自动完成的。
Opts
会覆盖相应的解析器选项。如果指定了选项 nameservers
,则假定它是完整的名称服务器列表,因此将忽略解析器选项 alt_nameserves
。但是,如果也为此函数指定了选项 alt_nameserves
,则将使用它。
选项 verbose
(或者更确切地说,{verbose,true}
)会导致通过 io:format/2
输出查询、回复、重传等的诊断信息,类似于诸如 dig
和 nslookup
之类的实用程序。
选项 nxdomain_reply
(或者更确切地说,{nxdomain_reply, true}
)会导致来自 DNS 服务器的 NXDOMAIN 错误作为 {error, {nxdomain, dns_msg()}}
返回。dns_msg/0
包含应答服务器包含的附加部分。这主要用于检查 SOA 记录以获取负缓存的 TTL。
如果 Opt
是任何原子,则将其解释为 {Opt,true}
,除非原子字符串以 "no"
开头,否则将其解释为 {Opt,false}
。例如,usevc
是 {usevc, true}
的别名,而 nousevc
是 {usevc, false}
的别名。
选项 inet6
对此函数没有影响。你可能想要使用 Type = a | aaaa
代替。