Skip to content

Commit

Permalink
icmp6: add functions to generate ICMPv6 filters
Browse files Browse the repository at this point in the history
  • Loading branch information
msantos committed May 21, 2013
1 parent a521c18 commit a5723f6
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
71 changes: 70 additions & 1 deletion src/gen_icmp.erl
Expand Up @@ -46,7 +46,14 @@
family/1,
getfd/1,
set_ttl/3,
get_ttl/2
get_ttl/2,

icmp6_filter_setpassall/0, icmp6_filter_setpassall/1,
icmp6_filter_setblockall/0, icmp6_filter_setblockall/1,
icmp6_filter_setpass/2,
icmp6_filter_setblock/2,
icmp6_filter_willpass/2,
icmp6_filter_willblock/2
]).
-export([recv/2, recv/3]).
-export([ping/1, ping/2, ping/3]).
Expand Down Expand Up @@ -617,6 +624,68 @@ ipv6_unicast_hops() ->
{unix, _} -> 4
end.

% IPv6 ICMP filtering
icmp6_filter_setpassall(<<_:256>>) ->
icmp6_filter_setpassall().

icmp6_filter_setpassall() ->
<<16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff,
16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff,
16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff,
16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff, 16#ff>>.

icmp6_filter_setblockall(<<_:256>>) ->
icmp6_filter_setblockall().

icmp6_filter_setblockall() ->
<<0:256>>.

%#define ICMP6_FILTER_SETPASS(type, filterp) \
% (((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
icmp6_filter_setpass(Type0, <<_:256>> = Filter) ->
Type = icmp6_message:type_to_uint8(Type0),
Offset = Type bsr 5,
Value = 1 bsl (Type band 31),
Fun = fun(N) -> N bor Value end,
array_set(Offset, Fun, Filter).


%#define ICMP6_FILTER_SETBLOCK(type, filterp) \
% (((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
icmp6_filter_setblock(Type0, <<_:256>> = Filter) ->
Type = icmp6_message:type_to_uint8(Type0),
Offset = Type bsr 5,
Value = 1 bsl (Type band 31),
Fun = fun(N) -> N band bnot Value end,
array_set(Offset, Fun, Filter).

%#define ICMP6_FILTER_WILLPASS(type, filterp) \
% ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
icmp6_filter_willpass(Type0, <<_:256>> = Filter) ->
Type = icmp6_message:type_to_uint8(Type0),
Offset = Type bsr 5,
Value = 1 bsl (Type band 31),
array_get(Offset, Filter) band Value =/= 0.

%#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
% ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
icmp6_filter_willblock(Type0, <<_:256>> = Filter) ->
Type = icmp6_message:type_to_uint8(Type0),
Offset = Type bsr 5,
Value = 1 bsl (Type band 31),
array_get(Offset, Filter) band Value =:= 0.

% Offset starts at 0
array_set(Offset, Fun, Bin) ->
Array = array:from_list([ N || <<N:4/native-unsigned-integer-unit:8>> <= Bin ]),
Value = Fun(array:get(Offset, Array)),
<< <<N:4/native-unsigned-integer-unit:8>> ||
N <- array:to_list(array:set(Offset, Value, Array))>>.

array_get(Offset, Bin) ->
Array = array:from_list([ N || <<N:4/native-unsigned-integer-unit:8>> <= Bin ]),
array:get(Offset, Array).

flush_events(Ref) ->
receive
{icmp, Ref, _Addr, _TTL, _Data} ->
Expand Down
11 changes: 11 additions & 0 deletions test/gen_icmp_tests.erl
Expand Up @@ -115,3 +115,14 @@ ipv6_set_ttl_test() ->
{_,_,_,_,_,_,_,_},
{_,_,_,_},
_}] = gen_icmp:ping("www.google.com", [inet6, {ttl,1}]).

% ICMPv6 filter tests
ipv6_filter_gen_test() ->
Filter = gen_icmp:icmp6_filter_setblockall(),

Filter1 = <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0>>,
Filter1 = gen_icmp:icmp6_filter_setpass(echo_request, Filter),
Filter1 = gen_icmp:icmp6_filter_setpass(echo_request, Filter1),

Filter = gen_icmp:icmp6_filter_setblock(echo_request, Filter1).

0 comments on commit a5723f6

Please sign in to comment.