inet_dns.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 586 行 · 第 1/2 页
ERL
586 行
%% ``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 via the world wide web 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.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(inet_dns).%% Dns record enocde/decode-export([decode/1, encode/1]).-export([decode_header/1, encode_header/1]).-export([number_of_queries/1, number_of_answers/1, number_of_authority/1, number_of_resources/1]).-import(lists, [reverse/1, nthtail/2]).-include("inet_int.hrl").-include("inet_dns.hrl").%% get N bits from X starting at bit B-define(bitf(X, N, B), (((X) bsr (B)) band ((1 bsl (N))-1))).-define(tolower(C), if (C) >= $A, (C) =< $Z -> ((C)-$A)+$a; true -> C end).%%%% Decode a dns buffer.%%decode(Buffer) -> case decode_header(Buffer) of {ok, H, [QD1,QD0,AN1,AN0,NS1,NS0,AR1,AR0 | Ptr0]} -> Qd = ?u16(QD1, QD0), An = ?u16(AN1, AN0), Ns = ?u16(NS1, NS0), Ar = ?u16(AR1, AR0), case decode_sections(Qd, An, Ns, Ar, Buffer, Ptr0) of {ok, {QdList,AnList,NsList,ArList}} -> {ok, #dns_rec { header = H, qdlist = QdList, anlist = AnList, nslist = NsList, arlist = ArList }}; Error -> Error end; Error -> Error end.decode_header([ID1,ID0,F1,F0 | Rest]) -> H = #dns_header { id = ?u16(ID1,ID0), %% Flag byte 0 qr = ?bitf(F1, 1, 7), opcode = ?bitf(F1, 4, 3), aa = ?bitf(F1, 1, 2), tc = ?bitf(F1, 1, 1), rd = ?bitf(F1, 1, 0), %% Flag byte 1 ra = ?bitf(F0, 1, 7), pr = ?bitf(F0, 1, 6), rcode = ?bitf(F0, 4, 0) }, {ok, H, Rest};decode_header(_) -> {error, fmt}.number_of_queries(Packet) when length(Packet) >= 12 -> [_,_,_,_, QD0,QD1 | _] = Packet, ?u16(QD0, QD1).number_of_answers(Packet) when length(Packet) >= 12 -> [_,_,_,_, _,_,AN0,AN1 | _] = Packet, ?u16(AN0, AN1).number_of_authority(Packet) when length(Packet) >= 12 -> [_,_,_,_, _,_,_,_,NS0,NS1 | _] = Packet, ?u16(NS0, NS1).number_of_resources(Packet) when length(Packet) >= 12 -> [_,_,_,_, _,_,_,_,_,_,AR0,AR1 | _] = Packet, ?u16(AR0, AR1).decode_sections(Qd, An, Ns, Ar, Buffer, Ptr0) -> case decode_query_section(Qd, Buffer, Ptr0) of {ok, {QdList, Ptr1}} -> case decode_res_section(An, Buffer, Ptr1) of {ok, {AnList, Ptr2}} -> case decode_res_section(Ns, Buffer, Ptr2) of {ok, {NsList, Ptr3}} -> case decode_res_section(Ar, Buffer, Ptr3) of {ok, {ArList,_Ptr4}} -> {ok, {QdList,AnList,NsList,ArList}}; Error -> Error end; Error -> Error end; Error -> Error end; Error -> Error end.%%%% Decode queries%%decode_query_section(0, _, Ptr0) -> { ok, {[], Ptr0}};decode_query_section(N, Buffer, Ptr0) when N >= 0 -> decode_query_section(N, Buffer, Ptr0, []);decode_query_section(_, _, _) -> {error, fmt}.decode_query_section(0, _, Ptr, Ls) -> { ok, {reverse(Ls), Ptr}};decode_query_section(Count, Buffer, Ptr0, Ls) -> case dn_expand(Ptr0, Buffer) of error -> {error, fmt}; {Name,_} -> case dn_skip(Ptr0) of [T0,T1,C0,C1 | Ptr1] -> decode_query_section( Count-1, Buffer, Ptr1, [ #dns_query { domain = Name, type = decode_type(?i16(T0,T1)), class = decode_class(?i16(C0,C1))} | Ls]); _ -> {error, fmt} end end.%%%% Decode resources%%decode_res_section(0, _, Ptr0) -> { ok, {[], Ptr0}};decode_res_section(N, Buffer, Ptr0) when N >= 0 -> decode_res_section(N, Buffer, Ptr0, []);decode_res_section(_, _, _) -> {error, fmt}. decode_res_section(0, _, Ptr, Ls) -> {ok, {reverse(Ls), Ptr}};decode_res_section(Count, Buffer, Ptr0, Ls) -> case dn_expand(Ptr0, Buffer) of error -> {error, fmt}; {Name,_} -> case dn_skip(Ptr0) of [T1,T0,C1,C0,TTL3,TTL2,TTL1,TTL0,L1,L0 | Ptr1] -> Len = ?i16(L1,L0), case get_data(Len, Ptr1) of error -> {error, fmt}; {Data, Ptr2} -> Type = decode_type(?i16(T1,T0)), Class = decode_class(?i16(C1,C0)), NData = decode_data(Type, Class, Data, Buffer), decode_res_section( Count-1, Buffer, Ptr2, [ #dns_rr { domain = Name, type = Type, class = Class, ttl = ?i32(TTL3,TTL2,TTL1,TTL0), data = NData } | Ls]) end; _ -> {error, fmt} end end.%%%% Encode a user query%%encode(Q) -> H = encode_header(Q#dns_rec.header), Qd = length(Q#dns_rec.qdlist), An = length(Q#dns_rec.anlist), Ns = length(Q#dns_rec.nslist), Ar = length(Q#dns_rec.arlist), B0 = H ++ ?int16(Qd) ++ ?int16(An) ++ ?int16(Ns) ++ ?int16(Ar), {B1,Ptrs0} = encode_query_section(Q#dns_rec.qdlist, [], B0), {B2,Ptrs1} = encode_res_section(Q#dns_rec.anlist, Ptrs0, B1), {B3,Ptrs2} = encode_res_section(Q#dns_rec.nslist, Ptrs1, B2), {B4,_Ptrs3} = encode_res_section(Q#dns_rec.arlist, Ptrs2, B3), {ok, B4}.encode_header(H) -> F1 = (H#dns_header.qr bsl 7) bor (H#dns_header.opcode bsl 3) bor (H#dns_header.aa bsl 2) bor (H#dns_header.tc bsl 1) bor H#dns_header.rd, F0 = (H#dns_header.ra bsl 7) bor (H#dns_header.pr bsl 6) bor H#dns_header.rcode, ?int16(H#dns_header.id) ++ [F1, F0].encode_query_section([Q | Qs], Ptrs, Buffer) -> DName = Q#dns_query.domain, Type = encode_type(Q#dns_query.type), Class = encode_class(Q#dns_query.class), {NBuffer, NPtrs} = dn_compress(DName, Ptrs, Buffer), encode_query_section(Qs, NPtrs, NBuffer ++ ?int16(Type) ++ ?int16(Class));encode_query_section([], Ptrs,Buffer) -> {Buffer, Ptrs}.encode_res_section([R | Rs], Ptrs, Buffer) -> DName = R#dns_rr.domain, Type = encode_type(R#dns_rr.type), Class = encode_class(R#dns_rr.class), {NBuffer, NPtrs} = dn_compress(DName, Ptrs, Buffer), DataPtr = length(NBuffer) + 10, % length(i16, i16, i32, i16) = 10 {Data,_Ptrs1} = encode_data(R#dns_rr.type, R#dns_rr.class, R#dns_rr.data, NPtrs, DataPtr), N = length(Data), encode_res_section(Rs, NPtrs, NBuffer ++ ?int16(Type) ++ ?int16(Class) ++ ?int32(R#dns_rr.ttl) ++ ?int16(N) ++ Data);encode_res_section([], Ptrs, Buffer) -> {Buffer, Ptrs}.%%%% Resource types%%decode_type(Type) -> case Type of ?T_A -> ?S_A; ?T_NS -> ?S_NS; ?T_MD -> ?S_MD; ?T_MF -> ?S_MF; ?T_CNAME -> ?S_CNAME; ?T_SOA -> ?S_SOA; ?T_MB -> ?S_MB; ?T_MG -> ?S_MG; ?T_MR -> ?S_MR; ?T_NULL -> ?S_NULL; ?T_WKS -> ?S_WKS; ?T_PTR -> ?S_PTR; ?T_HINFO -> ?S_HINFO; ?T_MINFO -> ?S_MINFO; ?T_MX -> ?S_MX; ?T_TXT -> ?S_TXT; ?T_AAAA -> ?S_AAAA; ?T_SRV -> ?S_SRV; %% non standard ?T_UINFO -> ?S_UINFO; ?T_UID -> ?S_UID; ?T_GID -> ?S_GID; ?T_UNSPEC -> ?S_UNSPEC; %% Query type values which do not appear in resource records ?T_AXFR -> ?S_AXFR; ?T_MAILB -> ?S_MAILB; ?T_MAILA -> ?S_MAILA; ?T_ANY -> ?S_ANY; _ -> Type %% raw unknown type end.%%%% Resource types%%encode_type(Type) -> case Type of ?S_A -> ?T_A; ?S_NS -> ?T_NS;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?