1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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]).
|