aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/src
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2015-06-02 09:14:18 +0200
committerIngela Anderton Andin <[email protected]>2015-06-03 14:22:42 +0200
commit051a662cdc5cfc2aa93d86119688c14743837a5f (patch)
tree9b6f585473696e64f4c856b9401a148fe4e07409 /lib/ssh/src
parent2c323bd46cecd0592a47e32e4b57f3b6600b828d (diff)
downloadotp-051a662cdc5cfc2aa93d86119688c14743837a5f.tar.gz
otp-051a662cdc5cfc2aa93d86119688c14743837a5f.tar.bz2
otp-051a662cdc5cfc2aa93d86119688c14743837a5f.zip
ssh: Add profile option
To enable the ssh daemon to run in a virtualized environment, where there can be more that one server that has the same ip-address and port, we add a new option profile. The profile name will be used in concatenation with ip-address and port to identify the ssh daemon instance. The name profile was chosen as there is a similar concept in the HTTP client in inets where profile names can be used to instantiate client configurations. Also the same type of option has been added to the HTTP server in inets.
Diffstat (limited to 'lib/ssh/src')
-rw-r--r--lib/ssh/src/ssh.erl19
-rw-r--r--lib/ssh/src/ssh.hrl1
-rw-r--r--lib/ssh/src/ssh_acceptor.erl6
-rw-r--r--lib/ssh/src/ssh_acceptor_sup.erl24
-rw-r--r--lib/ssh/src/ssh_system_sup.erl64
-rw-r--r--lib/ssh/src/sshd_sup.erl27
6 files changed, 95 insertions, 46 deletions
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 4a07473f74..48d18c05f3 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -29,7 +29,8 @@
channel_info/3,
daemon/1, daemon/2, daemon/3,
default_algorithms/0,
- stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2,
+ stop_listener/1, stop_listener/2, stop_listener/3,
+ stop_daemon/1, stop_daemon/2, stop_daemon/3,
shell/1, shell/2, shell/3]).
%%--------------------------------------------------------------------
@@ -158,7 +159,9 @@ daemon(HostAddr, Port, Options0) ->
stop_listener(SysSup) ->
ssh_system_sup:stop_listener(SysSup).
stop_listener(Address, Port) ->
- ssh_system_sup:stop_listener(Address, Port).
+ stop_listener(Address, Port, ?DEFAULT_PROFILE).
+stop_listener(Address, Port, Profile) ->
+ ssh_system_sup:stop_listener(Address, Port, Profile).
%%--------------------------------------------------------------------
-spec stop_daemon(pid()) -> ok.
@@ -170,8 +173,9 @@ stop_listener(Address, Port) ->
stop_daemon(SysSup) ->
ssh_system_sup:stop_system(SysSup).
stop_daemon(Address, Port) ->
- ssh_system_sup:stop_system(Address, Port).
-
+ ssh_system_sup:stop_system(Address, Port, ?DEFAULT_PROFILE).
+stop_daemon(Address, Port, Profile) ->
+ ssh_system_sup:stop_system(Address, Port, Profile).
%%--------------------------------------------------------------------
-spec shell(string()) -> _.
-spec shell(string(), proplists:proplist()) -> _.
@@ -232,7 +236,8 @@ start_daemon(Host, Port, Options, Inet) ->
end.
do_start_daemon(Host, Port, Options, SocketOptions) ->
- case ssh_system_sup:system_supervisor(Host, Port) of
+ Profile = proplists:get_value(profile, Options, ?DEFAULT_PROFILE),
+ case ssh_system_sup:system_supervisor(Host, Port, Profile) of
undefined ->
%% It would proably make more sense to call the
%% address option host but that is a too big change at the
@@ -382,6 +387,8 @@ handle_option([{minimal_remote_max_packet_size, _} = Opt|Rest], SocketOptions, S
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{id_string, _ID} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{profile, _ID} = Opt|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions).
@@ -476,6 +483,8 @@ handle_ssh_option({id_string, random}) ->
{id_string, {random,2,5}}; %% 2 - 5 random characters
handle_ssh_option({id_string, ID} = Opt) when is_list(ID) ->
Opt;
+handle_ssh_option({profile, Value} = Opt) when is_atom(Value) ->
+ Opt;
handle_ssh_option(Opt) ->
throw({error, {eoptions, Opt}}).
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 0c4d34f89c..94154c8a96 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -31,6 +31,7 @@
-define(SSH_LENGHT_INDICATOR_SIZE, 4).
-define(REKEY_TIMOUT, 3600000).
-define(REKEY_DATA_TIMOUT, 60000).
+-define(DEFAULT_PROFILE, default).
-define(FALSE, 0).
-define(TRUE, 1).
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index 34988f17b6..6c431af270 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -21,6 +21,8 @@
-module(ssh_acceptor).
+-include("ssh.hrl").
+
%% Internal application API
-export([start_link/5,
number_of_connections/1]).
@@ -82,8 +84,10 @@ acceptor_loop(Callback, Port, Address, Opts, ListenSocket, AcceptTimeout) ->
end.
handle_connection(Callback, Address, Port, Options, Socket) ->
- SystemSup = ssh_system_sup:system_supervisor(Address, Port),
SSHopts = proplists:get_value(ssh_opts, Options, []),
+ Profile = proplists:get_value(profile, SSHopts, ?DEFAULT_PROFILE),
+ SystemSup = ssh_system_sup:system_supervisor(Address, Port, Profile),
+
MaxSessions = proplists:get_value(max_sessions,SSHopts,infinity),
case number_of_connections(SystemSup) < MaxSessions of
true ->
diff --git a/lib/ssh/src/ssh_acceptor_sup.erl b/lib/ssh/src/ssh_acceptor_sup.erl
index 46fdef07d0..e101ce8b39 100644
--- a/lib/ssh/src/ssh_acceptor_sup.erl
+++ b/lib/ssh/src/ssh_acceptor_sup.erl
@@ -26,7 +26,9 @@
-module(ssh_acceptor_sup).
-behaviour(supervisor).
--export([start_link/1, start_child/2, stop_child/3]).
+-include("ssh.hrl").
+
+-export([start_link/1, start_child/2, stop_child/4]).
%% Supervisor callback
-export([init/1]).
@@ -45,14 +47,16 @@ start_child(AccSup, ServerOpts) ->
{error, already_present} ->
Address = proplists:get_value(address, ServerOpts),
Port = proplists:get_value(port, ServerOpts),
- stop_child(AccSup, Address, Port),
+ Profile = proplists:get_value(profile,
+ proplists:get_value(ssh_opts, ServerOpts), ?DEFAULT_PROFILE),
+ stop_child(AccSup, Address, Port, Profile),
supervisor:start_child(AccSup, Spec);
Reply ->
Reply
end.
-stop_child(AccSup, Address, Port) ->
- Name = id(Address, Port),
+stop_child(AccSup, Address, Port, Profile) ->
+ Name = id(Address, Port, Profile),
case supervisor:terminate_child(AccSup, Name) of
ok ->
supervisor:delete_child(AccSup, Name);
@@ -77,7 +81,8 @@ child_spec(ServerOpts) ->
Address = proplists:get_value(address, ServerOpts),
Port = proplists:get_value(port, ServerOpts),
Timeout = proplists:get_value(timeout, ServerOpts, ?DEFAULT_TIMEOUT),
- Name = id(Address, Port),
+ Profile = proplists:get_value(profile, proplists:get_value(ssh_opts, ServerOpts), ?DEFAULT_PROFILE),
+ Name = id(Address, Port, Profile),
SocketOpts = proplists:get_value(socket_opts, ServerOpts),
StartFunc = {ssh_acceptor, start_link, [Port, Address,
[{active, false},
@@ -89,6 +94,11 @@ child_spec(ServerOpts) ->
Type = worker,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-id(Address, Port) ->
- {ssh_acceptor_sup, Address, Port}.
+id(Address, Port, Profile) ->
+ case is_list(Address) of
+ true ->
+ {ssh_acceptor_sup, any, Port, Profile};
+ false ->
+ {ssh_acceptor_sup, Address, Port, Profile}
+ end.
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
index 660fe8bb65..acf94b4b73 100644
--- a/lib/ssh/src/ssh_system_sup.erl
+++ b/lib/ssh/src/ssh_system_sup.erl
@@ -28,13 +28,15 @@
-behaviour(supervisor).
+-include("ssh.hrl").
+
-export([start_link/1, stop_listener/1,
- stop_listener/2, stop_system/1,
- stop_system/2, system_supervisor/2,
+ stop_listener/3, stop_system/1,
+ stop_system/3, system_supervisor/3,
subsystem_supervisor/1, channel_supervisor/1,
connection_supervisor/1,
- acceptor_supervisor/1, start_subsystem/2, restart_subsystem/2,
- restart_acceptor/2, stop_subsystem/2]).
+ acceptor_supervisor/1, start_subsystem/2, restart_subsystem/3,
+ restart_acceptor/3, stop_subsystem/2]).
%% Supervisor callback
-export([init/1]).
@@ -45,14 +47,15 @@
start_link(ServerOpts) ->
Address = proplists:get_value(address, ServerOpts),
Port = proplists:get_value(port, ServerOpts),
- Name = make_name(Address, Port),
+ Profile = proplists:get_value(profile, proplists:get_value(ssh_opts, ServerOpts), ?DEFAULT_PROFILE),
+ Name = make_name(Address, Port, Profile),
supervisor:start_link({local, Name}, ?MODULE, [ServerOpts]).
stop_listener(SysSup) ->
stop_acceptor(SysSup).
-stop_listener(Address, Port) ->
- Name = make_name(Address, Port),
+stop_listener(Address, Port, Profile) ->
+ Name = make_name(Address, Port, Profile),
stop_acceptor(whereis(Name)).
stop_system(SysSup) ->
@@ -60,12 +63,12 @@ stop_system(SysSup) ->
spawn(fun() -> sshd_sup:stop_child(Name) end),
ok.
-stop_system(Address, Port) ->
- spawn(fun() -> sshd_sup:stop_child(Address, Port) end),
+stop_system(Address, Port, Profile) ->
+ spawn(fun() -> sshd_sup:stop_child(Address, Port, Profile) end),
ok.
-system_supervisor(Address, Port) ->
- Name = make_name(Address, Port),
+system_supervisor(Address, Port, Profile) ->
+ Name = make_name(Address, Port, Profile),
whereis(Name).
subsystem_supervisor(SystemSup) ->
@@ -103,9 +106,9 @@ stop_subsystem(SystemSup, SubSys) ->
end.
-restart_subsystem(Address, Port) ->
- SysSupName = make_name(Address, Port),
- SubSysName = id(ssh_subsystem_sup, Address, Port),
+restart_subsystem(Address, Port, Profile) ->
+ SysSupName = make_name(Address, Port, Profile),
+ SubSysName = id(ssh_subsystem_sup, Address, Port, Profile),
case supervisor:terminate_child(SysSupName, SubSysName) of
ok ->
supervisor:restart_child(SysSupName, SubSysName);
@@ -113,9 +116,9 @@ restart_subsystem(Address, Port) ->
Error
end.
-restart_acceptor(Address, Port) ->
- SysSupName = make_name(Address, Port),
- AcceptorName = id(ssh_acceptor_sup, Address, Port),
+restart_acceptor(Address, Port, Profile) ->
+ SysSupName = make_name(Address, Port, Profile),
+ AcceptorName = id(ssh_acceptor_sup, Address, Port, Profile),
supervisor:restart_child(SysSupName, AcceptorName).
%%%=========================================================================
@@ -137,7 +140,8 @@ child_specs(ServerOpts) ->
ssh_acceptor_child_spec(ServerOpts) ->
Address = proplists:get_value(address, ServerOpts),
Port = proplists:get_value(port, ServerOpts),
- Name = id(ssh_acceptor_sup, Address, Port),
+ Profile = proplists:get_value(profile, proplists:get_value(ssh_opts, ServerOpts), ?DEFAULT_PROFILE),
+ Name = id(ssh_acceptor_sup, Address, Port, Profile),
StartFunc = {ssh_acceptor_sup, start_link, [ServerOpts]},
Restart = transient,
Shutdown = infinity,
@@ -155,12 +159,23 @@ ssh_subsystem_child_spec(ServerOpts) ->
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-id(Sup, Address, Port) ->
- {Sup, Address, Port}.
-
-make_name(Address, Port) ->
- list_to_atom(lists:flatten(io_lib:format("ssh_system_~p_~p_sup",
- [Address, Port]))).
+id(Sup, Address, Port, Profile) ->
+ case is_list(Address) of
+ true ->
+ {Sup, any, Port, Profile};
+ false ->
+ {Sup, Address, Port, Profile}
+ end.
+
+make_name(Address, Port, Profile) ->
+ case is_list(Address) of
+ true ->
+ list_to_atom(lists:flatten(io_lib:format("ssh_system_~p_~p_~p_sup",
+ [any, Port, Profile])));
+ false ->
+ list_to_atom(lists:flatten(io_lib:format("ssh_system_~p_~p_~p_sup",
+ [Address, Port, Profile])))
+ end.
ssh_subsystem_sup([{_, Child, _, [ssh_subsystem_sup]} | _]) ->
Child;
@@ -178,3 +193,4 @@ stop_acceptor(Sup) ->
supervisor:which_children(Sup)],
supervisor:terminate_child(AcceptorSup, Name).
+
diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl
index 60222f5172..e879629ccb 100644
--- a/lib/ssh/src/sshd_sup.erl
+++ b/lib/ssh/src/sshd_sup.erl
@@ -26,8 +26,10 @@
-behaviour(supervisor).
+-include("ssh.hrl").
+
-export([start_link/1, start_child/1, stop_child/1,
- stop_child/2, system_name/1]).
+ stop_child/3, system_name/1]).
%% Supervisor callback
-export([init/1]).
@@ -40,13 +42,14 @@ start_link(Servers) ->
start_child(ServerOpts) ->
Address = proplists:get_value(address, ServerOpts),
- Port = proplists:get_value(port, ServerOpts),
- case ssh_system_sup:system_supervisor(Address, Port) of
+ Port = proplists:get_value(port, ServerOpts),
+ Profile = proplists:get_value(profile, proplists:get_value(ssh_opts, ServerOpts), ?DEFAULT_PROFILE),
+ case ssh_system_sup:system_supervisor(Address, Port, Profile) of
undefined ->
Spec = child_spec(Address, Port, ServerOpts),
case supervisor:start_child(?MODULE, Spec) of
{error, already_present} ->
- Name = id(Address, Port),
+ Name = id(Address, Port, Profile),
supervisor:delete_child(?MODULE, Name),
supervisor:start_child(?MODULE, Spec);
Reply ->
@@ -60,8 +63,8 @@ start_child(ServerOpts) ->
stop_child(Name) ->
supervisor:terminate_child(?MODULE, Name).
-stop_child(Address, Port) ->
- Name = id(Address, Port),
+stop_child(Address, Port, Profile) ->
+ Name = id(Address, Port, Profile),
stop_child(Name).
system_name(SysSup) ->
@@ -87,7 +90,8 @@ init([Servers]) ->
%%% Internal functions
%%%=========================================================================
child_spec(Address, Port, ServerOpts) ->
- Name = id(Address, Port),
+ Profile = proplists:get_value(profile, proplists:get_value(ssh_opts, ServerOpts), ?DEFAULT_PROFILE),
+ Name = id(Address, Port,Profile),
StartFunc = {ssh_system_sup, start_link, [ServerOpts]},
Restart = temporary,
Shutdown = infinity,
@@ -95,8 +99,13 @@ child_spec(Address, Port, ServerOpts) ->
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-id(Address, Port) ->
- {server, ssh_system_sup, Address, Port}.
+id(Address, Port, Profile) ->
+ case is_list(Address) of
+ true ->
+ {server, ssh_system_sup, any, Port, Profile};
+ false ->
+ {server, ssh_system_sup, Address, Port, Profile}
+ end.
system_name([], _ ) ->
undefined;