processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/en/ejabberd/
Other
6k stars 1.5k forks source link

Assigning INET_DIST_INTERFACE to an IPv6 address #4189

Closed GautaA closed 1 month ago

GautaA commented 3 months ago

Environment

Bug description

In an IPv6 only environment when trying to set INET_DIST_INTERFACE in ejabberdctl.cfg to "::" or :: the result is:

Protocol 'inet_tcp': register/listen error: badarg

Can this even be done? When testing in ERL emulator:

4> inet_tcp:parse_address("::").
{error,einval}
5> inet6_tcp:parse_address("::").
{ok,{0,0,0,0,0,0,0,0}}
badlop commented 3 months ago

This comment is just to say that I can reproduce it, and found no clue.

This works:

erl -sname aaa

epmd -names
epmd: up and running on port 4369 with data:
name aaa at port 35133

netstat -nl |  grep 35133
tcp        0      0 0.0.0.0:35133           0.0.0.0:*               LISTEN     

And also specifying a IPv4 address (the commas ' seem important here):

erl -name aaa@localhost -kernel inet_dist_use_interface '{127,0,0,1}'

epmd -names
epmd: up and running on port 4369 with data:
name aaa at port 37827

netstat -nl | grep 37827
tcp        0      0 127.0.0.1:37827         0.0.0.0:*               LISTEN     

However, I found no way to specify an IPv6 address. I tried:

erl -name aaa@localhost -kernel inet_dist_use_interface '{0,0,0,0,0,0,0,0}'
Protocol 'inet_tcp': register/listen error: badarg

erl -sname aaa@localhost -kernel inet_dist_use_interface '{0,0,0,0,0,0,0,0}'
Protocol 'inet_tcp': register/listen error: badarg

erl
1> inet:parse_address("FFFF::127.0.0.1").   
{ok,{65535,0,0,0,0,0,32512,1}}

erl -name aaa@localhost -kernel inet_dist_use_interface '{65535,0,0,0,0,0,32512,1}'
Protocol 'inet_tcp': register/listen error: badarg

erl -sname aaa -kernel inet_dist_use_interface '{65535,0,0,0,0,0,32512,1}'
Protocol 'inet_tcp': register/listen error: badarg

I can reproduce this with Erlang 25.3, 26.2.3 and 27.0-rc2

I couldn't find documentation for the -kernel option in erl https://erlang.org/documentation/doc-15.0-rc2/erts-14.3/doc/html/erl_cmd.html

The inet_dist_user_interface option is documented in the kernel application: https://erlang.org/documentation/doc-15.0-rc2/lib/kernel-9.3/doc/html/kernel_app.html#configuration

nosnilmot commented 3 months ago

it needs -proto_dist inet6_tcp (https://www.erlang.org/doc/man/erl.html#proto_dist):

erl -proto_dist inet6_tcp -sname hello -kernel inet_dist_use_interface "{0,0,0,0,0,0,0,0}"

badlop commented 3 months ago

Great finding!

Then I guess that ejabberdctl option was never used to setup a IPv6 address.

And to support it, a patch like this would be required:

diff --git a/ejabberdctl.template b/ejabberdctl.template
index f558e93b2..28c31c054 100755
--- a/ejabberdctl.template
+++ b/ejabberdctl.template
@@ -78,6 +78,9 @@ fi
 if [ -n "$INET_DIST_INTERFACE" ] ; then
     INET_DIST_INTERFACE2=$("$ERL" $ERLANG_OPTS -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt)
     if [ -n "$INET_DIST_INTERFACE2" ] ; then
+        if [ $(echo "$INET_DIST_INTERFACE2" | grep -o "," | wc -l) -eq 7 ] ; then
+            INET_DIST_INTERFACE2="$INET_DIST_INTERFACE2 -proto_dist inet6_tcp"
+        fi
         ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
     fi
 fi