diff options
Diffstat (limited to 'lib/ssh/src')
-rw-r--r-- | lib/ssh/src/ssh.hrl | 25 | ||||
-rw-r--r-- | lib/ssh/src/ssh_dbg.erl | 116 | ||||
-rw-r--r-- | lib/ssh/src/ssh_transport.erl | 31 |
3 files changed, 152 insertions, 20 deletions
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 9631427749..01c44cb371 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -492,4 +492,29 @@ -define(wr_record(N), ?wr_record(N, [])). +%% Circular trace buffer macros + +-record(circ_buf_entry, + { + module, + line, + function, + pid = self(), + value + }). + +-define(CIRC_BUF_IN(VALUE), + ssh_dbg:cbuf_in( + #circ_buf_entry{module = ?MODULE, + line = ?LINE, + function = {?FUNCTION_NAME,?FUNCTION_ARITY}, + pid = self(), + value = (VALUE) + }) + ). + +-define(CIRC_BUF_IN_ONCE(VALUE), + ((fun(V) -> ?CIRC_BUF_IN(V), V end)(VALUE)) + ). + -endif. % SSH_HRL defined diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl index b53c09b17d..4fe15b24d3 100644 --- a/lib/ssh/src/ssh_dbg.erl +++ b/lib/ssh/src/ssh_dbg.erl @@ -54,7 +54,13 @@ start_tracer/0, start_tracer/1, on/1, on/0, off/1, off/0, - go_on/0 + go_on/0, + %% Circular buffer + cbuf_start/0, cbuf_start/1, + cbuf_stop_clear/0, + cbuf_in/1, + cbuf_list/0, + fmt_cbuf_items/0, fmt_cbuf_item/1 ]). -export([shrink_bin/1, @@ -71,6 +77,8 @@ -behaviour(gen_server). -define(SERVER, ?MODULE). +-define(CALL_TIMEOUT, 15000). % 3x the default + %%%================================================================ -define(ALL_DBG_TYPES, get_all_dbg_types()). @@ -107,7 +115,7 @@ start_tracer(WriteFun) when is_function(WriteFun,3) -> start_tracer(WriteFun, InitAcc) when is_function(WriteFun, 3) -> Handler = fun(Arg, Acc0) -> - try_all_types_in_all_modules(gen_server:call(?SERVER, get_on), + try_all_types_in_all_modules(gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT), Arg, WriteFun, Acc0) end, @@ -122,7 +130,7 @@ off() -> off(?ALL_DBG_TYPES). % A bit overkill... off(Type) -> switch(off, Type). go_on() -> - IsOn = gen_server:call(?SERVER, get_on), + IsOn = gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT), on(IsOn). %%%---------------------------------------------------------------- @@ -253,7 +261,7 @@ switch(X, Types) when is_list(Types) -> end, case lists:usort(Types) -- ?ALL_DBG_TYPES of [] -> - gen_server:call(?SERVER, {switch,X,Types}); + gen_server:call(?SERVER, {switch,X,Types}, ?CALL_TIMEOUT); L -> {error, {unknown, L}} end. @@ -331,3 +339,103 @@ ts({_,_,Usec}=Now) when is_integer(Usec) -> io_lib:format("~.2.0w:~.2.0w:~.2.0w.~.6.0w",[HH,MM,SS,Usec]); ts(_) -> "-". + +%%%================================================================ +-define(CIRC_BUF, circ_buf). + +cbuf_start() -> + cbuf_start(20). + +cbuf_start(CbufMaxLen) -> + put(?CIRC_BUF, {CbufMaxLen,queue:new()}), + ok. + + +cbuf_stop_clear() -> + case erase(?CIRC_BUF) of + undefined -> + []; + {_CbufMaxLen,Queue} -> + queue:to_list(Queue) + end. + + +cbuf_in(Value) -> + case get(?CIRC_BUF) of + undefined -> + disabled; + {CbufMaxLen,Queue} -> + UpdatedQueue = + try queue:head(Queue) of + {Value, TS0, Cnt0} -> + %% Same Value as last saved in the queue + queue:in_r({Value, TS0, Cnt0+1}, + queue:drop(Queue) + ); + _ -> + queue:in_r({Value, erlang:timestamp(), 1}, + truncate_cbuf(Queue, CbufMaxLen) + ) + catch + error:empty -> + queue:in_r({Value, erlang:timestamp(), 1}, Queue) + end, + put(?CIRC_BUF, {CbufMaxLen,UpdatedQueue}), + ok + end. + + +cbuf_list() -> + case get(?CIRC_BUF) of + undefined -> + []; + {_CbufMaxLen,Queue} -> + queue:to_list(Queue) + end. + + +truncate_cbuf(Q, CbufMaxLen) -> + case queue:len(Q) of + N when N>=CbufMaxLen -> + truncate_cbuf(element(2,queue:out_r(Q)), CbufMaxLen); + _ -> + Q + end. + +fmt_cbuf_items() -> + lists:flatten( + io_lib:format("Circular trace buffer. Latest item first.~n~s~n", + [case get(?CIRC_BUF) of + {Max,_} -> + L = cbuf_list(), + [io_lib:format("==== ~.*w: ~s~n",[num_digits(Max),N,fmt_cbuf_item(X)]) || + {N,X} <- lists:zip(lists:seq(1,length(L)), L) + ]; + _ -> + io_lib:format("Not started.~n",[]) + end])). + + +num_digits(0) -> 1; +num_digits(N) when N>0 -> 1+trunc(math:log10(N)). + + +fmt_cbuf_item({Value, TimeStamp, N}) -> + io_lib:format("~s~s~n~s~n", + [fmt_ts(TimeStamp), + [io_lib:format(" (Repeated ~p times)",[N]) || N>1], + fmt_value(Value)]). + + +fmt_ts(TS = {_,_,Us}) -> + {{YY,MM,DD},{H,M,S}} = calendar:now_to_universal_time(TS), + io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~.6.0w UTC",[YY,MM,DD,H,M,S,Us]). + +fmt_value(#circ_buf_entry{module = M, + line = L, + function = {F,A}, + pid = Pid, + value = V}) -> + io_lib:format("~p:~p ~p/~p ~p~n~s",[M,L,F,A,Pid,fmt_value(V)]); +fmt_value(Value) -> + io_lib:format("~p",[Value]). diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 9ec16b420d..b6d7aa0b1b 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -128,9 +128,9 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()]. supported_algorithms(kex) -> select_crypto_supported( [ - {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]}, - {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]}, - {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]}, + {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {curves,secp384r1}, {hashs,sha384}]}, + {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {curves,secp521r1}, {hashs,sha512}]}, + {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {curves,secp256r1}, {hashs,sha256}]}, %% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves %% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448 {'curve25519-sha256', [{public_keys,eddh}, {curves,x25519}, {hashs,sha256}]}, @@ -147,9 +147,9 @@ supported_algorithms(kex) -> supported_algorithms(public_key) -> select_crypto_supported( [ - {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]}, - {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]}, - {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]}, + {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {curves,secp384r1}]}, + {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {curves,secp521r1}]}, + {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {curves,secp256r1}]}, {'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]}, {'rsa-sha2-256', [{public_keys,rsa}, {hashs,sha256} ]}, {'rsa-sha2-512', [{public_keys,rsa}, {hashs,sha512} ]}, @@ -174,9 +174,9 @@ supported_algorithms(cipher) -> supported_algorithms(mac) -> same( select_crypto_supported( - [{'hmac-sha2-256', [{hashs,sha256}]}, - {'hmac-sha2-512', [{hashs,sha512}]}, - {'hmac-sha1', [{hashs,sha}]}, + [{'hmac-sha2-256', [{macs,hmac}, {hashs,sha256}]}, + {'hmac-sha2-512', [{macs,hmac}, {hashs,sha512}]}, + {'hmac-sha1', [{macs,hmac}, {hashs,sha}]}, {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]}, {'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]} ] @@ -1978,15 +1978,10 @@ supported_algorithms(Key, BlackList) -> select_crypto_supported(L) -> - Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()], + Sup = crypto:supports(), [Name || {Name,CryptoRequires} <- L, crypto_supported(CryptoRequires, Sup)]. -crypto_supported_curves() -> - try crypto:ec_curves() - catch _:_ -> [] - end. - crypto_supported(Conditions, Supported) -> lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) -> crypto_name_supported(Tag,CryptoName,Supported); @@ -1996,7 +1991,11 @@ crypto_supported(Conditions, Supported) -> end, Conditions). crypto_name_supported(Tag, CryptoName, Supported) -> - lists:member(CryptoName, proplists:get_value(Tag,Supported,[])). + Vs = case proplists:get_value(Tag,Supported,[]) of + [] when Tag == curves -> crypto:ec_curves(); + L -> L + end, + lists:member(CryptoName, Vs). len_supported(Name, Len) -> try |