diff --git a/src/ejabberd_option.erl b/src/ejabberd_option.erl index 907272761..fd056b761 100644 --- a/src/ejabberd_option.erl +++ b/src/ejabberd_option.erl @@ -90,6 +90,8 @@ -export([oom_killer/0]). -export([oom_queue/0]). -export([oom_watermark/0]). +-export([outgoing_s2s_ipv4_address/0,outgoing_s2s_ipv4_address/1]). +-export([outgoing_s2s_ipv6_address/0,outgoing_s2s_ipv6_address/1]). -export([outgoing_s2s_families/0, outgoing_s2s_families/1]). -export([outgoing_s2s_port/0, outgoing_s2s_port/1]). -export([outgoing_s2s_timeout/0, outgoing_s2s_timeout/1]). @@ -667,6 +669,20 @@ outgoing_s2s_families() -> outgoing_s2s_families(Host) -> ejabberd_config:get_option({outgoing_s2s_families, Host}). +-spec outgoing_s2s_ipv4_address() -> inet:ip4_address(). +outgoing_s2s_ipv4_address() -> + outgoing_s2s_ipv4_address(global). +-spec outgoing_s2s_ipv4_address(global | binary()) -> inet:ip4_address(). +outgoing_s2s_ipv4_address(Host) -> + ejabberd_config:get_option({outgoing_s2s_ipv4_address, Host}). + +-spec outgoing_s2s_ipv6_address() -> inet:ip6_address(). +outgoing_s2s_ipv6_address() -> + outgoing_s2s_ipv6_address(global). +-spec outgoing_s2s_ipv6_address(global | binary()) -> inet:ip6_address(). +outgoing_s2s_ipv6_address(Host) -> + ejabberd_config:get_option({outgoing_s2s_ipv6_address, Host}). + -spec outgoing_s2s_port() -> 1..1114111. outgoing_s2s_port() -> outgoing_s2s_port(global). diff --git a/src/ejabberd_options.erl b/src/ejabberd_options.erl index a9ca961ae..a03071dc1 100644 --- a/src/ejabberd_options.erl +++ b/src/ejabberd_options.erl @@ -271,6 +271,10 @@ opt_type(outgoing_s2s_families) -> (ipv6) -> inet6 end, L) end); +opt_type(outgoing_s2s_ipv4_address) -> + econf:ipv4(); +opt_type(outgoing_s2s_ipv6_address) -> + econf:ipv6(); opt_type(outgoing_s2s_port) -> econf:port(); opt_type(outgoing_s2s_timeout) -> @@ -589,6 +593,8 @@ options() -> {oom_queue, 10000}, {oom_watermark, 80}, {outgoing_s2s_families, [inet, inet6]}, + {outgoing_s2s_ipv4_address, undefined}, + {outgoing_s2s_ipv6_address, undefined}, {outgoing_s2s_port, 5269}, {outgoing_s2s_timeout, timer:seconds(10)}, {pam_service, <<"ejabberd">>}, diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 3904c7fad..4a6d5cb67 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -24,7 +24,7 @@ %% xmpp_stream_out callbacks -export([tls_options/1, tls_required/1, tls_verify/1, tls_enabled/1, - connect_timeout/1, address_families/1, default_port/1, + connect_options/3, connect_timeout/1, address_families/1, default_port/1, dns_retries/1, dns_timeout/1, handle_auth_success/2, handle_auth_failure/3, handle_packet/2, handle_stream_end/2, handle_stream_downgraded/2, @@ -187,6 +187,17 @@ tls_verify(#{server_host := ServerHost} = State) -> tls_enabled(#{server_host := ServerHost}) -> ejabberd_s2s:tls_enabled(ServerHost). +connect_options(Addr, Opts, #{server_host := ServerHost}) -> + Type = get_addr_type(Addr), + Bindaddr = case Type of + inet -> ejabberd_option:outgoing_s2s_ipv4_address(ServerHost); + inet6 -> ejabberd_option:outgoing_s2s_ipv6_address(ServerHost) + end, + case Bindaddr of + undefined -> Opts; + _ -> lists:append([Opts, [{ip, Bindaddr}]]) + end. + connect_timeout(#{server_host := ServerHost}) -> ejabberd_option:outgoing_s2s_timeout(ServerHost). @@ -318,6 +329,11 @@ code_change(_OldVsn, State, _Extra) -> %%%=================================================================== %%% Internal functions %%%=================================================================== + +-spec get_addr_type(inet:ip_address()) -> inet:address_family(). +get_addr_type({_, _, _, _}) -> inet; +get_addr_type({_, _, _, _, _, _, _, _}) -> inet6. + -spec resend_queue(state()) -> state(). resend_queue(State) -> queue_fold(