檢視原始碼 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}
元組的列表。參數為 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 查詢。
解析指定主機、類別為 in
的指定 Type
的 DNS 查詢。成功時,在解析 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
,而解析的 dns_data/0
位於 #hostent.h_addr_list
中;請參閱 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
使用的後端函式。
此函式使用解析器選項 search
,就像 getbyname/2,3
一樣。
-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 資料。
解析指定的 Type
和 Class
的記錄 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
。