diff options
Diffstat (limited to 'src/dns.erl')
-rw-r--r-- | src/dns.erl | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/dns.erl b/src/dns.erl new file mode 100644 index 0000000..24fb8fb --- /dev/null +++ b/src/dns.erl @@ -0,0 +1,69 @@ +%%% Copyright (c) 2016, NORDUnet A/S. +%%% See LICENSE for licensing information. + +-module(dns). +-export([split_rrset/1, encode_rr/1, encode_rrset/1]). + +decode_name_label(Name) -> + <<Len:8/integer, Label:Len/binary, Rest/binary>> = Name, + {Label, Rest}. + +encode_name_label(Label) -> + Len = byte_size(Label), + <<Len:8/integer, Label/binary>>. + +decode_name(RR) -> + decode_name(RR, []). +decode_name(<<0, Rest/binary>>, Acc) -> + {lists:reverse(Acc), Rest}; +decode_name(Name, Acc) -> + {Label, Rest} = decode_name_label(Name), + decode_name(Rest, [Label | Acc]). + +-spec encode_name(list()) -> binary(). +encode_name(Name) -> + encode_name(Name, []). +encode_name([], Acc) -> + Bin = list_to_binary(lists:reverse(Acc)), + <<Bin/binary, 0>>; +encode_name([H|T], Acc) -> + encode_name(T, [encode_name_label(H) | Acc]). + +-spec decode_rr(binary()) -> {list(), binary()}. +decode_rr(RR) -> + {Name, RestRR} = decode_name(RR), + <<Type:2/binary, + Class:2/binary, + TTL:4/integer-unit:8, + RDLength:2/integer-unit:8, + RDATA:RDLength/binary, + Rest/binary>> = RestRR, + {[Name, Type, Class, TTL, RDATA], Rest}. + +-spec split_rrset(binary()) -> list(). +split_rrset(RRSet) -> + split_rrset(RRSet, []). +split_rrset(<<>>, Acc) -> + lists:reverse(Acc); +split_rrset(RRSet, Acc) -> + {RR, Rest} = decode_rr(RRSet), + split_rrset(Rest, [RR | Acc]). + +-spec encode_rr(list()) -> binary(). +encode_rr([Name, Type, Class, TTL, RDATA]) -> + EncodedName = encode_name(Name), + RDLength = byte_size(RDATA), + <<EncodedName/binary, + Type:2/binary, + Class:2/binary, + TTL:4/integer-unit:8, + RDLength:2/integer-unit:8, + RDATA/binary>>. + +-spec encode_rrset(list()) -> binary(). +encode_rrset(RRSet) -> + encode_rrset(RRSet, []). +encode_rrset([], Acc) -> + list_to_binary(lists:reverse(Acc)); +encode_rrset([H|T], Acc) -> + encode_rrset(T, [encode_rr(H) | Acc]). |