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 + -
显示快捷键?