Skip to content

Commit

Permalink
kernel: Add -dist_listen false option
Browse files Browse the repository at this point in the history
This option makes it so that the distribution no longer
listens for incoming connections. This way the node does
not need to occupy a tcp port, but it also cannot be part
of any global groups.
  • Loading branch information
garazdawi authored and sverker committed Mar 19, 2020
1 parent a8cac32 commit 7a7c90b
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 16 deletions.
13 changes: 13 additions & 0 deletions erts/doc/src/alt_dist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,19 @@
</p>
</item>

<tag><marker id="address"/><c>address() -></c><br/>&nbsp;&nbsp;<c>Address</c></tag>
<item>
<p><c>address/0</c> is called in order to get the <c>Address</c> part of the
<seealso marker="#listen"><c>listen/2</c></seealso> function without creating
a listen socket. All fields except <c>address</c> have to be set in the returned
record</p>
<p>Example:</p>
<code type="erl">address() ->
{ok, Host} = inet:gethostname(),
#net_address{ host = Host, protocol = tcp, family = inet6 }.
</code>
</item>

<tag><marker id="accept"/><c>accept(Listen) -></c><br/>&nbsp;&nbsp;<c>AcceptorPid</c></tag>
<item>
<p>
Expand Down
2 changes: 1 addition & 1 deletion lib/crypto/src/crypto.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2517,7 +2517,7 @@ on_load() ->
filename:join([PrivDir, "lib",
erlang:system_info(system_architecture)]),
Candidate =
filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ]),erl_prim_loader),
case Candidate of
[] -> Error1;
_ ->
Expand Down
20 changes: 12 additions & 8 deletions lib/kernel/src/global_group.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1312,16 +1312,20 @@ get_own_nodes() ->
%%% -hidden command line argument
%%%====================================================================================
publish_arg() ->
case init:get_argument(hidden) of
{ok,[[]]} ->
hidden;
{ok,[["true"]]} ->
hidden;
_ ->
normal
case net_kernel:dist_listen() of
false ->
hidden;
_ ->
case init:get_argument(hidden) of
{ok,[[]]} ->
hidden;
{ok,[["true"]]} ->
hidden;
_ ->
normal
end
end.


%%%====================================================================================
%%% Own group publication type and nodes
%%%====================================================================================
Expand Down
10 changes: 9 additions & 1 deletion lib/kernel/src/inet6_tcp_dist.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
%% Handles the connection setup phase with other Erlang nodes.

-export([listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1, is_node_name/1]).
setup/5, close/1, select/1, address/0, is_node_name/1]).

-export([setopts/2, getopts/2]).

Expand All @@ -34,6 +34,14 @@
select(Node) ->
inet_tcp_dist:gen_select(inet6_tcp, Node).

%% ------------------------------------------------------------
%% Get address family
%% address() => #net_address{}
%% ------------------------------------------------------------

address() ->
inet_tcp_dist:gen_address(inet6_tcp).

%% ------------------------------------------------------------
%% Create the listen socket, i.e. the port that this erlang
%% node is accessible through.
Expand Down
16 changes: 13 additions & 3 deletions lib/kernel/src/inet_tcp_dist.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
%% Handles the connection setup phase with other Erlang nodes.

-export([listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1, is_node_name/1]).
setup/5, close/1, select/1, address/0, is_node_name/1]).

%% Optional
-export([setopts/2, getopts/2]).

%% Generalized dist API
-export([gen_listen/2, gen_accept/2, gen_accept_connection/6,
gen_setup/6, gen_select/2]).
gen_setup/6, gen_select/2, gen_address/1]).

%% internal exports

Expand Down Expand Up @@ -63,6 +63,14 @@ gen_select(Driver, Node) ->
_ -> false
end.

%% ------------------------------------------------------------
%% Get the address family that this distribution uses
%% ------------------------------------------------------------
address() ->
gen_address(inet_tcp).
gen_address(Driver) ->
get_tcp_address(Driver).

%% ------------------------------------------------------------
%% Create the listen socket, i.e. the port that this erlang
%% node is accessible through.
Expand Down Expand Up @@ -436,9 +444,11 @@ split_node([], _, Ack) -> [lists:reverse(Ack)].
%% ------------------------------------------------------------
get_tcp_address(Driver, Socket) ->
{ok, Address} = inet:sockname(Socket),
NetAddr = get_tcp_address(Driver),
NetAddr#net_address{ address = Address }.
get_tcp_address(Driver) ->
{ok, Host} = inet:gethostname(),
#net_address {
address = Address,
host = Host,
protocol = tcp,
family = Driver:family()
Expand Down
54 changes: 51 additions & 3 deletions lib/kernel/src/net_kernel.erl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
kernel_apply/3,
longnames/0,
protocol_childspecs/0,
epmd_module/0]).
epmd_module/0,
dist_listen/0]).

-export([disconnect/1, passive_cnct/1]).
-export([hidden_connect_node/1]).
Expand Down Expand Up @@ -693,7 +694,10 @@ terminate(no_network, State) ->
terminate(_Reason, State) ->
lists:foreach(
fun(#listen {listen = Listen,module = Mod}) ->
Mod:close(Listen)
case Listen of
undefined -> ignore;
_ -> Mod:close(Listen)
end
end, State#state.listen),
lists:foreach(
fun(Node) -> ?nodedown(Node, State)
Expand Down Expand Up @@ -1541,6 +1545,18 @@ epmd_module() ->
erl_epmd
end.

%%
%% dist_listen() -> whether the erlang distribution should listen for connections
%%
dist_listen() ->
case init:get_argument(dist_listen) of
{ok,[[DoListen]]} ->
list_to_atom(DoListen) =/= false;
_ ->
true
end.


%%
%% Start all protocols
%%
Expand All @@ -1553,8 +1569,13 @@ start_protos(Name, Node, CleanHalt) ->
start_protos(Name, ["inet_tcp"], Node, CleanHalt)
end.



start_protos(Name, Ps, Node, CleanHalt) ->
case start_protos(Name, Ps, Node, [], CleanHalt) of
case case dist_listen() of
false -> start_protos_no_listen(Name, Ps, Node, [], CleanHalt);
_ -> start_protos(Name, Ps, Node, [], CleanHalt)
end of
[] ->
case CleanHalt of
true -> halt(1);
Expand All @@ -1564,6 +1585,33 @@ start_protos(Name, Ps, Node, CleanHalt) ->
{ok, Ls}
end.

start_protos_no_listen(Name, [Proto | Ps], Node, Ls, CleanHalt) ->
Mod = list_to_atom(Proto ++ "_dist"),
case set_node(Node, create_creation()) of
ok ->
auth:sync_cookie(),
L = #listen {
listen = undefined,
address = Mod:address(),
accept = undefined,
module = Mod },
start_protos_no_listen(Name, Ps, Node, [L|Ls], CleanHalt);
_ ->
S = "invalid node name: " ++ atom_to_list(Node),
proto_error(CleanHalt, Proto, S),
start_protos_no_listen(Name, Ps, Node, Ls, CleanHalt)
end;
start_protos_no_listen(_Name, [], _Node, Ls, _CleanHalt) ->
Ls.

create_creation() ->
try binary:decode_unsigned(crypto:strong_rand_bytes(4)) of
Creation ->
Creation
catch _:_ ->
rand:uniform((1 bsl 32)-1)
end.

start_protos(Name, [Proto | Ps], Node, Ls, CleanHalt) ->
Mod = list_to_atom(Proto ++ "_dist"),
case catch Mod:listen(Name) of
Expand Down

0 comments on commit 7a7c90b

Please sign in to comment.