Current section
Files
Jump to
Current section
Files
src/nat_scan.erl
%%%-------------------------------------------------------------------
%% @private
%% @doc
%% == NAT scan ==
%% @end
%%%-------------------------------------------------------------------
-module(nat_scan).
%% ------------------------------------------------------------------
%% API Function Exports
%% ------------------------------------------------------------------
-export([
start/0
]).
-define(LOG(A, B), io:format("[~p] " ++ A ++ "~n", [?MODULE] ++ B)).
%% ------------------------------------------------------------------
%% API Function Definitions
%% ------------------------------------------------------------------
start() ->
{ok, Default} = inet:gethostname(),
FileName = os:getenv("FILE", Default),
{ok, _} = nat_cache:start([{file, FileName}, {get, false}]),
%% Setup meck mocks for caching
ok = meck:new(hackney, [passthrough, no_link]),
ok = meck:new(gen_udp, [unstick, passthrough, no_link]),
ok = meck:new(inet_ext, [passthrough, no_link]),
setup_caching_mocks(),
_ = natupnp_v1(),
_ = natupnp_v2(),
_ = natpmp(),
_ = natpcp(),
meck:unload([hackney, gen_udp, inet_ext]),
nat_cache:stop().
setup_caching_mocks() ->
%% Hackney caching mock
meck:expect(hackney, request,
fun(Method, Url, Headers, Body, Opts) ->
Key = {hackney, request, [Method, Url]},
case nat_cache:get(Key) of
undefined ->
Result = meck:passthrough([Method, Url, Headers, Body, Opts]),
nat_cache:put(Key, Result),
Result;
Cached ->
Cached
end
end),
%% gen_udp caching mock (for NAT-PMP/PCP)
meck:expect(gen_udp, send,
fun(Socket, Ip, Port, Msg) ->
Key = {gen_udp, send, [Ip, Port, Msg]},
case nat_cache:get(Key) of
undefined ->
meck:passthrough([Socket, Ip, Port, Msg]);
{_Socket, Ip2, Port2, RespMsg} ->
self() ! {udp, Socket, Ip2, Port2, RespMsg},
ok
end
end),
%% inet_ext caching mock
meck:expect(inet_ext, get_internal_address,
fun(Gateway) ->
Key = {inet_ext, get_internal_address, [Gateway]},
case nat_cache:get(Key) of
undefined ->
Result = meck:passthrough([Gateway]),
nat_cache:put(Key, Result),
Result;
Cached ->
Cached
end
end).
natupnp_v1() ->
?LOG("[natupnp_v1] discovering", []),
case natupnp_v1:discover() of
{ok, Context} ->
?LOG("[natupnp_v1] discovered ~p", [Context]),
case natupnp_v1:add_port_mapping(Context, tcp, 8333, 8333, 3600) of
{ok, _Since, _InternalPort, _ExternalPort, _MappingLifetime}=OK ->
?LOG("[natupnp_v1] added port mapping ~p", [OK]),
case natupnp_v1:delete_port_mapping(Context, tcp, 8333, 8333) of
ok ->
?LOG("[natupnp_v1] deleted port mapping", []);
{error, R1} ->
?LOG("[natupnp_v1] failed to delete port mapping ~p", [R1])
end;
{error, R1} ->
?LOG("[natupnp_v1] failed to add port mapping ~p", [R1])
end,
case natupnp_v1:get_external_address(Context) of
{ok, ExtAddress} ->
?LOG("[natupnp_v1] got external address ~p", [ExtAddress]);
{error, R2} ->
?LOG("[natupnp_v1] failed to get external address ~p", [R2])
end,
case natupnp_v1:get_internal_address(Context) of
{ok, IntAddress} ->
?LOG("[natupnp_v1] got internal address ~p", [IntAddress])
end;
{error, _Reason} ->
?LOG("[natupnp_v1] failed to discover ~p", [_Reason])
end.
natupnp_v2() ->
?LOG("[natupnp_v2] discovering", []),
case natupnp_v2:discover() of
{ok, Context} ->
?LOG("[natupnp_v2] discovered ~p", [Context]),
case natupnp_v2:add_port_mapping(Context, tcp, 8333, 8333, 3600) of
{ok, _Since, _InternalPort, _ExternalPort, _MappingLifetime}=OK ->
?LOG("[natupnp_v2] added port mapping ~p", [OK]),
case natupnp_v2:delete_port_mapping(Context, tcp, 8333, 8333) of
ok ->
?LOG("[natupnp_v2] deleted port mapping", []);
{error, R1} ->
?LOG("[natupnp_v2] failed to delete port mapping ~p", [R1])
end;
{error, R1} ->
?LOG("[natupnp_v2] failed to add port mapping ~p", [R1])
end,
case natupnp_v2:get_external_address(Context) of
{ok, ExtAddress} ->
?LOG("[natupnp_v2] got external address ~p", [ExtAddress]);
{error, R2} ->
?LOG("[natupnp_v2] failed to get external address ~p", [R2])
end,
case natupnp_v2:get_internal_address(Context) of
{ok, IntAddress} ->
?LOG("[natupnp_v2] got internal address ~p", [IntAddress])
end;
{error, _Reason} ->
?LOG("[natupnp_v2] failed to discover ~p", [_Reason])
end.
natpmp() ->
?LOG("[natpmp] discovering", []),
case natpmp:discover() of
{ok, Context} ->
?LOG("[natpmp] discovered ~p", [Context]),
case natpmp:add_port_mapping(Context, tcp, 8333, 8333, 3600) of
{ok, _Since, _InternalPort, _ExternalPort, _MappingLifetime}=OK ->
?LOG("[natpmp] added port mapping ~p", [OK]),
case natpmp:delete_port_mapping(Context, tcp, 8333, 8333) of
ok ->
?LOG("[natpmp] deleted port mapping", []);
{error, R1} ->
?LOG("[natpmp] failed to delete port mapping ~p", [R1])
end;
{error, R1} ->
?LOG("[natpmp] failed to add port mapping ~p", [R1])
end,
case natpmp:get_external_address(Context) of
{ok, ExtAddress} ->
?LOG("[natpmp] got external address ~p", [ExtAddress]);
{error, R2} ->
?LOG("[natpmp] failed to get external address ~p", [R2])
end,
case natpmp:get_internal_address(Context) of
{ok, IntAddress} ->
?LOG("[natpmp] got internal address ~p", [IntAddress])
end;
{error, no_nat} ->
?LOG("[natpmp] failed to discover not nat", [])
end.
natpcp() ->
?LOG("[natpcp] discovering", []),
case natpcp:discover() of
{ok, Context} ->
?LOG("[natpcp] discovered ~p", [Context]),
case natpcp:add_port_mapping(Context, tcp, 8333, 8333, 3600) of
{ok, _Since, _InternalPort, _ExternalPort, _MappingLifetime}=OK ->
?LOG("[natpcp] added port mapping ~p", [OK]),
case natpcp:delete_port_mapping(Context, tcp, 8333, 8333) of
ok ->
?LOG("[natpcp] deleted port mapping", []);
{error, R1} ->
?LOG("[natpcp] failed to delete port mapping ~p", [R1])
end;
{error, R1} ->
?LOG("[natpcp] failed to add port mapping ~p", [R1])
end,
case natpcp:get_external_address(Context) of
{ok, ExtAddress} ->
?LOG("[natpcp] got external address ~p", [ExtAddress]);
{error, R2} ->
?LOG("[natpcp] failed to get external address ~p", [R2])
end,
case natpcp:get_internal_address(Context) of
{ok, IntAddress} ->
?LOG("[natpcp] got internal address ~p", [IntAddress])
end;
{error, no_nat} ->
?LOG("[natpcp] failed to discover no nat", [])
end.