aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/erl.xml18
-rw-r--r--erts/doc/src/init.xml5
-rw-r--r--erts/emulator/test/distribution_SUITE.erl69
-rw-r--r--erts/etc/common/erlexec.c21
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl6
-rw-r--r--lib/kernel/src/net_adm.erl3
-rw-r--r--lib/ssl/src/inet_tls_dist.erl3
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl3
8 files changed, 119 insertions, 9 deletions
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 1bbde7f1e0..e63928ddb0 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -338,7 +338,8 @@
<seealso marker="kernel:net_kernel">net_kernel(3)</seealso>.
It is also ensured that <c><![CDATA[epmd]]></c> runs on the current host
before Erlang is started. See
- <seealso marker="epmd">epmd(1)</seealso>.</p>
+ <seealso marker="epmd">epmd(1)</seealso> and the
+ <seealso marker="#start_epmd"><c>-start_epmd</c></seealso> option.</p>
<p>The name of the node will be <c><![CDATA[Name@Host]]></c>, where
<c><![CDATA[Host]]></c> is the fully qualified host name of the current
host. For short names, use the <c><![CDATA[-sname]]></c> flag instead.</p>
@@ -463,6 +464,21 @@
flag and those running with the <c><![CDATA[-name]]></c> flag, as node
names must be unique in distributed Erlang systems.</p>
</item>
+ <tag><marker id="start_epmd"/><c>-start_epmd true | false</c></tag>
+ <item>
+
+ <p>Specifies whether Erlang should start
+ <seealso marker="epmd">epmd</seealso> on startup. By default
+ this is <c>true</c>, but if you prefer to start epmd
+ manually, set this to <c>false</c>.</p>
+
+ <p>This only applies if Erlang is started as a distributed node,
+ i.e. if <c>-name</c> or <c>-sname</c> is specified. Otherwise,
+ epmd is not started even if <c>-start_epmd true</c> is given.</p>
+
+ <p>Note that a distributed node will fail to start if epmd is
+ not running.</p>
+ </item>
<tag><marker id="smp"/><c><![CDATA[-smp [enable|auto|disable]]]></c></tag>
<item>
<p><c>-smp enable</c> and <c>-smp</c> starts the Erlang runtime
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml
index 84a5aea335..878a33c9ca 100644
--- a/erts/doc/src/init.xml
+++ b/erts/doc/src/init.xml
@@ -241,6 +241,11 @@
marker="kernel:code">code(3)</seealso>.</p>
</item>
+ <tag><c>-epmd_module Module</c></tag>
+ <item>
+ <p>Specifies the module to use for registration and lookup of
+ node names. Defaults to <c>erl_epmd</c>.</p>
+ </item>
<tag><c>-eval Expr</c></tag>
<item>
<p>Scans, parses and evaluates an arbitrary expression
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index d0096fb1bc..26780f6017 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -55,7 +55,8 @@
bad_dist_ext_receive/1,
bad_dist_ext_process_info/1,
bad_dist_ext_control/1,
- bad_dist_ext_connection_id/1]).
+ bad_dist_ext_connection_id/1,
+ start_epmd_false/1, epmd_module/1]).
%% Internal exports.
-export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0,
@@ -64,6 +65,9 @@
dist_evil_parallel_receiver/0,
sendersender/4, sendersender2/4]).
+%% epmd_module exports
+-export([start_link/0, register_node/2, port_please/2]).
+
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {minutes, 4}}].
@@ -76,7 +80,8 @@ all() ->
{group, trap_bif}, {group, dist_auto_connect},
dist_parallel_send, atom_roundtrip, unicode_atom_roundtrip, atom_roundtrip_r15b,
contended_atom_cache_entry, contended_unicode_atom_cache_entry,
- bad_dist_structure, {group, bad_dist_ext}].
+ bad_dist_structure, {group, bad_dist_ext},
+ start_epmd_false, epmd_module].
groups() ->
[{bulk_send, [], [bulk_send_small, bulk_send_big, bulk_send_bigbig]},
@@ -1881,6 +1886,66 @@ dmsg_ext(Term) ->
dmsg_bad_atom_cache_ref() ->
[$R, 137].
+start_epmd_false(Config) when is_list(Config) ->
+ %% Start a node with the option -start_epmd false.
+ {ok, OtherNode} = start_node(start_epmd_false, "-start_epmd false"),
+ %% We should be able to ping it, as epmd was started by us:
+ pong = net_adm:ping(OtherNode),
+ stop_node(OtherNode),
+
+ ok.
+
+epmd_module(Config) when is_list(Config) ->
+ %% We need a relay node to test this, since the test node uses the
+ %% standard epmd module.
+ Sock1 = start_relay_node(epmd_module_node1, "-epmd_module " ++ ?MODULE_STRING),
+ Node1 = inet_rpc_nodename(Sock1),
+ %% Ask what port it's listening on - it won't have registered with
+ %% epmd.
+ {ok, {ok, Port1}} = do_inet_rpc(Sock1, application, get_env, [kernel, dist_listen_port]),
+
+ %% Start a second node, passing the port number as a secret
+ %% argument.
+ Sock2 = start_relay_node(epmd_module_node2, "-epmd_module " ++ ?MODULE_STRING
+ ++ " -other_node_port " ++ integer_to_list(Port1)),
+ Node2 = inet_rpc_nodename(Sock2),
+ %% Node 1 can't ping node 2
+ {ok, pang} = do_inet_rpc(Sock1, net_adm, ping, [Node2]),
+ {ok, []} = do_inet_rpc(Sock1, erlang, nodes, []),
+ {ok, []} = do_inet_rpc(Sock2, erlang, nodes, []),
+ %% But node 2 can ping node 1
+ {ok, pong} = do_inet_rpc(Sock2, net_adm, ping, [Node1]),
+ {ok, [Node2]} = do_inet_rpc(Sock1, erlang, nodes, []),
+ {ok, [Node1]} = do_inet_rpc(Sock2, erlang, nodes, []),
+
+ stop_relay_node(Sock2),
+ stop_relay_node(Sock1).
+
+%% epmd_module functions:
+
+start_link() ->
+ ignore.
+
+register_node(_Name, Port) ->
+ %% Save the port number we're listening on.
+ application:set_env(kernel, dist_listen_port, Port),
+ Creation = rand:uniform(3),
+ {ok, Creation}.
+
+port_please(_Name, _Ip) ->
+ case init:get_argument(other_node_port) of
+ error ->
+ %% None specified. Default to 42.
+ Port = 42,
+ Version = 5,
+ {port, Port, Version};
+ {ok, [[PortS]]} ->
+ %% Port number given on command line.
+ Port = list_to_integer(PortS),
+ Version = 5,
+ {port, Port, Version}
+ end.
+
%%% Utilities
timestamp() ->
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 42da05b1f7..2b2e0e480a 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -195,6 +195,7 @@ static char *plusz_val_switches[] = {
#endif
void usage(const char *switchname);
+static void usage_format(char *format, ...);
void start_epmd(char *epmd);
void error(char* format, ...);
@@ -795,6 +796,24 @@ int main(int argc, char **argv)
get_start_erl_data((char *) NULL);
}
#endif
+ else if (strcmp(argv[i], "-start_epmd") == 0) {
+ if (i+1 >= argc)
+ usage("-start_epmd");
+
+ if (strcmp(argv[i+1], "true") == 0) {
+ /* The default */
+ no_epmd = 0;
+ }
+ else if (strcmp(argv[i+1], "false") == 0) {
+ no_epmd = 1;
+ }
+ else
+ usage_format("Expected boolean argument for \'-start_epmd\'.\n");
+
+ add_arg(argv[i]);
+ add_arg(argv[i+1]);
+ i++;
+ }
else
add_arg(argv[i]);
@@ -1173,7 +1192,7 @@ usage_aux(void)
"]"
#endif
"] "
- "[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] "
+ "[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] [-start_epmd BOOLEAN] "
"[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c [BOOLEAN]] "
"[+C MODE] [+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
"[+l] [+M<SUBSWITCH> <ARGUMENT>] [+P MAX_PROCS] [+Q MAX_PORTS] "
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index 64b28bb49b..f91d7ef7c3 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -73,7 +73,8 @@ gen_listen(Driver, Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Driver, Socket),
{_,Port} = TcpAddress#net_address.address,
- case erl_epmd:register_node(Name, Port) of
+ ErlEpmd = net_kernel:epmd_module(),
+ case ErlEpmd:register_node(Name, Port) of
{ok, Creation} ->
{ok, {Socket, TcpAddress, Creation}};
Error ->
@@ -280,7 +281,8 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
case inet:getaddr(Address, AddressFamily) of
{ok, Ip} ->
Timer = dist_util:start_timer(SetupTime),
- case erl_epmd:port_please(Name, Ip) of
+ ErlEpmd = net_kernel:epmd_module(),
+ case ErlEpmd:port_please(Name, Ip) of
{port, TcpPort, Version} ->
?trace("port_please(~p) -> version ~p~n",
[Node,Version]),
diff --git a/lib/kernel/src/net_adm.erl b/lib/kernel/src/net_adm.erl
index a38356c224..8ec275b88b 100644
--- a/lib/kernel/src/net_adm.erl
+++ b/lib/kernel/src/net_adm.erl
@@ -96,7 +96,8 @@ names() ->
Reason :: address | file:posix().
names(Hostname) ->
- erl_epmd:names(Hostname).
+ ErlEpmd = net_kernel:epmd_module(),
+ ErlEpmd:names(Hostname).
-spec dns_hostname(Host) -> {ok, Name} | {error, Host} when
Host :: atom() | string(),
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 3481e89af0..0da4b3587f 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -87,7 +87,8 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
case inet:getaddr(Address, Driver:family()) of
{ok, Ip} ->
Timer = dist_util:start_timer(SetupTime),
- case erl_epmd:port_please(Name, Ip) of
+ ErlEpmd = net_kernel:epmd_module(),
+ case ErlEpmd:port_please(Name, Ip) of
{port, TcpPort, Version} ->
?trace("port_please(~p) -> version ~p~n",
[Node,Version]),
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index 4651687fe6..2e308a15b7 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -116,7 +116,8 @@ handle_call({listen, Driver, Name}, _From, State) ->
{ok, TcpAddress} = get_tcp_address(Socket),
{ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
- case erl_epmd:register_node(Name, Port) of
+ ErlEpmd = net_kernel:epmd_module(),
+ case ErlEpmd:register_node(Name, Port) of
{ok, Creation} ->
{reply, {ok, {Socket, TcpAddress, Creation}},
State#state{listen={Socket, World}}};