From 1498e0444ece4ec97059a03bd1a47e3dcbee5074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20P=C3=A9dron?= Date: Sat, 16 Mar 2024 18:06:18 +0100 Subject: [PATCH] rabbit_peer_discovery: Pass inetrc config file to temporary hidden node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] As shown in #10728, in an IPv6-only environment, `kernel` name resolution must be configured through an inetrc file. The temporary hidden node must be configured exactly like the main node (and all nodes in the cluster in fact) to allow communication. Thus we must pass the same inetrc file to that temporary hidden node. This wasn’t the case before this patch. [How] We query the main node’s kernel to see if there is any inetrc file set and we use the same on the temporary hidden node’s command line. While here, extract the handling of the `proto_dist` module from the TLS code. This parameter may be used outside of TLS like this IPv6-only environment. Fixes #10728. --- deps/rabbit/src/rabbit_peer_discovery.erl | 76 ++++++++++++++--------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/deps/rabbit/src/rabbit_peer_discovery.erl b/deps/rabbit/src/rabbit_peer_discovery.erl index a53ffe6083b3..fbbd7f70b824 100644 --- a/deps/rabbit/src/rabbit_peer_discovery.erl +++ b/deps/rabbit/src/rabbit_peer_discovery.erl @@ -372,7 +372,7 @@ query_node_props(Nodes) when Nodes =/= [] -> %% By using a temporary intermediate hidden node, we ask Erlang not to %% connect everyone automatically. Context = rabbit_prelaunch:get_context(), - VMArgs0 = ["-hidden"], + VMArgs0 = ["+pc","unicode","-hidden"], VMArgs1 = case init:get_argument(boot) of {ok, [[BootFileArg]]} -> ["-boot", BootFileArg | VMArgs0]; @@ -388,16 +388,18 @@ query_node_props(Nodes) when Nodes =/= [] -> _ -> VMArgs1 end, - VMArgs3 = maybe_add_tls_arguments(VMArgs2), + VMArgs3 = maybe_add_proto_dist_arguments(VMArgs2), + VMArgs4 = maybe_add_inetrc_arguments(VMArgs3), + VMArgs5 = maybe_add_tls_arguments(VMArgs4), PeerStartArg = case Context of #{nodename_type := longnames} -> #{name => PeerName, host => Suffix, longnames => true, - args => VMArgs3}; + args => VMArgs5}; _ -> #{name => PeerName, - args => VMArgs3} + args => VMArgs5} end, ?LOG_DEBUG("Peer discovery: peer node arguments: ~tp", [PeerStartArg]), @@ -423,27 +425,45 @@ query_node_props(Nodes) when Nodes =/= [] -> query_node_props([]) -> []. -maybe_add_tls_arguments(VMArgs0) -> +maybe_add_proto_dist_arguments(VMArgs) -> case init:get_argument(proto_dist) of - {ok, [["inet_tls"]]} -> - add_tls_arguments(inet_tls, VMArgs0); - {ok, [["inet6_tls"]]} -> - add_tls_arguments(inet6_tls, VMArgs0); + {ok, [[Val]]} -> + %% Note: + %% + %% We can't use list_to_existing_atom/1 because + %% the atom doesn't actually already exist. + %% + %% See net_kernel.erl / protocol_childspecs/1 + Mod = list_to_atom(Val ++ "_dist"), + ModDir = filename:dirname(code:which(Mod)), + ["-proto_dist", Val, "-pa", ModDir | VMArgs]; _ -> - VMArgs0 + VMArgs end. -add_tls_arguments(InetDistModule, VMArgs0) -> - VMArgs1 = case InetDistModule of - inet_tls -> - ProtoDistArg = ["-proto_dist", "inet_tls" | VMArgs0], - ["-pa", filename:dirname(code:which(inet_tls_dist)) - | ProtoDistArg]; - inet6_tls -> - ProtoDistArg = ["-proto_dist", "inet6_tls" | VMArgs0], - ["-pa", filename:dirname(code:which(inet6_tls_dist)) - | ProtoDistArg] - end, +maybe_add_inetrc_arguments(VMArgs) -> + %% If an inetrc file is configured, we need to use it for the temporary + %% hidden node too. + case application:get_env(kernel, inetrc) of + {ok, Val} when is_list(Val) -> + maybe_add_inetrc_arguments1(VMArgs, Val); + undefined -> + case os:getenv("ERL_INETRC") of + Val when is_list(Val) -> + maybe_add_inetrc_arguments1(VMArgs, Val); + false -> + VMArgs + end + end. + +maybe_add_inetrc_arguments1(VMArgs, Val) -> + %% The filename argument must be passed as a quoted string so that the + %% command line is correctly parsed as an Erlang string by the temporary + %% hidden node. + ValString = rabbit_misc:format("~0p", [Val]), + ["-kernel", "inetrc", ValString | VMArgs]. + +maybe_add_tls_arguments(VMArgs) -> %% In the next case, RabbitMQ has been configured with additional Erlang VM %% arguments such as this: %% @@ -494,14 +514,14 @@ add_tls_arguments(InetDistModule, VMArgs0) -> %% "/usr/local/lib/erlang/lib/ssl-11.0.3/ebin", %% "-proto_dist","inet_tls","-boot", %% "no_dot_erlang","-hidden"], - VMArgs2 = case init:get_argument(ssl_dist_opt) of + VMArgs1 = case init:get_argument(ssl_dist_opt) of {ok, SslDistOpts0} -> SslDistOpts1 = [["-ssl_dist_opt" | SslDistOpt] || SslDistOpt <- SslDistOpts0], SslDistOpts2 = lists:concat(SslDistOpts1), - SslDistOpts2 ++ VMArgs1; + SslDistOpts2 ++ VMArgs; _ -> - VMArgs1 + VMArgs end, %% In the next case, RabbitMQ has been configured with additional Erlang VM %% arguments such as this: @@ -511,13 +531,13 @@ add_tls_arguments(InetDistModule, VMArgs0) -> %% %% This code adds the `ssl_dist_optfile' argument to the peer node's %% argument list. - VMArgs3 = case init:get_argument(ssl_dist_optfile) of + VMArgs2 = case init:get_argument(ssl_dist_optfile) of {ok, [[SslDistOptfileArg]]} -> - ["-ssl_dist_optfile", SslDistOptfileArg | VMArgs2]; + ["-ssl_dist_optfile", SslDistOptfileArg | VMArgs1]; _ -> - VMArgs2 + VMArgs1 end, - VMArgs3. + VMArgs2. do_query_node_props(Nodes) when Nodes =/= [] -> %% Make sure all log messages are forwarded from this temporary hidden