From owner-svn-ports-all@FreeBSD.ORG Sun Apr 12 10:11:38 2015 Return-Path: Delivered-To: svn-ports-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 17D50C3C; Sun, 12 Apr 2015 10:11:38 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 01777B82; Sun, 12 Apr 2015 10:11:38 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t3CABbls002946; Sun, 12 Apr 2015 10:11:37 GMT (envelope-from olgeni@FreeBSD.org) Received: (from olgeni@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t3CABaaH002941; Sun, 12 Apr 2015 10:11:36 GMT (envelope-from olgeni@FreeBSD.org) Message-Id: <201504121011.t3CABaaH002941@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: olgeni set sender to olgeni@FreeBSD.org using -f From: Jimmy Olgeni Date: Sun, 12 Apr 2015 10:11:36 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r383850 - in head/lang/erlang: . files X-SVN-Group: ports-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the ports tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 12 Apr 2015 10:11:38 -0000 Author: olgeni Date: Sun Apr 12 10:11:35 2015 New Revision: 383850 URL: https://svnweb.freebsd.org/changeset/ports/383850 Log: Upgrade to version 17.5.1. Added: head/lang/erlang/files/patch-otp-17.5.1 (contents, props changed) Deleted: head/lang/erlang/files/patch-otp-17.4.1 Modified: head/lang/erlang/Makefile head/lang/erlang/distinfo Modified: head/lang/erlang/Makefile ============================================================================== --- head/lang/erlang/Makefile Sun Apr 12 09:57:39 2015 (r383849) +++ head/lang/erlang/Makefile Sun Apr 12 10:11:35 2015 (r383850) @@ -2,7 +2,7 @@ # $FreeBSD$ PORTNAME= erlang -PORTVERSION= 17.4.1 +PORTVERSION= 17.5.1 PORTEPOCH= 3 CATEGORIES= lang parallel java MASTER_SITES= http://www.erlang.org/download/:erlangorg \ @@ -18,8 +18,6 @@ DISTFILES= ${DISTNAME}${EXTRACT_SUFX}:er DIST_SUBDIR= erlang EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX} -PATCH_SITES= http://www.erlang.org/download - MAINTAINER= olgeni@FreeBSD.org COMMENT= Functional programming language from Ericsson @@ -47,7 +45,7 @@ DTRACE_DESC= Enable DTrace support OPTIONS_DEFAULT=KQUEUE OPENSSL SCTP SMP THREADS OPTIONS_EXCLUDE_DragonFly= SCTP -ERL_RELEASE= 17.4 +ERL_RELEASE= 17.5 USES= gmake perl5 USE_AUTOTOOLS= autoconf:env @@ -57,7 +55,7 @@ GNU_CONFIGURE= yes LDFLAGS+= -L${LOCALBASE}/lib EI_VSN= 3.7.20 -TOOLS_VSN= 2.7.1 +TOOLS_VSN= 2.7.2 .include @@ -209,13 +207,9 @@ post-install: ${TAR} --unlink -xzpf ${DISTDIR}/${DIST_SUBDIR}/${ERLANG_DOCS} \ -C ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB} - ${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/inets-5.10.4/* \ - ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/inets-5.10.5 - ${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/inets-5.10.4 - - ${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/erts-6.3/* \ - ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/erts-6.3.1 - ${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/erts-6.3 + ${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/ssh-3.2/* \ + ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/ssh-3.2.1 + ${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/ssh-3.2 ${INSTALL_DATA} ${WRKSRC}/lib/dialyzer/doc/*.txt \ ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/dialyzer-*/doc/ Modified: head/lang/erlang/distinfo ============================================================================== --- head/lang/erlang/distinfo Sun Apr 12 09:57:39 2015 (r383849) +++ head/lang/erlang/distinfo Sun Apr 12 10:11:35 2015 (r383850) @@ -1,9 +1,9 @@ -SHA256 (erlang/otp_src_17.4.tar.gz) = 0d82eda6ae7ac6f0f860093324e540fa514497068ec3b4177800284e8c761f56 -SIZE (erlang/otp_src_17.4.tar.gz) = 67171182 -SHA256 (erlang/otp_doc_man_17.4.tar.gz) = 6c1cdb8e9d367c7b6dc6b20706de9fd0a0f0b7dffd66532663b2a24ed7679a58 -SIZE (erlang/otp_doc_man_17.4.tar.gz) = 1360952 -SHA256 (erlang/otp_doc_html_17.4.tar.gz) = dd42b0104418de18e2247608a337bcd3bb24c59bbc36294deb5fae73ab6c90d6 -SIZE (erlang/otp_doc_html_17.4.tar.gz) = 33483554 +SHA256 (erlang/otp_src_17.5.tar.gz) = 3c28820c981b30c50df8ac2a4a238e5813454fa3ed2ad530bc7948a282846474 +SIZE (erlang/otp_src_17.5.tar.gz) = 67242289 +SHA256 (erlang/otp_doc_man_17.5.tar.gz) = 85b1b2a1011fc01af550f1fe9e5a599a4c5f2a35d264d2804af1d05590a857c3 +SIZE (erlang/otp_doc_man_17.5.tar.gz) = 1363320 +SHA256 (erlang/otp_doc_html_17.5.tar.gz) = baba1d373c1faacf4a1a6ec1220d57d0cb2b977edb74f32cd58dc786361c6cf5 +SIZE (erlang/otp_doc_html_17.5.tar.gz) = 33510258 SHA256 (erlang/armstrong_thesis_2003.pdf) = da585b914eb07350e2d6f727db5eb0fb1551f49fc1270f7d4dc079f2c8c1ab7a SIZE (erlang/armstrong_thesis_2003.pdf) = 859249 SHA256 (erlang/bjarnelic.pdf) = 9544d4af5cea324e5c9cf77e670d9561ad61ddc240cdb5c2afecebc0a3d7429b Added: head/lang/erlang/files/patch-otp-17.5.1 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/lang/erlang/files/patch-otp-17.5.1 Sun Apr 12 10:11:35 2015 (r383850) @@ -0,0 +1,826 @@ +diff --git OTP_VERSION OTP_VERSION +index 6060b96..9cbaf23 100644 +--- OTP_VERSION ++++ OTP_VERSION +@@ -1 +1 @@ +-17.5 ++17.5.1 +diff --git lib/ssh/doc/src/notes.xml lib/ssh/doc/src/notes.xml +index f22bca3..acbf312 100644 +--- lib/ssh/doc/src/notes.xml ++++ lib/ssh/doc/src/notes.xml +@@ -29,6 +29,28 @@ + notes.xml + + ++
Ssh 3.2.1 ++ ++
Fixed Bugs and Malfunctions ++ ++ ++

++ Ssh crashed if a message was sent on a channel with ++ packet_size = 0.

++

++ A new option for ssh:daemon is also introduced: ++ minimal_remote_max_packet_size. This option sets ++ the least max packet size declaration that the daemon ++ will accept from a client. The default value is 0 to ++ maintain compatibility with OpenSSH and the rfc:s.

++

++ Own Id: OTP-12645 Aux Id: seq12816

++
++
++
++ ++
++ +
Ssh 3.2 + +
Fixed Bugs and Malfunctions +diff --git lib/ssh/doc/src/ssh.xml lib/ssh/doc/src/ssh.xml +index d481a75..0e7e384 100644 +--- lib/ssh/doc/src/ssh.xml ++++ lib/ssh/doc/src/ssh.xml +@@ -338,6 +338,12 @@ + + + ++ ++ ++

The least maximum packet size that the daemon will accept in channel open requests from the client. The default value is 0. ++

++
++ + + +

Module implementing the behaviour ssh_server_key_api. +diff --git lib/ssh/src/ssh.appup.src lib/ssh/src/ssh.appup.src +index b2b2994..e76c110 100644 +--- lib/ssh/src/ssh.appup.src ++++ lib/ssh/src/ssh.appup.src +@@ -1,7 +1,7 @@ + %% -*- erlang -*- + %% %CopyrightBegin% + %% +-%% Copyright Ericsson AB 2004-2014. All Rights Reserved. ++%% Copyright Ericsson AB 2004-2015. All Rights Reserved. + %% + %% The contents of this file are subject to the Erlang Public License, + %% Version 1.1, (the "License"); you may not use this file except in +@@ -19,61 +19,9 @@ + + {"%VSN%", + [ +- {"3.0.8", [{load_module, ssh_connection, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_sftp, soft_purge, soft_purge, [ssh_xfer]}, +- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, +- {load_module, ssh, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_xfer, soft_purge, soft_purge, []} +- ]}, +- {"3.0.7", [{load_module, ssh_auth, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_acceptor, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_channel, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, +- {load_module, ssh_info, soft_purge, soft_purge, []}, +- {load_module, ssh_message, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_io, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_sftp, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_xfer, soft_purge, soft_purge, [ssh_connection_handler]}]}, +- {"3.0.6", [{load_module, ssh_auth, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_acceptor, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_channel, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, +- {load_module, ssh_info, soft_purge, soft_purge, []}, +- {load_module, ssh_message, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_io, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_sftp, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_xfer, soft_purge, soft_purge, [ssh_connection_handler]}]}, + {<<".*">>, [{restart_application, ssh}]} + ], + [ +- {"3.0.8", [{load_module, ssh_connection, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_sftp, soft_purge, soft_purge, []}, +- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, +- {load_module, ssh, soft_purge, soft_purge, []}, +- {load_module, ssh_xfer, soft_purge, soft_purge, []} +- ]}, +- {"3.0.7", [{load_module, ssh_auth, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_acceptor, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_channel, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, +- {load_module, ssh_info, soft_purge, soft_purge, []}, +- {load_module, ssh_message, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_io, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_sftp, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_xfer, soft_purge, soft_purge, [ssh_connection_handler]}]}, +- {"3.0.6", [{load_module, ssh_auth, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_acceptor, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_channel, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}, +- {load_module, ssh_info, soft_purge, soft_purge, []}, +- {load_module, ssh_message, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_io, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_sftp, soft_purge, soft_purge, [ssh_connection_handler]}, +- {load_module, ssh_xfer, soft_purge, soft_purge, [ssh_connection_handler]}]}, + {<<".*">>, [{restart_application, ssh}]} + ] + }. +diff --git lib/ssh/src/ssh.erl lib/ssh/src/ssh.erl +index eae33e3..51ad691 100644 +--- lib/ssh/src/ssh.erl ++++ lib/ssh/src/ssh.erl +@@ -345,9 +345,14 @@ handle_option([{parallel_login, _} = Opt|Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); + handle_option([parallel_login|Rest], SocketOptions, SshOptions) -> + handle_option(Rest, SocketOptions, [handle_ssh_option({parallel_login,true}) | SshOptions]); ++handle_option([{minimal_remote_max_packet_size, _} = 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). + ++ ++handle_ssh_option({minimal_remote_max_packet_size, Value} = Opt) when is_integer(Value), Value >=0 -> ++ Opt; + handle_ssh_option({system_dir, Value} = Opt) when is_list(Value) -> + Opt; + handle_ssh_option({user_dir, Value} = Opt) when is_list(Value) -> +diff --git lib/ssh/src/ssh_acceptor.erl lib/ssh/src/ssh_acceptor.erl +index 6c443ee..34988f1 100644 +--- lib/ssh/src/ssh_acceptor.erl ++++ lib/ssh/src/ssh_acceptor.erl +@@ -1,7 +1,7 @@ + %% + %% %CopyrightBegin% + %% +-%% Copyright Ericsson AB 2008-2013. All Rights Reserved. ++%% Copyright Ericsson AB 2008-2015. All Rights Reserved. + %% + %% The contents of this file are subject to the Erlang Public License, + %% Version 1.1, (the "License"); you may not use this file except in +@@ -43,7 +43,7 @@ start_link(Port, Address, SockOpts, Opts, AcceptTimeout) -> + acceptor_init(Parent, Port, Address, SockOpts, Opts, AcceptTimeout) -> + {_, Callback, _} = + proplists:get_value(transport, Opts, {tcp, gen_tcp, tcp_closed}), +- case (catch do_socket_listen(Callback, Port, SockOpts)) of ++ case (catch do_socket_listen(Callback, Port, [{active, false} | SockOpts])) of + {ok, ListenSocket} -> + proc_lib:init_ack(Parent, {ok, self()}), + acceptor_loop(Callback, +diff --git lib/ssh/src/ssh_connection.erl lib/ssh/src/ssh_connection.erl +index c66f810..654b9d4 100644 +--- lib/ssh/src/ssh_connection.erl ++++ lib/ssh/src/ssh_connection.erl +@@ -1,7 +1,7 @@ + %% + %% %CopyrightBegin% + %% +-%% Copyright Ericsson AB 2008-2014. All Rights Reserved. ++%% Copyright Ericsson AB 2008-2015. All Rights Reserved. + %% + %% The contents of this file are subject to the Erlang Public License, + %% Version 1.1, (the "License"); you may not use this file except in +@@ -326,9 +326,7 @@ channel_data(ChannelId, DataType, Data, + SendDataType, + SendData)} + end, SendList), +- FlowCtrlMsgs = flow_control(Replies, +- Channel, +- Cache), ++ FlowCtrlMsgs = flow_control(Replies, Channel, Cache), + {{replies, Replies ++ FlowCtrlMsgs}, Connection}; + _ -> + gen_fsm:reply(From, {error, closed}), +@@ -470,18 +468,31 @@ handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId, + handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type, + sender_channel = RemoteId, + initial_window_size = WindowSz, +- maximum_packet_size = PacketSz}, Connection0, server) -> +- +- try setup_session(Connection0, RemoteId, +- Type, WindowSz, PacketSz) of +- Result -> +- Result +- catch _:_ -> ++ maximum_packet_size = PacketSz}, ++ #connection{options = SSHopts} = Connection0, ++ server) -> ++ MinAcceptedPackSz = proplists:get_value(minimal_remote_max_packet_size, SSHopts, 0), ++ ++ if ++ MinAcceptedPackSz =< PacketSz -> ++ try setup_session(Connection0, RemoteId, ++ Type, WindowSz, PacketSz) of ++ Result -> ++ Result ++ catch _:_ -> ++ FailMsg = channel_open_failure_msg(RemoteId, ++ ?SSH_OPEN_CONNECT_FAILED, ++ "Connection refused", "en"), ++ {{replies, [{connection_reply, FailMsg}]}, ++ Connection0} ++ end; ++ ++ MinAcceptedPackSz > PacketSz -> + FailMsg = channel_open_failure_msg(RemoteId, +- ?SSH_OPEN_CONNECT_FAILED, +- "Connection refused", "en"), +- {{replies, [{connection_reply, FailMsg}]}, +- Connection0} ++ ?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, ++ lists:concat(["Maximum packet size below ",MinAcceptedPackSz, ++ " not supported"]), "en"), ++ {{replies, [{connection_reply, FailMsg}]}, Connection0} + end; + + handle_msg(#ssh_msg_channel_open{channel_type = "session", +@@ -501,41 +512,57 @@ handle_msg(#ssh_msg_channel_open{channel_type = "forwarded-tcpip" = Type, + initial_window_size = RWindowSz, + maximum_packet_size = RPacketSz, + data = Data}, +- #connection{channel_cache = Cache} = Connection0, server) -> ++ #connection{channel_cache = Cache, ++ options = SSHopts} = Connection0, server) -> + <> = Data, + +- case bound_channel(Address, Port, Connection0) of +- undefined -> ++ MinAcceptedPackSz = proplists:get_value(minimal_remote_max_packet_size, SSHopts, 0), ++ ++ if ++ MinAcceptedPackSz =< RPacketSz -> ++ case bound_channel(Address, Port, Connection0) of ++ undefined -> ++ FailMsg = channel_open_failure_msg(RemoteId, ++ ?SSH_OPEN_CONNECT_FAILED, ++ "Connection refused", "en"), ++ {{replies, ++ [{connection_reply, FailMsg}]}, Connection0}; ++ ChannelPid -> ++ {ChannelId, Connection1} = new_channel_id(Connection0), ++ LWindowSz = ?DEFAULT_WINDOW_SIZE, ++ LPacketSz = ?DEFAULT_PACKET_SIZE, ++ Channel = #channel{type = Type, ++ sys = "none", ++ user = ChannelPid, ++ local_id = ChannelId, ++ recv_window_size = LWindowSz, ++ recv_packet_size = LPacketSz, ++ send_window_size = RWindowSz, ++ send_packet_size = RPacketSz, ++ send_buf = queue:new() ++ }, ++ ssh_channel:cache_update(Cache, Channel), ++ OpenConfMsg = channel_open_confirmation_msg(RemoteId, ChannelId, ++ LWindowSz, LPacketSz), ++ {OpenMsg, Connection} = ++ reply_msg(Channel, Connection1, ++ {open, Channel, {forwarded_tcpip, ++ decode_ip(Address), Port, ++ decode_ip(Orig), OrigPort}}), ++ {{replies, [{connection_reply, OpenConfMsg}, ++ OpenMsg]}, Connection} ++ end; ++ ++ MinAcceptedPackSz > RPacketSz -> + FailMsg = channel_open_failure_msg(RemoteId, +- ?SSH_OPEN_CONNECT_FAILED, +- "Connection refused", "en"), +- {{replies, +- [{connection_reply, FailMsg}]}, Connection0}; +- ChannelPid -> +- {ChannelId, Connection1} = new_channel_id(Connection0), +- LWindowSz = ?DEFAULT_WINDOW_SIZE, +- LPacketSz = ?DEFAULT_PACKET_SIZE, +- Channel = #channel{type = Type, +- sys = "none", +- user = ChannelPid, +- local_id = ChannelId, +- recv_window_size = LWindowSz, +- recv_packet_size = LPacketSz, +- send_window_size = RWindowSz, +- send_packet_size = RPacketSz}, +- ssh_channel:cache_update(Cache, Channel), +- OpenConfMsg = channel_open_confirmation_msg(RemoteId, ChannelId, +- LWindowSz, LPacketSz), +- {OpenMsg, Connection} = +- reply_msg(Channel, Connection1, +- {open, Channel, {forwarded_tcpip, +- decode_ip(Address), Port, +- decode_ip(Orig), OrigPort}}), +- {{replies, [{connection_reply, OpenConfMsg}, +- OpenMsg]}, Connection} ++ ?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, ++ lists:concat(["Maximum packet size below ",MinAcceptedPackSz, ++ " not supported"]), "en"), ++ {{replies, [{connection_reply, FailMsg}]}, Connection0} + end; + ++ + handle_msg(#ssh_msg_channel_open{channel_type = "forwarded-tcpip", + sender_channel = RemoteId}, + Connection, client) -> +@@ -917,7 +944,8 @@ start_channel(Cb, Id, Args, SubSysSup, Exec) -> + %%-------------------------------------------------------------------- + %%% Internal functions + %%-------------------------------------------------------------------- +-setup_session(#connection{channel_cache = Cache} = Connection0, ++setup_session(#connection{channel_cache = Cache ++ } = Connection0, + RemoteId, + Type, WindowSize, PacketSize) -> + {ChannelId, Connection} = new_channel_id(Connection0), +@@ -929,6 +957,7 @@ setup_session(#connection{channel_cache = Cache} = Connection0, + recv_packet_size = ?DEFAULT_PACKET_SIZE, + send_window_size = WindowSize, + send_packet_size = PacketSize, ++ send_buf = queue:new(), + remote_id = RemoteId + }, + ssh_channel:cache_update(Cache, Channel), +@@ -1024,63 +1053,74 @@ request_reply_or_data(#channel{local_id = ChannelId, user = ChannelPid}, + + update_send_window(Channel, _, undefined, + #connection{channel_cache = Cache}) -> +- do_update_send_window(Channel, Channel#channel.send_buf, Cache); ++ do_update_send_window(Channel, Cache); + +-update_send_window(Channel, DataType, Data, ++update_send_window(#channel{send_buf = SendBuffer} = Channel, DataType, Data, + #connection{channel_cache = Cache}) -> +- do_update_send_window(Channel, Channel#channel.send_buf ++ [{DataType, Data}], Cache). ++ do_update_send_window(Channel#channel{send_buf = queue:in({DataType, Data}, SendBuffer)}, ++ Cache). + +-do_update_send_window(Channel0, Buf0, Cache) -> +- {Buf1, NewSz, Buf2} = get_window(Buf0, +- Channel0#channel.send_packet_size, +- Channel0#channel.send_window_size), +- +- Channel = Channel0#channel{send_window_size = NewSz, send_buf = Buf2}, ++do_update_send_window(Channel0, Cache) -> ++ {SendMsgs, Channel} = get_window(Channel0, []), + ssh_channel:cache_update(Cache, Channel), +- {Buf1, Channel}. ++ {SendMsgs, Channel}. + +-get_window(Bs, PSz, WSz) -> +- get_window(Bs, PSz, WSz, []). +- +-get_window(Bs, _PSz, 0, Acc) -> +- {lists:reverse(Acc), 0, Bs}; +-get_window([B0 = {DataType, Bin} | Bs], PSz, WSz, Acc) -> +- BSz = size(Bin), +- if BSz =< WSz -> %% will fit into window +- if BSz =< PSz -> %% will fit into a packet +- get_window(Bs, PSz, WSz-BSz, [B0|Acc]); +- true -> %% split into packet size +- <> = Bin, +- get_window([setelement(2, B0, Bin2) | Bs], +- PSz, WSz-PSz, +- [{DataType, Bin1}|Acc]) ++get_window(#channel{send_window_size = 0 ++ } = Channel, Acc) -> ++ {lists:reverse(Acc), Channel}; ++get_window(#channel{send_packet_size = 0 ++ } = Channel, Acc) -> ++ {lists:reverse(Acc), Channel}; ++get_window(#channel{send_buf = Buffer, ++ send_packet_size = PacketSize, ++ send_window_size = WindowSize0 ++ } = Channel, Acc0) -> ++ case queue:out(Buffer) of ++ {{value, {_, Data} = Msg}, NewBuffer} -> ++ case handle_send_window(Msg, size(Data), PacketSize, WindowSize0, Acc0) of ++ {WindowSize, Acc, {_, <<>>}} -> ++ {lists:reverse(Acc), Channel#channel{send_window_size = WindowSize, ++ send_buf = NewBuffer}}; ++ {WindowSize, Acc, Rest} -> ++ get_window(Channel#channel{send_window_size = WindowSize, ++ send_buf = queue:in_r(Rest, NewBuffer)}, Acc) + end; +- WSz =< PSz -> %% use rest of window +- <> = Bin, +- get_window([setelement(2, B0, Bin2) | Bs], +- PSz, WSz-WSz, +- [{DataType, Bin1}|Acc]); +- true -> %% use packet size +- <> = Bin, +- get_window([setelement(2, B0, Bin2) | Bs], +- PSz, WSz-PSz, +- [{DataType, Bin1}|Acc]) ++ {empty, NewBuffer} -> ++ {[], Channel#channel{send_buf = NewBuffer}} ++ end. ++ ++handle_send_window(Msg = {Type, Data}, Size, PacketSize, WindowSize, Acc) when Size =< WindowSize -> ++ case Size =< PacketSize of ++ true -> ++ {WindowSize - Size, [Msg | Acc], {Type, <<>>}}; ++ false -> ++ <> = Data, ++ {WindowSize - PacketSize, [{Type, Msg1} | Acc], {Type, Msg2}} + end; +-get_window([], _PSz, WSz, Acc) -> +- {lists:reverse(Acc), WSz, []}. ++handle_send_window({Type, Data}, _, PacketSize, WindowSize, Acc) when WindowSize =< PacketSize -> ++ <> = Data, ++ {WindowSize - WindowSize, [{Type, Msg1} | Acc], {Type, Msg2}}; ++handle_send_window({Type, Data}, _, PacketSize, WindowSize, Acc) -> ++ <> = Data, ++ {WindowSize - PacketSize, [{Type, Msg1} | Acc], {Type, Msg2}}. + + flow_control(Channel, Cache) -> + flow_control([window_adjusted], Channel, Cache). +- ++ + flow_control([], Channel, Cache) -> + ssh_channel:cache_update(Cache, Channel), + []; +- + flow_control([_|_], #channel{flow_control = From, +- send_buf = []} = Channel, Cache) when From =/= undefined -> +- [{flow_control, Cache, Channel, From, ok}]; ++ send_buf = Buffer} = Channel, Cache) when From =/= undefined -> ++ case queue:is_empty(Buffer) of ++ true -> ++ ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}), ++ [{flow_control, Cache, Channel, From, ok}]; ++ false -> ++ [] ++ end; + flow_control(_,_,_) -> +- []. ++ []. + + pty_req(ConnectionHandler, Channel, Term, Width, Height, + PixWidth, PixHeight, PtyOpts, TimeOut) -> +diff --git lib/ssh/src/ssh_connection_handler.erl lib/ssh/src/ssh_connection_handler.erl +index 68523aa..e1f2e05 100644 +--- lib/ssh/src/ssh_connection_handler.erl ++++ lib/ssh/src/ssh_connection_handler.erl +@@ -1,7 +1,7 @@ + %% + %% %CopyrightBegin% + %% +-%% Copyright Ericsson AB 2008-2014. All Rights Reserved. ++%% Copyright Ericsson AB 2008-2015. All Rights Reserved. + %% + %% The contents of this file are subject to the Erlang Public License, + %% Version 1.1, (the "License"); you may not use this file except in +@@ -751,7 +751,9 @@ handle_sync_event({open, ChannelPid, Type, InitialWindowSize, MaxPacketSize, Dat + user = ChannelPid, + local_id = ChannelId, + recv_window_size = InitialWindowSize, +- recv_packet_size = MaxPacketSize}, ++ recv_packet_size = MaxPacketSize, ++ send_buf = queue:new() ++ }, + ssh_channel:cache_update(Cache, Channel), + State = add_request(true, ChannelId, From, State2), + start_timeout(ChannelId, From, Timeout), +@@ -1241,10 +1243,9 @@ event(Event, StateName, State) -> + handle_disconnect(DisconnectMsg, State); + throw:{ErrorToDisplay, #ssh_msg_disconnect{} = DisconnectMsg} -> + handle_disconnect(DisconnectMsg, State, ErrorToDisplay); +- _:Error -> +- log_error(Error), ++ _:_ -> + handle_disconnect(#ssh_msg_disconnect{code = error_code(StateName), +- description = "Internal error", ++ description = "Invalid state", + language = "en"}, State) + end. + error_code(key_exchange) -> +diff --git lib/ssh/src/ssh_info.erl lib/ssh/src/ssh_info.erl +index 9a91875..30df32c 100644 +--- lib/ssh/src/ssh_info.erl ++++ lib/ssh/src/ssh_info.erl +@@ -27,18 +27,21 @@ + -compile(export_all). + + print() -> ++ print(user). ++ ++print(D) -> + try supervisor:which_children(ssh_sup) + of + _ -> +- io:nl(), +- print_general(), +- io:nl(), +- underline("Client part", $=), +- print_clients(), +- io:nl(), +- underline("Server part", $=), +- print_servers(), +- io:nl(), ++ io:nl(D), ++ print_general(D), ++ io:nl(D), ++ underline(D, "Client part", $=), ++ print_clients(D), ++ io:nl(D), ++ underline(D, "Server part", $=), ++ print_servers(D), ++ io:nl(D), + %% case os:type() of + %% {unix,_} -> + %% io:nl(), +@@ -50,90 +53,95 @@ print() -> + %% catch io:format(os:cmd("netstat -tpn")); + %% _ -> ok + %% end, +- underline("Supervisors", $=), +- walk_sups(ssh_sup), +- io:nl() ++ underline(D, "Supervisors", $=), ++ walk_sups(D, ssh_sup), ++ io:nl(D) + catch + _:_ -> +- io:format("Ssh not found~n",[]) ++ io:format(D,"Ssh not found~n",[]) + end. + + %%%================================================================ +-print_general() -> ++print_general(D) -> + {_Name, Slogan, Ver} = lists:keyfind(ssh,1,application:which_applications()), +- underline(io_lib:format("~s ~s", [Slogan, Ver]), $=), +- io:format('This printout is generated ~s. ~n',[datetime()]). ++ underline(D, io_lib:format("~s ~s", [Slogan, Ver]), $=), ++ io:format(D, 'This printout is generated ~s. ~n',[datetime()]). + + %%%================================================================ +-print_clients() -> ++print_clients(D) -> ++ PrintClient = fun(X) -> print_client(D,X) end, + try +- lists:foreach(fun print_client/1, supervisor:which_children(sshc_sup)) ++ lists:foreach(PrintClient, supervisor:which_children(sshc_sup)) + catch + C:E -> +- io:format('***FAILED: ~p:~p~n',[C,E]) ++ io:format(D, '***FAILED: ~p:~p~n',[C,E]) + end. + +-print_client({undefined,Pid,supervisor,[ssh_connection_handler]}) -> ++print_client(D, {undefined,Pid,supervisor,[ssh_connection_handler]}) -> + {{Local,Remote},_Str} = ssh_connection_handler:get_print_info(Pid), +- io:format(" Local=~s Remote=~s~n",[fmt_host_port(Local),fmt_host_port(Remote)]); +-print_client(Other) -> +- io:format(" [[Other 1: ~p]]~n",[Other]). ++ io:format(D, " Local=~s Remote=~s~n",[fmt_host_port(Local),fmt_host_port(Remote)]); ++print_client(D, Other) -> ++ io:format(D, " [[Other 1: ~p]]~n",[Other]). + + + %%%================================================================ +-print_servers() -> ++print_servers(D) -> ++ PrintServer = fun(X) -> print_server(D,X) end, + try +- lists:foreach(fun print_server/1, supervisor:which_children(sshd_sup)) ++ lists:foreach(PrintServer, supervisor:which_children(sshd_sup)) + catch + C:E -> +- io:format('***FAILED: ~p:~p~n',[C,E]) ++ io:format(D, '***FAILED: ~p:~p~n',[C,E]) + end. + +-print_server({{server,ssh_system_sup,LocalHost,LocalPort},Pid,supervisor,[ssh_system_sup]}) when is_pid(Pid) -> +- io:format('Local=~s (~p children)~n',[fmt_host_port({LocalHost,LocalPort}), +- ssh_acceptor:number_of_connections(Pid)]), +- lists:foreach(fun print_system_sup/1, supervisor:which_children(Pid)); +-print_server(Other) -> +- io:format(" [[Other 2: ~p]]~n",[Other]). ++print_server(D, {{server,ssh_system_sup,LocalHost,LocalPort},Pid,supervisor,[ssh_system_sup]}) when is_pid(Pid) -> ++ io:format(D, 'Local=~s (~p children)~n',[fmt_host_port({LocalHost,LocalPort}), ++ ssh_acceptor:number_of_connections(Pid)]), ++ PrintSystemSup = fun(X) -> print_system_sup(D,X) end, ++ lists:foreach(PrintSystemSup, supervisor:which_children(Pid)); ++print_server(D, Other) -> ++ io:format(D, " [[Other 2: ~p]]~n",[Other]). + +-print_system_sup({Ref,Pid,supervisor,[ssh_subsystem_sup]}) when is_reference(Ref), ++print_system_sup(D, {Ref,Pid,supervisor,[ssh_subsystem_sup]}) when is_reference(Ref), + is_pid(Pid) -> +- lists:foreach(fun print_channels/1, supervisor:which_children(Pid)); +-print_system_sup({{ssh_acceptor_sup,LocalHost,LocalPort}, Pid,supervisor, [ssh_acceptor_sup]}) when is_pid(Pid) -> +- io:format(" [Acceptor for ~s]~n",[fmt_host_port({LocalHost,LocalPort})]); +-print_system_sup(Other) -> +- io:format(" [[Other 3: ~p]]~n",[Other]). ++ PrintChannels = fun(X) -> print_channels(D,X) end, ++ lists:foreach(PrintChannels, supervisor:which_children(Pid)); ++print_system_sup(D, {{ssh_acceptor_sup,LocalHost,LocalPort}, Pid,supervisor, [ssh_acceptor_sup]}) when is_pid(Pid) -> ++ io:format(D, " [Acceptor for ~s]~n",[fmt_host_port({LocalHost,LocalPort})]); ++print_system_sup(D, Other) -> ++ io:format(D, " [[Other 3: ~p]]~n",[Other]). + +-print_channels({{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) -> +- lists:foreach(fun print_channel/1, supervisor:which_children(Pid)); +-print_channels(Other) -> +- io:format(" [[Other 4: ~p]]~n",[Other]). ++print_channels(D, {{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) -> ++ PrintChannel = fun(X) -> print_channel(D,X) end, ++ lists:foreach(PrintChannel, supervisor:which_children(Pid)); ++print_channels(D, Other) -> ++ io:format(D, " [[Other 4: ~p]]~n",[Other]). + + +-print_channel({Ref,Pid,worker,[ssh_channel]}) when is_reference(Ref), +- is_pid(Pid) -> ++print_channel(D, {Ref,Pid,worker,[ssh_channel]}) when is_reference(Ref), ++ is_pid(Pid) -> + {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid), + {{Local,Remote},StrM} = ssh_connection_handler:get_print_info(ConnManager), +- io:format(' ch ~p: ~s ~s',[ChannelID, StrM, Str]), +- io:format(" Local=~s Remote=~s~n",[fmt_host_port(Local),fmt_host_port(Remote)]); +-print_channel(Other) -> +- io:format(" [[Other 5: ~p]]~n",[Other]). ++ io:format(D, ' ch ~p: ~s ~s',[ChannelID, StrM, Str]), ++ io:format(D, " Local=~s Remote=~s~n",[fmt_host_port(Local),fmt_host_port(Remote)]); ++print_channel(D, Other) -> ++ io:format(D, " [[Other 5: ~p]]~n",[Other]). + + %%%================================================================ + -define(inc(N), (N+4)). + +-walk_sups(StartPid) -> +- io:format("Start at ~p, ~s.~n",[StartPid,dead_or_alive(StartPid)]), +- walk_sups(children(StartPid), _Indent=?inc(0)). ++walk_sups(D, StartPid) -> ++ io:format(D, "Start at ~p, ~s.~n",[StartPid,dead_or_alive(StartPid)]), ++ walk_sups(D, children(StartPid), _Indent=?inc(0)). + +-walk_sups([H={_,Pid,SupOrWorker,_}|T], Indent) -> +- indent(Indent), io:format('~200p ~p is ~s~n',[H,Pid,dead_or_alive(Pid)]), ++walk_sups(D, [H={_,Pid,SupOrWorker,_}|T], Indent) -> ++ indent(D, Indent), io:format(D, '~200p ~p is ~s~n',[H,Pid,dead_or_alive(Pid)]), + case SupOrWorker of +- supervisor -> walk_sups(children(Pid), ?inc(Indent)); ++ supervisor -> walk_sups(D, children(Pid), ?inc(Indent)); + _ -> ok + end, +- walk_sups(T, Indent); +-walk_sups([], _) -> ++ walk_sups(D, T, Indent); ++walk_sups(_D, [], _) -> + ok. + + dead_or_alive(Name) when is_atom(Name) -> +@@ -149,7 +157,7 @@ dead_or_alive(Pid) when is_pid(Pid) -> + _ -> "alive" + end. + +-indent(I) -> io:format('~*c',[I,$ ]). ++indent(D, I) -> io:format(D,'~*c',[I,$ ]). + + children(Pid) -> + Parent = self(), +@@ -166,16 +174,16 @@ children(Pid) -> + end. + + %%%================================================================ +-underline(Str) -> +- underline(Str, $-). ++underline(D, Str) -> ++ underline(D, Str, $-). + +-underline(Str, LineChar) -> ++underline(D, Str, LineChar) -> + Len = lists:flatlength(Str), +- io:format('~s~n',[Str]), +- line(Len,LineChar). ++ io:format(D, '~s~n',[Str]), ++ line(D,Len,LineChar). + +-line(Len, Char) -> +- io:format('~*c~n', [Len,Char]). ++line(D, Len, Char) -> ++ io:format(D, '~*c~n', [Len,Char]). + + + datetime() -> +@@ -188,6 +196,6 @@ fmt_host_port({Host,Port}) -> io_lib:format('~s:~p',[Host,Port]). + + + +-nyi() -> +- io:format('Not yet implemented~n',[]), ++nyi(D) -> ++ io:format(D,'Not yet implemented~n',[]), + nyi. +diff --git lib/ssh/test/ssh_basic_SUITE.erl lib/ssh/test/ssh_basic_SUITE.erl +index 45c0303..81c7b5c 100644 +--- lib/ssh/test/ssh_basic_SUITE.erl ++++ lib/ssh/test/ssh_basic_SUITE.erl +@@ -50,6 +50,8 @@ all() -> + double_close, + ssh_connect_timeout, + ssh_connect_arg4_timeout, ++ packet_size_zero, ++ ssh_daemon_minimal_remote_max_packet_size_option, + {group, hardening_tests} + ]. + +@@ -757,6 +759,64 @@ ms_passed(N1={_,_,M1}, N2={_,_,M2}) -> + 1000 * (Min*60 + Sec + (M2-M1)/1000000). + + %%-------------------------------------------------------------------- ++packet_size_zero(Config) -> ++ SystemDir = ?config(data_dir, Config), ++ PrivDir = ?config(priv_dir, Config), ++ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth ++ file:make_dir(UserDir), ++ ++ {Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, ++ {user_dir, UserDir}, ++ {user_passwords, [{"vego", "morot"}]}]), ++ Conn = ++ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, ++ {user_dir, UserDir}, ++ {user_interaction, false}, ++ {user, "vego"}, ++ {password, "morot"}]), ++ ++ {ok,Chan} = ssh_connection:session_channel(Conn, 1000, _MaxPacketSize=0, 60000), ++ ok = ssh_connection:shell(Conn, Chan), ++ ++ ssh:close(Conn), ++ ssh:stop_daemon(Server), ++ ++ receive ++ {ssh_cm,Conn,{data,Chan,_Type,_Msg1}} = M -> ++ ct:pal("Got ~p",[M]), ++ ct:fail(doesnt_obey_max_packet_size_0) ++ after 5000 -> ++ ok ++ end. ++ ++%%-------------------------------------------------------------------- ++ssh_daemon_minimal_remote_max_packet_size_option(Config) -> ++ SystemDir = ?config(data_dir, Config), ++ PrivDir = ?config(priv_dir, Config), ++ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth ++ file:make_dir(UserDir), ++ ++ {Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, ++ {user_dir, UserDir}, ++ {user_passwords, [{"vego", "morot"}]}, ++ {failfun, fun ssh_test_lib:failfun/2}, ++ {minimal_remote_max_packet_size, 14}]), ++ Conn = ++ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, ++ {user_dir, UserDir}, ++ {user_interaction, false}, ++ {user, "vego"}, ++ {password, "morot"}]), ++ ++ %% Try the limits of the minimal_remote_max_packet_size: ++ {ok, _ChannelId} = ssh_connection:session_channel(Conn, 100, 14, infinity), ++ {open_error,_,"Maximum packet size below 14 not supported",_} = ++ ssh_connection:session_channel(Conn, 100, 13, infinity), ++ ++ ssh:close(Conn), ++ ssh:stop_daemon(Server). ++ ++%%-------------------------------------------------------------------- + ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true). + ssh_connect_negtimeout_sequential(Config) -> ssh_connect_negtimeout(Config,false). + +@@ -970,7 +1030,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) -> + + %% Due to timing the error message may or may not be delivered to + %% the "tcp-application" before the socket closed message is recived +-check_error("Internal error") -> ++check_error("Invalid state") -> + ok; + check_error("Connection closed") -> + ok; +diff --git lib/ssh/vsn.mk lib/ssh/vsn.mk +index 0d90278..fec8dac 100644 +--- lib/ssh/vsn.mk ++++ lib/ssh/vsn.mk +@@ -1,5 +1,4 @@ + #-*-makefile-*- ; force emacs to enter makefile-mode + +-SSH_VSN = 3.2 ++SSH_VSN = 3.2.1 + APP_VSN = "ssh-$(SSH_VSN)" +- +diff --git otp_versions.table otp_versions.table +index 64ffd82..a82f535 100644 +--- otp_versions.table ++++ otp_versions.table +@@ -1,3 +1,4 @@ ++OTP-17.5.1 : ssh-3.2.1 # asn1-3.0.4 common_test-1.10 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 diameter-1.9 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 erts-6.4 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.6 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16 sasl-2.4.1 snmp-5.1.1 ssl-6.0 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 : + OTP-17.5 : asn1-3.0.4 common_test-1.10 compiler-5.0.4 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 diameter-1.9 eldap-1.1.1 erts-6.4 hipe-3.11.3 inets-5.10.6 kernel-3.2 mnesia-4.12.5 observer-2.0.4 os_mon-2.3.1 public_key-0.23 runtime_tools-1.8.16 ssh-3.2 ssl-6.0 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8 tools-2.7.2 wx-1.3.3 # cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 edoc-0.7.16 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 ic-4.3.6 jinterface-1.5.12 megaco-3.17.3 odbc-2.10.22 orber-3.7.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 reltool-0.6.6 sasl-2.4.1 snmp-5.1.1 typer-0.9.8 webtool-0.8.10 xmerl-1.3.7 : + OTP-17.4.1 : erts-6.3.1 inets-5.10.5 # asn1-3.0.3 common_test-1.9 compiler-5.0.3 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.4.2 debugger-4.0.2 dialyzer-2.7.3 diameter-1.8 edoc-0.7.16 eldap-1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.2 ic-4.3.6 jinterface-1.5.12 kernel-3.1 megaco-3.17.3 mnesia-4.12.4 observer-2.0.3 odbc-2.10.22 orber-3.7.1 os_mon-2.3 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.22.1 reltool-0.6.6 runtime_tools-1.8.15 sasl-2.4.1 snmp-5.1.1 ssh-3.1 ssl-5.3.8 stdlib-2.3 syntax_tools-1.6.17 test_server-3.7.2 tools-2.7.1 typer-0.9.8 webtool-0.8.10 wx-1.3.2 xmerl-1.3.7 : + OTP-17.4 : asn1-3.0.3 common_test-1.9 compiler-5.0.3 crypto-3.4.2 debugger-4.0.2 dialyzer-2.7.3 diameter-1.8 edoc-0.7.16 eldap-1.1 erl_docgen-0.3.7 erl_interface-3.7.20 erts-6.3 eunit-2.2.9 hipe-3.11.2 inets-5.10.4 jinterface-1.5.12 kernel-3.1 megaco-3.17.3 mnesia-4.12.4 observer-2.0.3 odbc-2.10.22 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 runtime_tools-1.8.15 snmp-5.1.1 ssh-3.1 ssl-5.3.8 stdlib-2.3 syntax_tools-1.6.17 test_server-3.7.2 tools-2.7.1 wx-1.3.2 # cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 et-1.5 gs-1.5.16 ic-4.3.6 orber-3.7.1 os_mon-2.3 ose-1.0.2 public_key-0.22.1 reltool-0.6.6 sasl-2.4.1 typer-0.9.8 webtool-0.8.10 xmerl-1.3.7 :