aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2017-04-04 19:53:05 +0200
committerHans Nilsson <[email protected]>2017-04-07 10:23:41 +0200
commit7ad21ca66f5a46be231fffe884ac2c3b5d97c7ae (patch)
treee29e3010212809dc9c2981d36663a1e69aa9f680
parent2f91341ae855b28c82024caa87c7541e94f68a18 (diff)
downloadotp-7ad21ca66f5a46be231fffe884ac2c3b5d97c7ae.tar.gz
otp-7ad21ca66f5a46be231fffe884ac2c3b5d97c7ae.tar.bz2
otp-7ad21ca66f5a46be231fffe884ac2c3b5d97c7ae.zip
ssh: document what happens when ssh:daemon sets both HostAddr and ip option
The idea is that the HostAddress argument takes precedence over an ip-option. However, an ip-option overrides the 'any' HostAddr. This fixes the case of dameon(Port, [{ip,IP}..] in a non-surprising way.
-rw-r--r--lib/ssh/doc/src/ssh.xml22
-rw-r--r--lib/ssh/src/ssh.erl82
2 files changed, 29 insertions, 75 deletions
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 88d402cf38..48c9aa18e9 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -379,7 +379,7 @@
on the given port.</fsummary>
<type>
<v>Port = integer()</v>
- <v>HostAddress = ip_address() | any</v>
+ <v>HostAddress = ip_address() | any | loopback</v>
<v>Options = [{Option, Value}]</v>
<v>Option = atom()</v>
<v>Value = term()</v>
@@ -390,6 +390,26 @@
<p>Starts a server listening for SSH connections on the given
port. If the <c>Port</c> is 0, a random free port is selected. See
<seealso marker="#daemon_info/1">daemon_info/1</seealso> about how to find the selected port number.</p>
+
+ <p>Please note that by historical reasons both the <c>HostAddress</c> argument and the inet socket option
+ <c>ip</c> set the listening address. This is a source of possible inconsistent settings.</p>
+
+ <p>The rules for handling the two address passing options are:</p>
+ <list>
+ <item>if <c>HostAddress</c> is an ip-address, that ip-address is the listening address.
+ An ip-option will be discarded if present.</item>
+
+ <item>if <c>HostAddress</c> is <c>loopback</c>, the listening address
+ is <c>loopback</c> and an loopback address will be choosen by the underlying layers.
+ An ip-option will be discarded if present.</item>
+
+ <item>if <c>HostAddress</c> is <c>any</c> and no ip-option is present, the listening address is
+ <c>any</c> and the socket will listen to all addresses</item>
+
+ <item>if <c>HostAddress</c> is <c>any</c> and an ip-option is present, the listening address is
+ set to the value of the ip-option</item>
+ </list>
+
<p>Options:</p>
<taglist>
<tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 8c802d46eb..3e80a04b70 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -225,7 +225,8 @@ daemon(Port, UserOptions) when 0 =< Port, Port =< 65535 ->
daemon(any, Port, UserOptions).
-daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535 ->
+daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535,
+ Host0 == any ; Host0 == loopback ; is_tuple(Host0) ->
try
{Host1, UserOptions} = handle_daemon_args(Host0, UserOptions0),
#{} = Options0 = ssh_options:handle_options(server, UserOptions),
@@ -259,7 +260,11 @@ daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535 ->
{error,Error};
_C:_E ->
{error,{cannot_start_daemon,_C,_E}}
- end.
+ end;
+
+daemon(_, _, _) ->
+ {error, badarg}.
+
%%--------------------------------------------------------------------
@@ -378,35 +383,6 @@ default_algorithms() ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-
-%% - if Address is 'any' and no ip-option is present, the name is
-%% 'any' and the socket will listen to all addresses
-%%
-%% - if Address is 'any' and an ip-option is present, the name is
-%% set to the value of the ip-option and the socket will listen
-%% to that address
-%%
-%% - if Address is 'loopback' and no ip-option is present, the name
-%% is 'loopback' and an loopback address will be choosen by the
-%% underlying layers
-%%
-%% - if Address is 'loopback' and an ip-option is present, the name
-%% is set to the value of the ip-option kept and the socket will
-%% listen to that address
-%%
-%% - if Address is an ip-address, that ip-address is the name and
-%% the listening address. An ip-option will be discarded.
-%%
-%% - if Address is a HostName, and that resolves to an ip-address,
-%% that ip-address is the name and the listening address. An
-%% ip-option will be discarded.
-%%
-%% - if Address is a string or an atom other than thoose defined
-%% above, that Address will be the name and the listening address
-%% will be choosen by the lower layers taking an ip-option in
-%% consideration
-%%
-
%% The handle_daemon_args/2 function basically only sets the ip-option in Opts
%% so that it is correctly set when opening the listening socket.
@@ -416,53 +392,11 @@ handle_daemon_args(any, Opts) ->
IP -> {IP, Opts}
end;
-handle_daemon_args(loopback, Opts) ->
- case proplists:get_value(ip, Opts) of
- undefined -> {loopback, [{ip,loopback}|Opts]};
- IP -> {IP, Opts}
- end;
-
-handle_daemon_args(IPaddr, Opts) when is_tuple(IPaddr) ->
+handle_daemon_args(IPaddr, Opts) when is_tuple(IPaddr) ; IPaddr == loopback ->
case proplists:get_value(ip, Opts) of
undefined -> {IPaddr, [{ip,IPaddr}|Opts]};
IPaddr -> {IPaddr, Opts};
IP -> {IPaddr, [{ip,IPaddr}|Opts--[{ip,IP}]]} %% Backward compatibility
- end;
-
-handle_daemon_args(Address, Opts) when is_list(Address) ; % IP address in string or a domain
- is_atom(Address) % domains could be atoms in inet
- ->
- IP = proplists:get_value(ip, Opts),
- case inet:parse_strict_address(Address) of
- %% check if Address is an IP-address
- {ok, IP} -> {IP, Opts};
- {ok, OtherIP} -> {OtherIP, [{ip,OtherIP}|Opts--[{ip,IP}]]};
- _ ->
- %% Not an IP-address. Check if it is a host name:
- case inet:getaddr(Address, family(Opts)) of
- {ok, IP} -> {Address, Opts};
- {ok, OtherIP} -> {Address, [{ip,OtherIP}|Opts--[{ip,IP}]]};
- _ ->
- %% Not a Host name and not an IP address, let
- %% inet and the OS later figure out what it
- %% could be
- {Address, Opts}
- end
- end.
-
-%% Has the caller indicated the address family?
-family(Opts) ->
- family(Opts, inet).
-
-family(Opts, Default) ->
- case proplists:get_value(inet,Opts) of
- true -> inet;
- inet -> inet;
- inet6 -> inet6;
- _ -> case proplists:get_value(inet6,Opts) of
- true -> inet6;
- _ -> Default
- end
end.
%%%----------------------------------------------------------------