File 2507-ssh-document-what-happens-when-ssh-daemon-sets-both-.patch of Package erlang

From 7ad21ca66f5a46be231fffe884ac2c3b5d97c7ae Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 4 Apr 2017 19:53:05 +0200
Subject: [PATCH 8/9] 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.
---
 lib/ssh/doc/src/ssh.xml | 22 ++++++++++++-
 lib/ssh/src/ssh.erl     | 82 +++++--------------------------------------------
 2 files changed, 29 insertions(+), 75 deletions(-)

diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 88d402cf3..48c9aa18e 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 8c802d46e..3e80a04b7 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.
 
 %%%----------------------------------------------------------------
-- 
2.12.2

openSUSE Build Service is sponsored by