From f7ca16604b567d19078a3edb7c9ba84ffa33a2dc Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Wed, 4 Jun 2014 12:32:00 +0200
Subject: ssh: Handle inet and inet6 option correctly

---
 lib/ssh/doc/src/ssh.xml          |  6 ++++-
 lib/ssh/src/ssh.erl              | 26 ++++++++++++++++-----
 lib/ssh/test/ssh_basic_SUITE.erl | 50 ++++++++++++++++++++++++++++++++--------
 3 files changed, 66 insertions(+), 16 deletions(-)

(limited to 'lib/ssh')

diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 5a141ced3c..876eba598a 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -4,7 +4,7 @@
 <erlref>
   <header>
     <copyright>
-      <year>2004</year><year>2013</year>
+      <year>2004</year><year>2014</year>
       <holder>Ericsson AB. All Rights Reserved.</holder>
     </copyright>
     <legalnotice>
@@ -97,6 +97,8 @@
 	<seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/[2, 4]</seealso>.</p>
 	<p>Options are:</p>
 	<taglist>
+	  <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
+	  <item> IP version to use.</item>
           <tag><c><![CDATA[{user_dir, string()}]]></c></tag>
 	  <item>
 	    <p>Sets the user directory i.e. the directory containing
@@ -230,6 +232,8 @@
         port.</p>
 	<p>Options are:</p>
         <taglist>
+	  <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
+	  <item> IP version to use when the host address is specified as <c>any</c>. </item>
 	  <tag><c><![CDATA[{subsystems, [subsystem_spec()]]]></c></tag>
 	  <item>
 	    Provides specifications for handling of subsystems. The
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 240de69eff..bf7ba0be7f 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -74,8 +74,7 @@ connect(Host, Port, Options, Timeout) ->
 	    {_, Transport, _} = TransportOpts =
 		proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}),
 	    ConnectionTimeout = proplists:get_value(connect_timeout, Options, infinity),
-	    Inet = proplists:get_value(inet, SshOptions, inet),
-	    try Transport:connect(Host, Port,  [ {active, false}, Inet | SocketOptions], ConnectionTimeout) of
+	    try Transport:connect(Host, Port,  [ {active, false} | SocketOptions], ConnectionTimeout) of
 		{ok, Socket} ->
 		    Opts =  [{user_pid, self()}, {host, Host} | fix_idle_time(SshOptions)],
 		    ssh_connection_handler:start_connection(client, Socket, Opts, Timeout);
@@ -256,8 +255,8 @@ do_start_daemon(Host, Port, Options, SocketOptions) ->
 
 handle_options(Opts) ->
     try handle_option(proplists:unfold(Opts), [], []) of
-	{_,_} = Options ->
-	    Options
+	{Inet, Ssh} ->
+	    {handle_ip(Inet), Ssh}
     catch
 	throw:Error ->
 	    Error
@@ -436,8 +435,9 @@ handle_inet_option({active, _} = Opt) ->
     throw({error, {{eoptions, Opt}, "Ssh has built in flow control, "
 		   "and activ is handled internaly user is not allowd"
 		   "to specify this option"}});
-handle_inet_option({inet, Value} = Opt) when (Value == inet) or (Value == inet6) ->
-    Opt;
+
+handle_inet_option({inet, Value}) when (Value == inet) or (Value == inet6) ->
+    Value;
 handle_inet_option({reuseaddr, _} = Opt) ->
     throw({error, {{eoptions, Opt},"Is set internaly user is not allowd"
 		   "to specify this option"}});
@@ -460,3 +460,17 @@ handle_pref_algs([H|T], Acc) ->
 	_ ->
 	    false
     end.
+
+handle_ip(Inet) -> %% Default to ipv4
+    case lists:member(inet, Inet) of
+	true ->
+	    Inet;
+	false ->
+	    case lists:member(inet6, Inet) of
+		true -> 
+		    Inet;
+		false ->
+		    [inet | Inet]
+	    end
+    end.
+	
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index ba38c1da40..bf7fb4c73e 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -66,7 +66,8 @@ groups() ->
 basic_tests() ->
     [send, close, peername_sockname,
      exec, exec_compressed, shell, cli, known_hosts, 
-     idle_time, rekey, openssh_zlib_basic_test].
+     idle_time, rekey, openssh_zlib_basic_test,
+     misc_ssh_options, inet_option].
 
 
 %%--------------------------------------------------------------------
@@ -175,16 +176,47 @@ misc_ssh_options(Config) when is_list(Config) ->
     SystemDir = filename:join(?config(priv_dir, Config), system),
     UserDir = ?config(priv_dir, Config),
     
-    CMiscOpt0 = [{connecect_timeout, 1000}, {ip_v6_disabled, false}, {user_dir, UserDir}],
-    CMiscOpt1 = [{connecect_timeout, infinity}, {ip_v6_disabled, true}, {user_dir, UserDir}],
-    SMiscOpt0 =  [{ip_v6_disabled, false}, {user_dir, UserDir}, {system_dir, SystemDir}],
-    SMiscOpt1 =  [{ip_v6_disabled, true}, {user_dir, UserDir}, {system_dir, SystemDir}],
+    CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}],
+    CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}],
+    SMiscOpt0 =  [{user_dir, UserDir}, {system_dir, SystemDir}],
+    SMiscOpt1 =  [{user_dir, UserDir}, {system_dir, SystemDir}],
+
+    basic_test([{client_opts, CMiscOpt0}, {server_opts, SMiscOpt0}]),
+    basic_test([{client_opts, CMiscOpt1}, {server_opts, SMiscOpt1}]).
+
+%%--------------------------------------------------------------------
+inet_option() ->
+    [{doc, "Test configuring IPv4"}].
+inet_option(Config) when is_list(Config) ->   
+    SystemDir = filename:join(?config(priv_dir, Config), system),
+    UserDir = ?config(priv_dir, Config),
     
-    ClientOpts = ?config(client_opts, Config),
-    ServerOpts = ?config(server_opts, Config),
+    ClientOpts =  [{silently_accept_hosts, true},
+		   {user_dir, UserDir},
+		   {user_interaction, false}],
+    ServerOpts = [{system_dir, SystemDir},
+		  {user_dir, UserDir},
+		  {failfun, fun ssh_test_lib:failfun/2}], 
+
+    basic_test([{client_opts, [{inet, inet} | ClientOpts]}, 
+		{server_opts, [{inet, inet} | ServerOpts]}]).
 
-    basic_test([{client_opts, CMiscOpt0 ++ ClientOpts}, {server_opts, SMiscOpt0 ++ ServerOpts}]),
-    basic_test([{client_opts, CMiscOpt1 ++ ClientOpts}, {server_opts, SMiscOpt1 ++ ServerOpts}]).
+%%--------------------------------------------------------------------
+inet6_option() ->
+    [{doc, "Test configuring IPv6"}].
+inet6_option(Config) when is_list(Config) ->   
+    SystemDir = filename:join(?config(priv_dir, Config), system),
+    UserDir = ?config(priv_dir, Config),
+    
+    ClientOpts =  [{silently_accept_hosts, true},
+		   {user_dir, UserDir},
+		   {user_interaction, false}],
+    ServerOpts = [{system_dir, SystemDir},
+		  {user_dir, UserDir},
+		  {failfun, fun ssh_test_lib:failfun/2}], 
+
+    basic_test([{client_opts, [{inet, inet6} | ClientOpts]}, 
+		{server_opts, [{inet, inet6} | ServerOpts]}]).
 
 %%--------------------------------------------------------------------
 exec() ->
-- 
cgit v1.2.3