summaryrefslogtreecommitdiff
path: root/lib/ssh/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/src')
-rw-r--r--lib/ssh/src/ssh.erl59
-rw-r--r--lib/ssh/src/ssh.hrl10
-rw-r--r--lib/ssh/src/ssh_cli.erl177
-rw-r--r--lib/ssh/src/ssh_options.erl2
-rw-r--r--lib/ssh/src/ssh_sftp.erl41
-rw-r--r--lib/ssh/src/ssh_transport.erl19
-rw-r--r--lib/ssh/src/ssh_xfer.erl39
-rw-r--r--lib/ssh/src/ssh_xfer.hrl4
8 files changed, 186 insertions, 165 deletions
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 28f8e0ac18..c93b796078 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -477,33 +477,12 @@ stop_daemon(Address, Port, Profile) ->
%% and will not return until the remote shell is ended.(e.g. on
%% exit from the shell)
%%--------------------------------------------------------------------
--spec shell(open_socket() | host()) -> _.
+-spec shell(open_socket() | host() | connection_ref()) -> _.
shell(Socket) when is_port(Socket) ->
shell(Socket, []);
-shell(Host) ->
- shell(Host, ?SSH_DEFAULT_PORT, []).
-
-
--spec shell(open_socket() | host(), client_options()) -> _.
-
-shell(Socket, Options) when is_port(Socket) ->
- start_shell( connect(Socket, Options) );
-shell(Host, Options) ->
- shell(Host, ?SSH_DEFAULT_PORT, Options).
-
--spec shell(Host, Port, Options) -> _ when
- Host :: host(),
- Port :: inet:port_number(),
- Options :: client_options() .
-
-shell(Host, Port, Options) ->
- start_shell( connect(Host, Port, Options) ).
-
-
-
-start_shell({ok, ConnectionRef}) ->
+shell(ConnectionRef) when is_pid(ConnectionRef) ->
case ssh_connection:session_channel(ConnectionRef, infinity) of
{ok,ChannelId} ->
success = ssh_connection:ptty_alloc(ConnectionRef, ChannelId, []),
@@ -521,8 +500,38 @@ start_shell({ok, ConnectionRef}) ->
Error
end;
-start_shell(Error) ->
- Error.
+shell(Host) ->
+ shell(Host, ?SSH_DEFAULT_PORT, []).
+
+
+-spec shell(open_socket() | host(), client_options()) -> _.
+
+shell(Socket, Options) when is_port(Socket) ->
+ case connect(Socket, Options) of
+ {ok,ConnectionRef} ->
+ shell(ConnectionRef),
+ close(ConnectionRef);
+ Error ->
+ Error
+ end;
+
+shell(Host, Options) ->
+ shell(Host, ?SSH_DEFAULT_PORT, Options).
+
+
+-spec shell(Host, Port, Options) -> _ when
+ Host :: host(),
+ Port :: inet:port_number(),
+ Options :: client_options() .
+
+shell(Host, Port, Options) ->
+ case connect(Host, Port, Options) of
+ {ok,ConnectionRef} ->
+ shell(ConnectionRef),
+ close(ConnectionRef);
+ Error ->
+ Error
+ end.
%%--------------------------------------------------------------------
-spec default_algorithms() -> algs_list() .
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index a991f72cf2..86c447f695 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -163,6 +163,8 @@
'aes128-ctr' |
'aes128-gcm@openssh.com' |
'aes192-ctr' |
+ 'aes192-cbc' |
+ 'aes256-cbc' |
'aes256-ctr' |
'aes256-gcm@openssh.com' |
'chacha20-poly1305@openssh.com'
@@ -171,6 +173,7 @@
-type mac_alg() :: 'AEAD_AES_128_GCM' |
'AEAD_AES_256_GCM' |
'hmac-sha1' |
+ 'hmac-sha1-96' |
'hmac-sha2-256' |
'hmac-sha2-512'
.
@@ -315,17 +318,20 @@
-type subsystem_daemon_option() :: {subsystems, subsystem_specs()}.
-type subsystem_specs() :: [ subsystem_spec() ].
--type shell_daemon_option() :: {shell, mod_fun_args() | 'shell_fun/1'() | 'shell_fun/2'() }.
+-type shell_daemon_option() :: {shell, shell_spec()} .
+-type shell_spec() :: mod_fun_args() | shell_fun() | disabled .
+-type shell_fun() :: 'shell_fun/1'() | 'shell_fun/2'() .
-type 'shell_fun/1'() :: fun((User::string()) -> pid()) .
-type 'shell_fun/2'() :: fun((User::string(), PeerAddr::inet:ip_address()) -> pid()).
-type exec_daemon_option() :: {exec, exec_spec()} .
--type exec_spec() :: {direct, exec_fun()} .
+-type exec_spec() :: {direct, exec_fun()} | disabled | deprecated_exec_opt().
-type exec_fun() :: 'exec_fun/1'() | 'exec_fun/2'() | 'exec_fun/3'().
-type 'exec_fun/1'() :: fun((Cmd::string()) -> exec_result()) .
-type 'exec_fun/2'() :: fun((Cmd::string(), User::string()) -> exec_result()) .
-type 'exec_fun/3'() :: fun((Cmd::string(), User::string(), ClientAddr::ip_port()) -> exec_result()) .
-type exec_result() :: {ok,Result::term()} | {error,Reason::term()} .
+-type deprecated_exec_opt() :: fun() | mod_fun_args() .
-type ssh_cli_daemon_option() :: {ssh_cli, mod_args() | no_cli }.
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index af51356355..7f04fcb804 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -46,6 +46,8 @@
exec
}).
+-define(EXEC_ERROR_STATUS, 255).
+
%%====================================================================
%% ssh_server_channel callbacks
%%====================================================================
@@ -105,6 +107,12 @@ handle_ssh_msg({ssh_cm, ConnectionHandler,
write_chars(ConnectionHandler, ChannelId, Chars),
{ok, State#state{pty = Pty, buf = NewBuf}};
+handle_ssh_msg({ssh_cm, ConnectionHandler, {shell, ChannelId, WantReply}}, #state{shell=disabled} = State) ->
+ write_chars(ConnectionHandler, ChannelId, 1, "Prohibited."),
+ ssh_connection:reply_request(ConnectionHandler, WantReply, success, ChannelId),
+ ssh_connection:exit_status(ConnectionHandler, ChannelId, ?EXEC_ERROR_STATUS),
+ ssh_connection:send_eof(ConnectionHandler, ChannelId),
+ {stop, ChannelId, State#state{channel = ChannelId, cm = ConnectionHandler}};
handle_ssh_msg({ssh_cm, ConnectionHandler, {shell, ChannelId, WantReply}}, State) ->
NewState = start_shell(ConnectionHandler, State),
ssh_connection:reply_request(ConnectionHandler, WantReply, success, ChannelId),
@@ -114,22 +122,28 @@ handle_ssh_msg({ssh_cm, ConnectionHandler, {shell, ChannelId, WantReply}}, Stat
handle_ssh_msg({ssh_cm, ConnectionHandler, {exec, ChannelId, WantReply, Cmd}}, S0) ->
case
case S0#state.exec of
+ disabled ->
+ {"Prohibited.", ?EXEC_ERROR_STATUS, 1};
+
{direct,F} ->
%% Exec called and a Fun or MFA is defined to use. The F returns the
%% value to return.
- exec_direct(ConnectionHandler, F, Cmd);
+ %% The standard I/O is directed from/to the channel ChannelId.
+ exec_direct(ConnectionHandler, ChannelId, Cmd, F, WantReply, S0);
- undefined when S0#state.shell == ?DEFAULT_SHELL ->
+ undefined when S0#state.shell == ?DEFAULT_SHELL ;
+ S0#state.shell == disabled ->
%% Exec called and the shell is the default shell (= Erlang shell).
%% To be exact, eval the term as an Erlang term (but not using the
%% ?DEFAULT_SHELL directly). This disables banner, prompts and such.
- exec_in_erlang_default_shell(Cmd);
+ %% The standard I/O is directed from/to the channel ChannelId.
+ exec_in_erlang_default_shell(ConnectionHandler, ChannelId, Cmd, WantReply, S0);
undefined ->
%% Exec called, but the a shell other than the default shell is defined.
%% No new exec shell is defined, so don't execute!
%% We don't know if it is intended to use the new shell or not.
- {"Prohibited.", 255, 1};
+ {"Prohibited.", ?EXEC_ERROR_STATUS, 1};
_ ->
%% Exec called and a Fun or MFA is defined to use. The F communicates via
@@ -216,14 +230,9 @@ handle_msg({Group, Req}, #state{group = Group, buf = Buf, pty = Pty,
write_chars(ConnectionHandler, ChannelId, Chars),
{ok, State#state{buf = NewBuf}};
-handle_msg({'EXIT', Group, Reason}, #state{group = Group,
+handle_msg({'EXIT', Group, _Reason}, #state{group = Group,
cm = ConnectionHandler,
channel = ChannelId} = State) ->
- Status = case Reason of
- normal -> 0;
- _ -> -1
- end,
- ssh_connection:exit_status(ConnectionHandler, ChannelId, Status),
ssh_connection:send_eof(ConnectionHandler, ChannelId),
{stop, ChannelId, State};
@@ -357,7 +366,7 @@ insert_chars([], {Buf, BufTail, Col}, _Tty) ->
insert_chars(Chars, {Buf, BufTail, Col}, Tty) ->
{NewBuf, _NewBufTail, WriteBuf, NewCol} =
conv_buf(Chars, Buf, [], [], Col),
- M = move_cursor(NewCol + length(BufTail), NewCol, Tty),
+ M = move_cursor(special_at_width(NewCol+length(BufTail), Tty), NewCol, Tty),
{[WriteBuf, BufTail | M], {NewBuf, BufTail, NewCol}}.
%%% delete characters at current position, (backwards if negative argument)
@@ -372,7 +381,7 @@ delete_chars(N, {Buf, BufTail, Col}, Tty) -> % N < 0
NewBuf = nthtail(-N, Buf),
NewCol = case Col + N of V when V >= 0 -> V; _ -> 0 end,
M1 = move_cursor(Col, NewCol, Tty),
- M2 = move_cursor(NewCol + length(BufTail) - N, NewCol, Tty),
+ M2 = move_cursor(special_at_width(NewCol+length(BufTail)-N, Tty), NewCol, Tty),
{[M1, BufTail, lists:duplicate(-N, $ ) | M2],
{NewBuf, BufTail, NewCol}}.
@@ -429,6 +438,10 @@ move_cursor(From, To, #ssh_pty{width=Width, term=Type}) ->
end,
[Tcol | Trow].
+%%% Caution for line "breaks"
+special_at_width(From0, #ssh_pty{width=Width}) when (From0 rem Width) == 0 -> From0 - 1;
+special_at_width(From0, _) -> From0.
+
%% %%% write out characters
%% %%% make sure that there is data to send
%% %%% before calling ssh_connection:send
@@ -518,86 +531,94 @@ start_exec_shell(ConnectionHandler, Cmd, State) ->
buf = empty_buf()}.
%%--------------------------------------------------------------------
-exec_in_erlang_default_shell(Cmd) ->
- case eval(parse(scan(Cmd))) of
- {ok, Term} ->
- {io_lib:format("~p\n", [Term]), 0, 0};
- {error, Error} when is_atom(Error) ->
- {io_lib:format("Error in ~p: ~p\n", [Cmd,Error]), -1, 1};
- _ ->
- {io_lib:format("Error: ~p\n", [Cmd]), -1, 1}
- end.
+exec_in_erlang_default_shell(ConnectionHandler, ChannelId, Cmd, WantReply, State) ->
+ exec_in_self_group(ConnectionHandler, ChannelId, WantReply, State,
+ fun() ->
+ eval(parse(scan(Cmd)))
+ end).
+
scan(Cmd) ->
erl_scan:string(Cmd).
parse({ok, Tokens, _}) ->
erl_parse:parse_exprs(Tokens);
-parse(Error) ->
- Error.
+parse({error, {_,erl_scan,Cause}, _}) ->
+ {error, erl_scan:format_error(Cause)}.
eval({ok, Expr_list}) ->
- case (catch erl_eval:exprs(Expr_list,
- erl_eval:new_bindings())) of
- {value, Value, _NewBindings} ->
- {ok, Value};
- {'EXIT', {Error, _}} ->
- {error, Error};
- {error, Error} ->
- {error, Error};
- Error ->
- {error, Error}
- end;
+ {value, Value, _NewBindings} = erl_eval:exprs(Expr_list, erl_eval:new_bindings()),
+ {ok, Value};
+eval({error, {_,erl_parse,Cause}}) ->
+ {error, erl_parse:format_error(Cause)};
eval({error,Error}) ->
- {error, Error};
-eval(Error) ->
{error, Error}.
%%--------------------------------------------------------------------
-exec_direct(ConnectionHandler, ExecSpec, Cmd) ->
- try
- case ExecSpec of
- _ when is_function(ExecSpec, 1) ->
- ExecSpec(Cmd);
- _ when is_function(ExecSpec, 2) ->
- [{user,User}] = ssh_connection_handler:connection_info(ConnectionHandler, [user]),
- ExecSpec(Cmd, User);
- _ when is_function(ExecSpec, 3) ->
- ConnectionInfo =
- ssh_connection_handler:connection_info(ConnectionHandler, [peer, user]),
- User = proplists:get_value(user, ConnectionInfo),
- {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
- ExecSpec(Cmd, User, PeerAddr)
- end
- of
- Reply ->
- return_direct_exec_reply(Reply, Cmd)
- catch
- C:Error ->
- {io_lib:format("Error in \"~s\": ~p ~p~n", [Cmd,C,Error]), -1, 1}
- end.
-
-
+exec_direct(ConnectionHandler, ChannelId, Cmd, ExecSpec, WantReply, State) ->
+ Fun =
+ fun() ->
+ if
+ is_function(ExecSpec, 1) ->
+ ExecSpec(Cmd);
+
+ is_function(ExecSpec, 2) ->
+ [{user,User}] = ssh_connection_handler:connection_info(ConnectionHandler, [user]),
+ ExecSpec(Cmd, User);
+
+ is_function(ExecSpec, 3) ->
+ ConnectionInfo =
+ ssh_connection_handler:connection_info(ConnectionHandler, [peer, user]),
+ User = proplists:get_value(user, ConnectionInfo),
+ {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
+ ExecSpec(Cmd, User, PeerAddr);
+
+ true ->
+ {error, "Bad exec fun in server"}
+ end
+ end,
+ exec_in_self_group(ConnectionHandler, ChannelId, WantReply, State, Fun).
-return_direct_exec_reply(Reply, Cmd) ->
- case fmt_exec_repl(Reply) of
- {ok,S} ->
- {S, 0, 0};
- {error,S} ->
- {io_lib:format("Error in \"~s\": ~s~n", [Cmd,S]), -1, 1}
- end.
+%%--------------------------------------------------------------------
+%% Help for directing stdin and stdout from and to the channel from/to the client
+%%
+exec_in_self_group(ConnectionHandler, ChannelId, WantReply, State, Fun) ->
+ Exec =
+ fun() ->
+ spawn(
+ fun() ->
+ case try
+ ssh_connection:reply_request(ConnectionHandler, WantReply, success, ChannelId),
+ Fun()
+ of
+ {ok, Result} ->
+ {ok, Result};
+ {error, Error} ->
+ {error, Error};
+ X ->
+ {error, "Bad exec fun in server. Invalid return value: "++t2str(X)}
+ catch error:Err ->
+ {error,Err};
+ Cls:Exp ->
+ {error,{Cls,Exp}}
+ end
+ of
+ {ok,Str} ->
+ write_chars(ConnectionHandler, ChannelId, t2str(Str)),
+ ssh_connection:exit_status(ConnectionHandler, ChannelId, 0);
+ {error, Str} ->
+ write_chars(ConnectionHandler, ChannelId, 1, "**Error** "++t2str(Str)),
+ ssh_connection:exit_status(ConnectionHandler, ChannelId, ?EXEC_ERROR_STATUS)
+ end
+ end)
+ end,
+ {ok, State#state{group = group:start(self(), Exec, [{echo,false}]),
+ buf = empty_buf()}}.
+
-fmt_exec_repl({T,A}) when T==ok ; T==error ->
- try
- {T, io_lib:format("~s",[A])}
- catch
- error:badarg ->
- {T, io_lib:format("~p", [A])};
- C:Err ->
- {error, io_lib:format("~p:~p~n",[C,Err])}
- end;
-fmt_exec_repl(Other) ->
- {error, io_lib:format("Bad exec-plugin return: ~p",[Other])}.
+t2str(T) -> try io_lib:format("~s",[T])
+ catch _:_ -> io_lib:format("~p",[T])
+ end.
%%--------------------------------------------------------------------
% Pty can be undefined if the client never sets any pty options before
diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl
index 39f23a8b8a..e2a18edc0d 100644
--- a/lib/ssh/src/ssh_options.erl
+++ b/lib/ssh/src/ssh_options.erl
@@ -306,6 +306,7 @@ default(server) ->
shell =>
#{default => ?DEFAULT_SHELL,
chk => fun({M,F,A}) -> is_atom(M) andalso is_atom(F) andalso is_list(A);
+ (disabled) -> true;
(V) -> check_function1(V) orelse check_function2(V)
end,
class => user_option
@@ -314,6 +315,7 @@ default(server) ->
exec =>
#{default => undefined,
chk => fun({direct, V}) -> check_function1(V) orelse check_function2(V) orelse check_function3(V);
+ (disabled) -> true;
%% Compatibility (undocumented):
({M,F,A}) -> is_atom(M) andalso is_atom(F) andalso is_list(A);
(V) -> check_function1(V) orelse check_function2(V) orelse check_function3(V)
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index 4b6e187c3a..28df85dfa4 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -160,8 +160,10 @@ start_channel(Socket, UserOptions) when is_port(Socket) ->
start_channel(Cm, UserOptions) when is_pid(Cm) ->
Timeout = proplists:get_value(timeout, UserOptions, infinity),
{_SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions),
- case ssh_xfer:attach(Cm, [], ChanOpts) of
- {ok, ChannelId, Cm} ->
+ WindowSize = proplists:get_value(window_size, ChanOpts, ?XFER_WINDOW_SIZE),
+ PacketSize = proplists:get_value(packet_size, ChanOpts, ?XFER_PACKET_SIZE),
+ case ssh_connection:session_channel(Cm, WindowSize, PacketSize, Timeout) of
+ {ok, ChannelId} ->
case ssh_client_channel:start(Cm, ChannelId,
?MODULE, [Cm, ChannelId, SftpOpts]) of
{ok, Pid} ->
@@ -194,25 +196,24 @@ start_channel(Host, UserOptions) ->
-> {ok,pid(),ssh:connection_ref()} | {error,reason()}.
start_channel(Host, Port, UserOptions) ->
- {SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions),
+ {SshOpts, _ChanOpts, _SftpOpts} = handle_options(UserOptions),
Timeout = % A mixture of ssh:connect and ssh_sftp:start_channel:
- proplists:get_value(connect_timeout, SshOpts,
- proplists:get_value(timeout, SftpOpts, infinity)),
- case ssh_xfer:connect(Host, Port, SshOpts, ChanOpts, Timeout) of
- {ok, ChannelId, Cm} ->
- case ssh_client_channel:start(Cm, ChannelId, ?MODULE, [Cm,ChannelId,SftpOpts]) of
- {ok, Pid} ->
- case wait_for_version_negotiation(Pid, Timeout) of
- ok ->
- {ok, Pid, Cm};
- TimeOut ->
- TimeOut
- end;
- {error, Reason} ->
- {error, format_channel_start_error(Reason)};
- ignore ->
- {error, ignore}
- end;
+ case proplists:get_value(connect_timeout, UserOptions) of
+ undefined ->
+ proplists:get_value(timeout, UserOptions, infinity);
+ TO ->
+ TO
+ end,
+ case ssh:connect(Host, Port, SshOpts, Timeout) of
+ {ok, Cm} ->
+ case start_channel(Cm, UserOptions) of
+ {ok, Pid} ->
+ {ok, Pid, Cm};
+ Error ->
+ Error
+ end;
+ {error, Timeout} ->
+ {error, timeout};
Error ->
Error
end.
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index a85926354e..d1a3d513d1 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -108,7 +108,9 @@ default_algorithms(cipher) ->
]));
default_algorithms(mac) ->
supported_algorithms(mac, same(['AEAD_AES_128_GCM',
- 'AEAD_AES_256_GCM']));
+ 'AEAD_AES_256_GCM',
+ 'hmac-sha1-96'
+ ]));
default_algorithms(Alg) ->
supported_algorithms(Alg, []).
@@ -161,6 +163,8 @@ supported_algorithms(cipher) ->
{'aes128-ctr', [{ciphers,aes_128_ctr}]},
{'AEAD_AES_256_GCM', [{ciphers,aes_256_gcm}]},
{'AEAD_AES_128_GCM', [{ciphers,aes_128_gcm}]},
+ {'aes256-cbc', [{ciphers,aes_256_cbc}]},
+ {'aes192-cbc', [{ciphers,aes_192_cbc}]},
{'aes128-cbc', [{ciphers,aes_128_cbc}]},
{'3des-cbc', [{ciphers,des_ede3_cbc}]}
]
@@ -171,6 +175,7 @@ supported_algorithms(mac) ->
[{'hmac-sha2-256', [{macs,hmac}, {hashs,sha256}]},
{'hmac-sha2-512', [{macs,hmac}, {hashs,sha512}]},
{'hmac-sha1', [{macs,hmac}, {hashs,sha}]},
+ {'hmac-sha1-96', [{macs,hmac}, {hashs,sha}]},
{'AEAD_AES_128_GCM', [{ciphers,aes_128_gcm}]},
{'AEAD_AES_256_GCM', [{ciphers,aes_256_gcm}]}
]
@@ -1345,6 +1350,18 @@ cipher('aes128-cbc') ->
iv_bytes = 16,
block_bytes = 16};
+cipher('aes192-cbc') ->
+ #cipher{impl = aes_192_cbc,
+ key_bytes = 24,
+ iv_bytes = 16,
+ block_bytes = 16};
+
+cipher('aes256-cbc') ->
+ #cipher{impl = aes_256_cbc,
+ key_bytes = 32,
+ iv_bytes = 16,
+ block_bytes = 16};
+
cipher('aes128-ctr') ->
#cipher{impl = aes_128_ctr,
key_bytes = 16,
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index 1d77ccb311..b071b38be2 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -24,7 +24,6 @@
-module(ssh_xfer).
--export([attach/2, attach/3, connect/3, connect/4, connect/5]).
-export([open/6, opendir/3, readdir/3, close/3, read/5, write/5,
rename/5, remove/3, mkdir/4, rmdir/3, realpath/3, extended/4,
stat/4, fstat/4, lstat/4, setstat/4,
@@ -47,44 +46,6 @@
-define(is_set(F, Bits),
((F) band (Bits)) == (F)).
--define(XFER_PACKET_SIZE, 65536).
--define(XFER_WINDOW_SIZE, 20*?XFER_PACKET_SIZE).
-
-attach(CM, Opts) ->
- open_xfer(CM, Opts, []).
-
-attach(CM, Opts, ChanOpts) ->
- open_xfer(CM, Opts, ChanOpts).
-
-
-connect(Host, Port, Opts) ->
- case ssh:connect(Host, Port, Opts) of
- {ok, CM} -> open_xfer(CM, Opts, []);
- Error -> Error
- end.
-
-connect(Host, Port, Opts, Timeout) ->
- connect(Host, Port, Opts, [], Timeout).
-
-connect(Host, Port, Opts, ChanOpts, Timeout) ->
- case ssh:connect(Host, Port, Opts, Timeout) of
- {ok, CM} -> open_xfer(CM, [{timeout, Timeout}|Opts], ChanOpts);
- {error, Timeout} -> {error, timeout};
- Error -> Error
- end.
-
-
-open_xfer(CM, Opts, ChanOpts) ->
- TMO = proplists:get_value(timeout, Opts, infinity),
- WindowSize = proplists:get_value(window_size, ChanOpts, ?XFER_WINDOW_SIZE),
- PacketSize = proplists:get_value(packet_size, ChanOpts, ?XFER_PACKET_SIZE),
- case ssh_connection:session_channel(CM, WindowSize, PacketSize, TMO) of
- {ok, ChannelId} ->
- {ok, ChannelId, CM};
- Error ->
- Error
- end.
-
protocol_version_request(XF, Version) ->
xf_request(XF, ?SSH_FXP_INIT, <<?UINT32(Version)>>).
diff --git a/lib/ssh/src/ssh_xfer.hrl b/lib/ssh/src/ssh_xfer.hrl
index a76e9151db..aaf2c16d10 100644
--- a/lib/ssh/src/ssh_xfer.hrl
+++ b/lib/ssh/src/ssh_xfer.hrl
@@ -20,6 +20,10 @@
%%
+
+-define(XFER_PACKET_SIZE, 65536).
+-define(XFER_WINDOW_SIZE, 20*?XFER_PACKET_SIZE).
+
%%% Description: SFTP defines
-define(SSH_SFTP_PROTOCOL_VERSION, 6).
%%%----------------------------------------------------------------------