Compare commits

...
Sign in to create a new pull request.

16 commits

Author SHA1 Message Date
Peter Lemenkov
94ed2172da Fix for doc generation with OpenJDK 1.8.0
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2016-11-09 19:59:54 +03:00
Peter Lemenkov
4627cfdff1 Backports for mnesia, and epmd in ipv6-only env
- Respect -proto_dist switch while connecting to EPMD
- Cherry-picked fix for OTP-13423. Mnesia transactions could hang while
  waiting on a response from a node who had stopped.

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2016-11-09 17:40:36 +03:00
John Eckersberg
6515854c29 Revert "Enable error_logger depth fine tuning" (rhbz#1324922)
This reverts commit 7704629233.
2016-04-07 12:49:59 -04:00
Peter Lemenkov
9f08c84c22 Fixed issue with nodes registration over IPv6
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2016-02-28 11:45:12 +03:00
Peter Lemenkov
db107ef77c Add missing dependency
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2016-02-19 19:01:15 +03:00
Peter Lemenkov
7704629233 Enable error_logger depth fine tuning
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2016-01-27 16:10:13 +03:00
John Eckersberg
52781ec84e fix inet_dist_listen_{min,max} for ipv6
Also add patch for epmd ipv6 support

Resolves: rhbz#1299253
Resolves: rhbz#1299251
2016-01-20 16:14:16 +03:00
Peter Lemenkov
92d16c1e81 Enable crash dump creation during a large distrubution error
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2016-01-11 17:40:03 +03:00
John Eckersberg
686f250c6f Add patch for CVE-2015-2774 - TLS-1.0 POODLE vulnerability (rhbz#1206712) 2015-08-07 11:43:21 -04:00
Peter Lemenkov
961faf17fa Disable SSLv3
Disable SSLv3 (see rhbz #1169375). Also backport useful os:getenv/2 from
master (see https://github.com/erlang/otp/pull/535 )

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2014-12-01 21:39:43 +03:00
Peter Lemenkov
03a198125b Fixed CVE-2014-1693 (backported fix from ver. 17.x.x, see patch no. 17)
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2014-11-17 16:50:28 +03:00
Peter Lemenkov
e73e8a3d3f Trimmed dependency chain
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2014-11-12 09:09:56 +03:00
Peter Lemenkov
2a4618920d Merge branch 'master' into epel7 2014-06-11 13:13:48 +04:00
Peter Lemenkov
a92942722d Merge branch 'master' into epel7 2014-06-06 18:31:24 +04:00
Peter Lemenkov
2dbf73fdba Merge branch 'master' into epel7
Conflicts:
	erlang.spec
2014-06-06 16:51:07 +04:00
Sam Kottler
6f09315364 A few changes to get EPEL7 boostrapped and built 2014-02-07 18:13:30 +01:00
18 changed files with 5612 additions and 120 deletions

View file

@ -17,13 +17,6 @@
%bcond_without doc %bcond_without doc
# No fop for EPEL5, and only for x86/x86_64 in EPEL6, so just disable there too
%if 0%{?el5}%{?el6}
%global use_prebuilt_docs 1
%else
%global use_prebuilt_docs 0
%endif
%ifarch %{arm} %{ix86} x86_64 ppc %{power64} %ifarch %{arm} %{ix86} x86_64 ppc %{power64}
%global __with_hipe 1 %global __with_hipe 1
%endif %endif
@ -32,18 +25,16 @@
Name: erlang Name: erlang
Version: %{upstream_ver} Version: %{upstream_ver}
Release: %{upstream_rel_for_rpm}.7%{?dist} Release: %{upstream_rel_for_rpm}.18%{?dist}
Summary: General-purpose programming language and runtime environment Summary: General-purpose programming language and runtime environment
Group: Development/Languages Group: Development/Languages
License: ERPL License: ERPL
URL: http://www.erlang.org URL: http://www.erlang.org
Source0: http://www.erlang.org/download/otp_src_%{upstream_ver}%{upstream_rel}-1.tar.gz %if 0%{?el7}%{?fedora}
%if %{use_prebuilt_docs} VCS: scm:git:https://github.com/erlang/otp
Source1: http://erlang.org/download/otp_doc_html_%{upstream_ver}%{upstream_rel}-1.tar.gz
Source2: http://erlang.org/download/otp_doc_man_%{upstream_ver}%{upstream_rel}-1.tar.gz
%endif %endif
Source4: http://www.erlang.org/download/otp_src_%{upstream_ver}%{upstream_rel}-1.readme Source0: http://www.erlang.org/download/otp_src_%{upstream_ver}%{upstream_rel}-1.tar.gz
Source5: epmd.service Source5: epmd.service
Source6: epmd.socket Source6: epmd.socket
Source7: epmd@.service Source7: epmd@.service
@ -104,11 +95,56 @@ Patch12: otp-0012-Add-systemd-support-to-epmd.patch
# Fedora specific patch # Fedora specific patch
# Added systemd notify support to EPMD # Added systemd notify support to EPMD
Patch13: otp-0013-Added-systemd-notify-support-to-EPMD.patch Patch13: otp-0013-Added-systemd-notify-support-to-EPMD.patch
# Fedora specific patch
# Install internal hrl files when necessary
Patch14: otp-0014-Install-internal-hrl-files-when-necessary.patch
# Fedora specific patch
# Expose NIF version
Patch15: otp-0015-Expose-NIF-version.patch
# Fedora specific patch
# Split off webtool dependency from tools
Patch16: otp-0016-Split-off-webtool-dependency-from-tools.patch
# Fedora specific patch
# lib/inets/src/ftp/ftp.erl: Check the filenames, usernames,
Patch17: otp-0017-lib-inets-src-ftp-ftp.erl-Check-the-filenames-userna.patch
# Fedora specific patch
# Introduce os:getenv/2
Patch18: otp-0018-Introduce-os-getenv-2.patch
# Fedora specific patch
# Patch removes support for SSLv3 protocol because it is proved
Patch19: otp-0019-Patch-removes-support-for-SSLv3-protocol-because-it-.patch
# Fedora specific patch
# R16B03-1 backport of TLS-1.0 padding check
Patch20: otp-0020-R16B03-1-backport-of-TLS-1.0-padding-check.patch
# Fedora specific patch
# Add patch to crash dump on large distribution
Patch21: otp-0021-Add-patch-to-crash-dump-on-large-distribution.patch
# Fedora specific patch
# kernel: inet6_tcp_dist: reuse inet_tcp_dist code
Patch22: otp-0022-kernel-inet6_tcp_dist-reuse-inet_tcp_dist-code.patch
# Fedora specific patch
# epmd: support IPv6 node registration
Patch23: otp-0023-epmd-support-IPv6-node-registration.patch
# Fedora specific patch
# Remove unused code in error logger handlers
Patch24: otp-0024-Remove-unused-code-in-error-logger-handlers.patch
# Fedora specific patch
# Teach sasl_report to limit crash reports
Patch25: otp-0025-Teach-sasl_report-to-limit-crash-reports.patch
# Fedora specific patch
# Revert "Remove unused code in error logger handlers"
Patch26: otp-0026-Revert-Remove-unused-code-in-error-logger-handlers.patch
# Fedora specific patch
# Respect -proto_dist switch while connection to EPMD
Patch27: otp-0027-Respect-proto_dist-switch-while-connection-to-EPMD.patch
# Fedora specific patch
# mnesia: Send mnesia_down messages to waiting transactions
Patch28: otp-0028-mnesia-Send-mnesia_down-messages-to-waiting-transact.patch
# Fedora specific patch
# Fix a few javadoc errors
Patch29: otp-0029-Fix-a-few-javadoc-errors.patch
# end of autogenerated patch tag list # end of autogenerated patch tag list
# BuildRoot not strictly needed since F10, but keep it for spec file robustness
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
BuildRequires: lksctp-tools-devel BuildRequires: lksctp-tools-devel
BuildRequires: ncurses-devel BuildRequires: ncurses-devel
BuildRequires: openssl-devel BuildRequires: openssl-devel
@ -116,8 +152,7 @@ BuildRequires: zlib-devel
BuildRequires: flex BuildRequires: flex
BuildRequires: m4 BuildRequires: m4
%if %{with doc} %if %{with doc}
%if %{use_prebuilt_docs} # BEWARE. No fop for EPEL5, and only for x86/x86_64 in EPEL6, so we cannot regenerate docs here
%else
BuildRequires: fop BuildRequires: fop
BuildRequires: libxslt BuildRequires: libxslt
@ -126,14 +161,11 @@ BuildRequires: libxslt
BuildRequires: erlang BuildRequires: erlang
%endif %endif
%endif %endif
%endif
%if 0%{?el6}%{?fedora}
BuildRequires: emacs BuildRequires: emacs
BuildRequires: xemacs BuildRequires: xemacs
BuildRequires: emacs-el BuildRequires: emacs-el
BuildRequires: xemacs-packages-extra-el BuildRequires: xemacs-packages-extra-el
%endif
%if 0%{?el7}%{?fedora} %if 0%{?el7}%{?fedora}
# for <systemd/sd-daemon.h> # for <systemd/sd-daemon.h>
@ -144,63 +176,64 @@ Requires(postun):systemd
Requires: systemd Requires: systemd
%endif %endif
Requires: erlang-appmon%{?_isa} = %{version}-%{release} BuildRequires: erlang-rpm-macros
Requires: erlang-asn1%{?_isa} = %{version}-%{release}
Requires: erlang-common_test%{?_isa} = %{version}-%{release}
Requires: erlang-compiler%{?_isa} = %{version}-%{release}
Requires: erlang-cosEvent%{?_isa} = %{version}-%{release}
Requires: erlang-cosEventDomain%{?_isa} = %{version}-%{release}
Requires: erlang-cosFileTransfer%{?_isa} = %{version}-%{release}
Requires: erlang-cosNotification%{?_isa} = %{version}-%{release}
Requires: erlang-cosProperty%{?_isa} = %{version}-%{release}
Requires: erlang-cosTime%{?_isa} = %{version}-%{release}
Requires: erlang-cosTransactions%{?_isa} = %{version}-%{release}
Requires: erlang-crypto%{?_isa} = %{version}-%{release}
Requires: erlang-debugger%{?_isa} = %{version}-%{release}
Requires: erlang-dialyzer%{?_isa} = %{version}-%{release} Requires: %{name}-appmon%{?_isa} = %{version}-%{release}
Requires: erlang-diameter%{?_isa} = %{version}-%{release} Requires: %{name}-asn1%{?_isa} = %{version}-%{release}
Requires: erlang-edoc%{?_isa} = %{version}-%{release} Requires: %{name}-common_test%{?_isa} = %{version}-%{release}
Requires: erlang-eldap%{?_isa} = %{version}-%{release} Requires: %{name}-compiler%{?_isa} = %{version}-%{release}
Requires: erlang-erl_docgen%{?_isa} = %{version}-%{release} Requires: %{name}-cosEvent%{?_isa} = %{version}-%{release}
Requires: erlang-erl_interface%{?_isa} = %{version}-%{release} Requires: %{name}-cosEventDomain%{?_isa} = %{version}-%{release}
Requires: erlang-erts%{?_isa} = %{version}-%{release} Requires: %{name}-cosFileTransfer%{?_isa} = %{version}-%{release}
Requires: erlang-et%{?_isa} = %{version}-%{release} Requires: %{name}-cosNotification%{?_isa} = %{version}-%{release}
Requires: erlang-eunit%{?_isa} = %{version}-%{release} Requires: %{name}-cosProperty%{?_isa} = %{version}-%{release}
Requires: erlang-examples%{?_isa} = %{version}-%{release} Requires: %{name}-cosTime%{?_isa} = %{version}-%{release}
Requires: erlang-gs%{?_isa} = %{version}-%{release} Requires: %{name}-cosTransactions%{?_isa} = %{version}-%{release}
Requires: erlang-hipe%{?_isa} = %{version}-%{release} Requires: %{name}-crypto%{?_isa} = %{version}-%{release}
Requires: erlang-ic%{?_isa} = %{version}-%{release} Requires: %{name}-debugger%{?_isa} = %{version}-%{release}
Requires: erlang-inets%{?_isa} = %{version}-%{release} Requires: %{name}-dialyzer%{?_isa} = %{version}-%{release}
Requires: erlang-jinterface%{?_isa} = %{version}-%{release} Requires: %{name}-diameter%{?_isa} = %{version}-%{release}
Requires: erlang-kernel%{?_isa} = %{version}-%{release} Requires: %{name}-edoc%{?_isa} = %{version}-%{release}
Requires: erlang-megaco%{?_isa} = %{version}-%{release} Requires: %{name}-eldap%{?_isa} = %{version}-%{release}
Requires: erlang-mnesia%{?_isa} = %{version}-%{release} Requires: %{name}-erl_docgen%{?_isa} = %{version}-%{release}
Requires: erlang-observer%{?_isa} = %{version}-%{release} Requires: %{name}-erl_interface%{?_isa} = %{version}-%{release}
Requires: erlang-odbc%{?_isa} = %{version}-%{release} Requires: %{name}-erts%{?_isa} = %{version}-%{release}
Requires: erlang-orber%{?_isa} = %{version}-%{release} Requires: %{name}-et%{?_isa} = %{version}-%{release}
Requires: erlang-os_mon%{?_isa} = %{version}-%{release} Requires: %{name}-eunit%{?_isa} = %{version}-%{release}
Requires: erlang-otp_mibs%{?_isa} = %{version}-%{release} Requires: %{name}-examples%{?_isa} = %{version}-%{release}
Requires: erlang-parsetools%{?_isa} = %{version}-%{release} Requires: %{name}-gs%{?_isa} = %{version}-%{release}
Requires: erlang-percept%{?_isa} = %{version}-%{release} Requires: %{name}-hipe%{?_isa} = %{version}-%{release}
Requires: erlang-pman%{?_isa} = %{version}-%{release} Requires: %{name}-ic%{?_isa} = %{version}-%{release}
Requires: erlang-public_key%{?_isa} = %{version}-%{release} Requires: %{name}-inets%{?_isa} = %{version}-%{release}
Requires: erlang-reltool%{?_isa} = %{version}-%{release} Requires: %{name}-jinterface%{?_isa} = %{version}-%{release}
Requires: erlang-runtime_tools%{?_isa} = %{version}-%{release} Requires: %{name}-kernel%{?_isa} = %{version}-%{release}
Requires: erlang-sasl%{?_isa} = %{version}-%{release} Requires: %{name}-megaco%{?_isa} = %{version}-%{release}
Requires: erlang-snmp%{?_isa} = %{version}-%{release} Requires: %{name}-mnesia%{?_isa} = %{version}-%{release}
Requires: erlang-ssh%{?_isa} = %{version}-%{release} Requires: %{name}-observer%{?_isa} = %{version}-%{release}
Requires: erlang-ssl%{?_isa} = %{version}-%{release} Requires: %{name}-odbc%{?_isa} = %{version}-%{release}
Requires: erlang-stdlib%{?_isa} = %{version}-%{release} Requires: %{name}-orber%{?_isa} = %{version}-%{release}
Requires: erlang-syntax_tools%{?_isa} = %{version}-%{release} Requires: %{name}-os_mon%{?_isa} = %{version}-%{release}
Requires: erlang-test_server%{?_isa} = %{version}-%{release} Requires: %{name}-otp_mibs%{?_isa} = %{version}-%{release}
Requires: erlang-toolbar%{?_isa} = %{version}-%{release} Requires: %{name}-parsetools%{?_isa} = %{version}-%{release}
Requires: erlang-tools%{?_isa} = %{version}-%{release} Requires: %{name}-percept%{?_isa} = %{version}-%{release}
Requires: erlang-tv%{?_isa} = %{version}-%{release} Requires: %{name}-pman%{?_isa} = %{version}-%{release}
Requires: erlang-typer%{?_isa} = %{version}-%{release} Requires: %{name}-public_key%{?_isa} = %{version}-%{release}
Requires: erlang-webtool%{?_isa} = %{version}-%{release} Requires: %{name}-reltool%{?_isa} = %{version}-%{release}
Requires: erlang-wx%{?_isa} = %{version}-%{release} Requires: %{name}-runtime_tools%{?_isa} = %{version}-%{release}
Requires: erlang-xmerl%{?_isa} = %{version}-%{release} Requires: %{name}-sasl%{?_isa} = %{version}-%{release}
Requires: %{name}-snmp%{?_isa} = %{version}-%{release}
Requires: %{name}-ssh%{?_isa} = %{version}-%{release}
Requires: %{name}-ssl%{?_isa} = %{version}-%{release}
Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
Requires: %{name}-syntax_tools%{?_isa} = %{version}-%{release}
Requires: %{name}-test_server%{?_isa} = %{version}-%{release}
Requires: %{name}-toolbar%{?_isa} = %{version}-%{release}
Requires: %{name}-tools%{?_isa} = %{version}-%{release}
Requires: %{name}-tv%{?_isa} = %{version}-%{release}
Requires: %{name}-typer%{?_isa} = %{version}-%{release}
Requires: %{name}-webtool%{?_isa} = %{version}-%{release}
Requires: %{name}-wx%{?_isa} = %{version}-%{release}
Requires: %{name}-xmerl%{?_isa} = %{version}-%{release}
Obsoletes: erlang-docbuilder Obsoletes: erlang-docbuilder
Obsoletes: erlang-inviso Obsoletes: erlang-inviso
@ -405,15 +438,15 @@ Requires: %{name}-syntax_tools%{?_isa} = %{version}-%{release}
%description diameter %description diameter
Diameter (RFC 3588) library Diameter (RFC 3588) library
%if %{with doc}
%package doc %package doc
Summary: Erlang documentation Summary: Erlang documentation
Group: Development/Languages Group: Development/Languages
%if 0%{?el6}%{?el7}%{?fedora}
BuildArch: noarch BuildArch: noarch
%endif
%description doc %description doc
Documentation for Erlang. Documentation for Erlang.
%endif
%package edoc %package edoc
Summary: A utility used to generate documentation out of tags in source files Summary: A utility used to generate documentation out of tags in source files
@ -462,10 +495,16 @@ Low level interface to C.
%package erts %package erts
Summary: Functionality necessary to run the Erlang System itself Summary: Functionality necessary to run the Erlang System itself
Group: Development/Languages Group: Development/Languages
# epmd user, epmd group
Requires(pre): shadow-utils
Requires: %{name}-kernel%{?_isa} = %{version}-%{release} Requires: %{name}-kernel%{?_isa} = %{version}-%{release}
Requires: %{name}-stdlib%{?_isa} = %{version}-%{release} Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
# This library is dlopened so it can't be picked up automatically by the RPM
# dependency checker
Requires: lksctp-tools Requires: lksctp-tools
# See erts/emulator/beam/erl_driver.h or call erlang:system_info(driver_version).
Provides: erlang(erl_drv_version) = 2.2 Provides: erlang(erl_drv_version) = 2.2
# See erts/emulator/beam/erl_nif.h or call erlang:system_info(nif_version).
Provides: erlang(erl_nif_version) = 2.4 Provides: erlang(erl_nif_version) = 2.4
%description erts %description erts
@ -558,7 +597,7 @@ Group: Development/Languages
Requires: %{name}-erts%{?_isa} = %{version}-%{release} Requires: %{name}-erts%{?_isa} = %{version}-%{release}
# FIXME see erlang-ic also # FIXME see erlang-ic also
#Requires: jpackage-utils #Requires: jpackage-utils
%if 0%{?fedora}%{?el7} %if 0%{?el7}%{?fedora}
BuildRequires: java-devel BuildRequires: java-devel
%else %else
%ifarch %{ix86} x86_64 %ifarch %{ix86} x86_64
@ -788,7 +827,6 @@ Secure Shell application with sftp and ssh support.
%package ssl %package ssl
Summary: Secure Socket Layer support Summary: Secure Socket Layer support
Group: Development/Languages Group: Development/Languages
#Requires: %{name}-asn1%{?_isa} = %{version}-%{release}
Requires: %{name}-crypto%{?_isa} = %{version}-%{release} Requires: %{name}-crypto%{?_isa} = %{version}-%{release}
Requires: %{name}-erts%{?_isa} = %{version}-%{release} Requires: %{name}-erts%{?_isa} = %{version}-%{release}
Requires: %{name}-kernel%{?_isa} = %{version}-%{release} Requires: %{name}-kernel%{?_isa} = %{version}-%{release}
@ -828,7 +866,6 @@ Requires: %{name}-inets%{?_isa} = %{version}-%{release}
Requires: %{name}-kernel%{?_isa} = %{version}-%{release} Requires: %{name}-kernel%{?_isa} = %{version}-%{release}
Requires: %{name}-observer%{?_isa} = %{version}-%{release} Requires: %{name}-observer%{?_isa} = %{version}-%{release}
Requires: %{name}-runtime_tools%{?_isa} = %{version}-%{release} Requires: %{name}-runtime_tools%{?_isa} = %{version}-%{release}
#Requires: %{name}-sasl%{?_isa} = %{version}-%{release}
Requires: %{name}-stdlib%{?_isa} = %{version}-%{release} Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
Requires: %{name}-tools%{?_isa} = %{version}-%{release} Requires: %{name}-tools%{?_isa} = %{version}-%{release}
@ -855,7 +892,12 @@ Requires: %{name}-inets%{?_isa} = %{version}-%{release}
Requires: %{name}-kernel%{?_isa} = %{version}-%{release} Requires: %{name}-kernel%{?_isa} = %{version}-%{release}
Requires: %{name}-runtime_tools%{?_isa} = %{version}-%{release} Requires: %{name}-runtime_tools%{?_isa} = %{version}-%{release}
Requires: %{name}-stdlib%{?_isa} = %{version}-%{release} Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
Requires: %{name}-webtool%{?_isa} = %{version}-%{release} # This is a weak dependency triggered by the "cover_web" application.
# Unfortunately Recommends/Suggests tags are supported only in Fedora 21+ and
# RHEL 8+ (eventually)
%if 0%{?fedora} >= 21 || 0%{?rhel} >= 8
Suggests: %{name}-webtool%{?_isa} = %{version}-%{release}
%endif
Provides: emacs-common-erlang = %{version}-%{release} Provides: emacs-common-erlang = %{version}-%{release}
%description tools %description tools
@ -922,7 +964,6 @@ Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
%description xmerl %description xmerl
Provides support for XML 1.0. Provides support for XML 1.0.
%if 0%{?el6}%{?fedora}
%package -n emacs-erlang %package -n emacs-erlang
Summary: Compiled elisp files for erlang-mode under GNU Emacs Summary: Compiled elisp files for erlang-mode under GNU Emacs
Requires: emacs-common-erlang = %{version}-%{release} Requires: emacs-common-erlang = %{version}-%{release}
@ -960,7 +1001,6 @@ BuildArch: noarch
%description -n xemacs-erlang-el %description -n xemacs-erlang-el
Erlang mode for XEmacs (source lisp files). Erlang mode for XEmacs (source lisp files).
%endif
%prep %prep
%setup -q -n otp_src_%{upstream_ver}%{upstream_rel}-1 %setup -q -n otp_src_%{upstream_ver}%{upstream_rel}-1
@ -983,6 +1023,22 @@ Erlang mode for XEmacs (source lisp files).
%patch11 -p1 -b .Add_systemd_option_to_empd_Check_for_include_system %patch11 -p1 -b .Add_systemd_option_to_empd_Check_for_include_system
%patch12 -p1 -b .Add_systemd_support_to_epmd %patch12 -p1 -b .Add_systemd_support_to_epmd
%patch13 -p1 -b .Added_systemd_notify_support_to_EPMD %patch13 -p1 -b .Added_systemd_notify_support_to_EPMD
%patch14 -p1 -b .Install_internal_hrl_files_when_necessary
%patch15 -p1 -b .Expose_NIF_version
%patch16 -p1 -b .Split_off_webtool_dependency_from_tools
%patch17 -p1 -b .lib_inets_src_ftp_ftp_erl_Check_the_filenames_userna
%patch18 -p1 -b .Introduce_os_getenv_2
%patch19 -p1 -b .Patch_removes_support_for_SSLv3_protocol_because_it_
%patch20 -p1 -b .R16B03_1_backport_of_TLS_1_0_padding_check
%patch21 -p1 -b .Add_patch_to_crash_dump_on_large_distribution
%patch22 -p1 -b .kernel_inet6_tcp_dist_reuse_inet_tcp_dist_code
%patch23 -p1 -b .epmd_support_IPv6_node_registration
%patch24 -p1 -b .Remove_unused_code_in_error_logger_handlers
%patch25 -p1 -b .Teach_sasl_report_to_limit_crash_reports
%patch26 -p1 -b .Revert_Remove_unused_code_in_error_logger_handlers
%patch27 -p1 -b .Respect_proto_dist_switch_while_connection_to_EPMD
%patch28 -p1 -b .mnesia_Send_mnesia_down_messages_to_waiting_transact
%patch29 -p1 -b .Fix_a_few_javadoc_errors
# end of autogenerated prep patch list # end of autogenerated prep patch list
# FIXME we should come up with a better solution # FIXME we should come up with a better solution
@ -1005,9 +1061,9 @@ rm -f lib/ssl/examples/certs/etc/erlangCA/index.txt.old
%build %build
%ifarch sparcv9 sparc64 %ifarch sparcv9 sparc64
CFLAGS="$RPM_OPT_FLAGS -mcpu=ultrasparc -fno-strict-aliasing" %configure --enable-shared-zlib --enable-sctp %{?__with_hipe:--enable-hipe} CFLAGS="$RPM_OPT_FLAGS -mcpu=ultrasparc -fno-strict-aliasing" %configure --enable-shared-zlib --enable-sctp --enable-systemd %{?__with_hipe:--enable-hipe}
%else %else
CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %configure --enable-shared-zlib --enable-sctp %{?__with_hipe:--enable-hipe} CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %configure --enable-shared-zlib --enable-sctp --enable-systemd %{?__with_hipe:--enable-hipe}
%endif %endif
# Remove pre-built BEAM files # Remove pre-built BEAM files
@ -1016,7 +1072,6 @@ make clean
# GNU Emacs/XEmacs related stuff # GNU Emacs/XEmacs related stuff
erlang_tools_vsn="$(sed -n 's/TOOLS_VSN = //p' lib/tools/vsn.mk)" erlang_tools_vsn="$(sed -n 's/TOOLS_VSN = //p' lib/tools/vsn.mk)"
%if 0%{?el6}%{?fedora}
# GNU Emacs related stuff # GNU Emacs related stuff
cat > emacs-erlang-init.el << EOF cat > emacs-erlang-init.el << EOF
(setq load-path (cons "%{_emacs_sitelispdir}/erlang" load-path)) (setq load-path (cons "%{_emacs_sitelispdir}/erlang" load-path))
@ -1043,12 +1098,10 @@ rm -f xemacs-erlang/erlang-flymake.el
pushd xemacs-erlang pushd xemacs-erlang
%{_xemacs_bytecompile} *.el %{_xemacs_bytecompile} *.el
popd popd
%endif
make make
%if %{with doc} %if %{with doc}
%if %{use_prebuilt_docs}
%else
# should use FOP_OPTS after #832323 is resolved # should use FOP_OPTS after #832323 is resolved
%ifnarch ppc %{power64} %ifnarch ppc %{power64}
export BASE_OPTIONS=-Xmx1024m export BASE_OPTIONS=-Xmx1024m
@ -1057,13 +1110,9 @@ export BASE_OPTIONS=-Xmx1536m
%endif %endif
make docs make docs
%endif %endif
%endif
%install %install
rm -rf $RPM_BUILD_ROOT
%if 0%{?el6}%{?fedora}
# GNU Emacs/XEmacs related stuff # GNU Emacs/XEmacs related stuff
erlang_tools_vsn="$(sed -n 's/TOOLS_VSN = //p' lib/tools/vsn.mk)" erlang_tools_vsn="$(sed -n 's/TOOLS_VSN = //p' lib/tools/vsn.mk)"
@ -1089,25 +1138,12 @@ for f in lib/tools/emacs/{README,*.el}; do
done done
rm -f "$RPM_BUILD_ROOT%{_xemacs_sitelispdir}/erlang/erlang-flymake.el" rm -f "$RPM_BUILD_ROOT%{_xemacs_sitelispdir}/erlang/erlang-flymake.el"
install -m 0644 xemacs-erlang/*.elc "$RPM_BUILD_ROOT%{_xemacs_sitelispdir}/erlang/" install -m 0644 xemacs-erlang/*.elc "$RPM_BUILD_ROOT%{_xemacs_sitelispdir}/erlang/"
%endif
make DESTDIR=$RPM_BUILD_ROOT install make DESTDIR=$RPM_BUILD_ROOT install
%if %{with doc} %if %{with doc}
%if %{use_prebuilt_docs}
# extract prebuilt docs and man-pages
tar xf %{SOURCE1} -C $RPM_BUILD_ROOT%{_libdir}/erlang
tar xf %{SOURCE2} -C $RPM_BUILD_ROOT%{_libdir}/erlang
# rm Win32-specific functionality
rm -f $RPM_BUILD_ROOT%{_libdir}/erlang/man/man3/nteventlog.*
# rm VxWorks specific
rm -f $RPM_BUILD_ROOT%{_libdir}/erlang/man/man3/erl_set_memory_block.*
# rm unneeded files
rm -f $RPM_BUILD_ROOT%{_libdir}/erlang/erts-*/info
rm -f $RPM_BUILD_ROOT%{_libdir}/erlang/lib/*-*/info
%else
env ERL_LIBS="$RPM_BUILD_ROOT%{_libdir}/erlang/lib" make DESTDIR=$RPM_BUILD_ROOT install-docs env ERL_LIBS="$RPM_BUILD_ROOT%{_libdir}/erlang/lib" make DESTDIR=$RPM_BUILD_ROOT install-docs
%endif %endif
%endif
# Do not install info files - they are almost empty and useless # Do not install info files - they are almost empty and useless
find $RPM_BUILD_ROOT%{_libdir}/erlang -type f -name info -exec rm -f {} \; find $RPM_BUILD_ROOT%{_libdir}/erlang -type f -name info -exec rm -f {} \;
@ -1194,10 +1230,6 @@ useradd -r -g epmd -d /tmp -s /sbin/nologin \
-c "Erlang Port Mapper Daemon" epmd 2>/dev/null || : -c "Erlang Port Mapper Daemon" epmd 2>/dev/null || :
%clean
rm -rf $RPM_BUILD_ROOT
%files %files
%if %{with doc} %if %{with doc}
%dir %{_docdir}/%{n_uvr}/ %dir %{_docdir}/%{n_uvr}/
@ -1410,8 +1442,8 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/erlang/man/man4/diameter_dict.* %{_libdir}/erlang/man/man4/diameter_dict.*
%endif %endif
%files doc
%if %{with doc} %if %{with doc}
%files doc
%doc %{_docdir}/%{n_uvr}/doc %doc %{_docdir}/%{n_uvr}/doc
%doc %{_docdir}/%{n_uvr}/erts-*/ %doc %{_docdir}/%{n_uvr}/erts-*/
%doc %{_docdir}/%{n_uvr}/lib/ %doc %{_docdir}/%{n_uvr}/lib/
@ -1436,7 +1468,9 @@ rm -rf $RPM_BUILD_ROOT
%files erl_docgen %files erl_docgen
%{_libdir}/erlang/lib/erl_docgen-*/ %{_libdir}/erlang/lib/erl_docgen-*/
%if %{with doc}
%{_libdir}/erlang/man/man6/erl_docgen.* %{_libdir}/erlang/man/man6/erl_docgen.*
%endif
%files erl_interface %files erl_interface
%{_libdir}/erlang/lib/erl_interface-*/ %{_libdir}/erlang/lib/erl_interface-*/
@ -1455,7 +1489,9 @@ rm -rf $RPM_BUILD_ROOT
%endif %endif
%files erts %files erts
# TODO these directories should be packaged separately # TODO
# In order to have a parallel-installable Erlang packages these directories
# should be packaged separately
%dir %{_libdir}/erlang/ %dir %{_libdir}/erlang/
%dir %{_libdir}/erlang/bin/ %dir %{_libdir}/erlang/bin/
%dir %{_libdir}/erlang/lib/ %dir %{_libdir}/erlang/lib/
@ -1556,6 +1592,7 @@ rm -rf $RPM_BUILD_ROOT
%dir %{_libdir}/erlang/lib/eunit-*/ %dir %{_libdir}/erlang/lib/eunit-*/
%{_libdir}/erlang/lib/eunit-*/ebin %{_libdir}/erlang/lib/eunit-*/ebin
%{_libdir}/erlang/lib/eunit-*/include %{_libdir}/erlang/lib/eunit-*/include
%{_libdir}/erlang/lib/eunit-*/src
%if %{with doc} %if %{with doc}
%{_libdir}/erlang/man/man3/eunit.* %{_libdir}/erlang/man/man3/eunit.*
%{_libdir}/erlang/man/man3/eunit_surefire.* %{_libdir}/erlang/man/man3/eunit_surefire.*
@ -2313,7 +2350,6 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/erlang/man/man3/xmerl_xsd.* %{_libdir}/erlang/man/man3/xmerl_xsd.*
%endif %endif
%if 0%{?el6}%{?fedora}
%files -n emacs-erlang %files -n emacs-erlang
%dir %{_emacs_sitelispdir}/erlang %dir %{_emacs_sitelispdir}/erlang
%doc %{_emacs_sitelispdir}/erlang/README %doc %{_emacs_sitelispdir}/erlang/README
@ -2331,10 +2367,48 @@ rm -rf $RPM_BUILD_ROOT
%files -n xemacs-erlang-el %files -n xemacs-erlang-el
%{_xemacs_sitelispdir}/erlang/*.el %{_xemacs_sitelispdir}/erlang/*.el
%endif
%changelog %changelog
* Wed Nov 9 2016 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.18
- Respect -proto_dist switch while connecting to EPMD
- Cherry-picked fix for OTP-13423. Mnesia transactions could hang while waiting
on a response from a node who had stopped.
- Fix for doc generation with OpenJDK 1.8.0
* Thu Apr 7 2016 John Eckersberg <eck@redhat.com> - R16B-03.17
- Revert "Enable error_logger depth fine tuning" (rhbz#1324922)
* Sun Feb 28 2016 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.16
- Fixed issue with nodes registration over IPv6
* Fri Feb 19 2016 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.15
- Add missing dependency
* Wed Jan 27 2016 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.14
- Enable error_logger depth fine tuning
* Sun Jan 17 2016 John Eckersberg <eck@redhat.com> - R16B-03.13
- Fix inet_dist_listen_{min,max} for ipv6 (rhbz#1299251)
- Add patch for epmd ipv6 support (rhbz#1299253)
* Mon Jan 11 2016 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.12
- Enable crash dump creation during a large distrubution error
* Fri Aug 7 2015 John Eckersberg <eck@redhat.com> - R16B-03.11
- Add patch for CVE-2015-2774 - TLS-1.0 POODLE vulnerability (rhbz#1206712)
* Mon Dec 01 2014 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.10
- Disable SSLv3 (see rhbz #1169375)
- Backport useful os:getenv/2 from master (see https://github.com/erlang/otp/pull/535 )
* Mon Nov 17 2014 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.9
- Fixed CVE-2014-1693 (backported fix from ver. 17.x.x, see patch no. 17)
* Tue Nov 11 2014 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.8
- Trimmed dependency chain
- Cleaned up spec-file
* Wed Jun 11 2014 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.7 * Wed Jun 11 2014 Peter Lemenkov <lemenkov@gmail.com> - R16B-03.7
- Added missing template for epmd@.socket - Added missing template for epmd@.socket

View file

@ -0,0 +1,97 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Tue, 26 Aug 2014 13:53:49 +0400
Subject: [PATCH] Install internal hrl files when necessary
Sometimes we install *.erl files. Some these files include a private
*.hrl files, so in order to make these *.erl files usable we have to
install these private includes as well.
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
Conflicts:
lib/eunit/src/Makefile
lib/percept/src/Makefile
lib/test_server/src/Makefile
diff --git a/lib/debugger/src/Makefile b/lib/debugger/src/Makefile
index 5a6f298..b40ef23 100644
--- a/lib/debugger/src/Makefile
+++ b/lib/debugger/src/Makefile
@@ -77,7 +77,7 @@ MODULES= \
HRL_FILES=
-INTERNAL_HRL_FILES= dbg_ieval.hrl
+INTERNAL_HRL_FILES= dbg_ieval.hrl dbg_wx_filedialog_win.hrl
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile
index a5e147d..8483e28 100644
--- a/lib/eunit/src/Makefile
+++ b/lib/eunit/src/Makefile
@@ -46,6 +46,8 @@ SOURCES= \
INCLUDE_FILES = eunit.hrl
+INTERNAL_HRL_FILES= eunit_internal.hrl
+
PARSE_TRANSFORM_BIN = $(PARSE_TRANSFORM:%.erl=$(EBIN)/%.$(EMULATOR))
TARGET_FILES= $(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR))
@@ -117,6 +119,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(PARSE_TRANSFORM_BIN) $(OBJECTS) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
$(INSTALL_DIR) "$(RELSYSDIR)/include"
$(INSTALL_DATA) $(INCLUDE_DELIVERABLES) "$(RELSYSDIR)/include"
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index dbda2a2..3e1792f 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -122,6 +122,7 @@ HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \
../include/net_address.hrl
INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
+ erl_epmd.hrl hipe_ext_format.hrl \
inet_dns.hrl inet_res.hrl \
inet_boot.hrl inet_config.hrl inet_int.hrl \
inet_dns_record_adts.hrl
diff --git a/lib/percept/src/Makefile b/lib/percept/src/Makefile
index e501539..5902da3 100644
--- a/lib/percept/src/Makefile
+++ b/lib/percept/src/Makefile
@@ -50,6 +50,8 @@ MODULES= \
#HRL_FILES= ../include/
+INTERNAL_HRL_FILES= egd.hrl percept.hrl
+
ERL_FILES= $(MODULES:%=%.erl)
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
@@ -93,6 +95,8 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
# $(INSTALL_DIR) "$(RELSYSDIR)/include"
# $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index bcb1bc3..deb7caf 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -123,7 +123,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(TS_HRL_FILES) "$(RELSYSDIR)/src"
$(INSTALL_DIR) "$(RELSYSDIR)/include"
$(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"

View file

@ -0,0 +1,90 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Sun, 2 Nov 2014 19:49:55 +0300
Subject: [PATCH] Expose NIF version
This patch allows checking for NIF API version in a way similar to
driver version. E.g. by calling erlang:system_info(nif_version).
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
Conflicts:
erts/emulator/test/driver_SUITE.erl
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index e3ef48a..b9d7230 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -5903,6 +5903,11 @@ ok
<seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>, and
<seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p>
</item>
+ <tag><c>nif_version</c></tag>
+ <item>
+ <p>Returns a string containing the erlang NIF version
+ used by the runtime system. It will be on the form "&lt;major ver&gt;.&lt;minor ver&gt;".</p>
+ </item>
<tag><marker id="system_info_otp_release"><c>otp_release</c></marker></tag>
<item>
<p>Returns a string containing the OTP release number.</p>
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index d7f1e2d..7a7f23e 100755
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -27,6 +27,7 @@
#include "erl_process.h"
#include "error.h"
#include "erl_driver.h"
+#include "erl_nif.h"
#include "bif.h"
#include "big.h"
#include "erl_version.h"
@@ -2428,6 +2429,13 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
ERL_DRV_EXTENDED_MINOR_VERSION);
hp = HAlloc(BIF_P, 2*n);
BIF_RET(buf_to_intlist(&hp, buf, n, NIL));
+ } else if (ERTS_IS_ATOM_STR("nif_version", BIF_ARG_1)) {
+ char buf[42];
+ int n = erts_snprintf(buf, 42, "%d.%d",
+ ERL_NIF_MAJOR_VERSION,
+ ERL_NIF_MINOR_VERSION);
+ hp = HAlloc(BIF_P, 2*n);
+ BIF_RET(buf_to_intlist(&hp, buf, n, NIL));
} else if (ERTS_IS_ATOM_STR("smp_support", BIF_ARG_1)) {
#ifdef ERTS_SMP
BIF_RET(am_true);
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 2919265..c0f14ad 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -2124,6 +2124,7 @@ tuple_to_list(_Tuple) ->
(modified_timing_level) -> integer() | undefined;
(multi_scheduling) -> disabled | blocked | enabled;
(multi_scheduling_blockers) -> [PID :: pid()];
+ (nif_version) -> string();
(otp_release) -> string();
(port_count) -> non_neg_integer();
(port_limit) -> pos_integer();
diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl
index 1d4b878..64f1b82 100644
--- a/lib/runtime_tools/src/system_information.erl
+++ b/lib/runtime_tools/src/system_information.erl
@@ -344,6 +344,7 @@ erlang_system_info() ->
logical_processors_online,
logical_processors_available,
driver_version,
+ nif_version,
emu_args,
ethread_info,
beam_jump_table,
diff --git a/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat b/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat
index 0900ead..9ded5a1 100644
--- a/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat
+++ b/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat
@@ -9720,6 +9720,7 @@
{logical_processors_online,4},
{logical_processors_available,4},
{driver_version,"2.1"},
+ {nif_version,"1.1"},
{taints,[]}]},
{erts_compile_info,
[{ldflags,[]},

View file

@ -0,0 +1,40 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Sat, 8 Nov 2014 22:54:57 +0300
Subject: [PATCH] Split off webtool dependency from tools
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/tools/src/cover_web.erl b/lib/tools/src/cover_web.erl
index 69f2f3b..9085300 100644
--- a/lib/tools/src/cover_web.erl
+++ b/lib/tools/src/cover_web.erl
@@ -50,14 +50,25 @@
%%%----------------------------------------------------------------------
%% Start webtool and webcover from erlang shell
start() ->
- webtool:start(),
- webtool:start_tools([],"app=webcover"),
+ try
+ % Disable automatic dependency picking up
+ erlang:apply(webtool, start, []),
+ erlang:apply(webtool, start_tools, [[],"app=webcover"])
+ catch
+ error:undef -> error_logger:error_msg("No erlang-webtool found.~nPlease install erlang-webtool package first.~n")
+ end,
ok.
%% Stop webtool and webcover from erlang shell
stop() ->
- webtool:stop_tools([],"app=webcover"),
- webtool:stop().
+ try
+ % Disable automatic dependency picking up
+ erlang:apply(webtool, stop_tools, [[],"app=webcover"]),
+ erlang:apply(webtool, stop, [])
+ catch
+ error:undef -> error_logger:error_msg("No erlang-webtool found.~nPlease install erlang-webtool package first.~n")
+ end,
+ ok.

View file

@ -0,0 +1,430 @@
From: Sergei Golovan <sgolovan@gmail.com>
Date: Sun, 9 Feb 2014 23:06:25 +0400
Subject: [PATCH] lib/inets/src/ftp/ftp.erl: Check the filenames, usernames,
passwords etc. for <CR> and <LF> in them and return error if these
offending chars are found. See
http://erlang.org/pipermail/erlang-bugs/2014-January/003998.html for
details. lib/inets/test/ftp_suite_lib.erl: Added checks for <CR><LF> in file
and directory names.
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index 520db1b..5674599 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -192,7 +192,12 @@ do_open(Pid, OpenOptions, TLSOpts) ->
'ok' | {'error', Reason :: 'euser' | common_reason()}.
user(Pid, User, Pass) ->
- call(Pid, {user, User, Pass}, atom).
+ case {is_name_sane(User), is_name_sane(Pass)} of
+ {true, true} ->
+ call(Pid, {user, User, Pass}, atom);
+ _ ->
+ {error, euser}
+ end.
-spec user(Pid :: pid(),
User :: string(),
@@ -201,7 +206,12 @@ user(Pid, User, Pass) ->
'ok' | {'error', Reason :: 'euser' | common_reason()}.
user(Pid, User, Pass, Acc) ->
- call(Pid, {user, User, Pass, Acc}, atom).
+ case {is_name_sane(User), is_name_sane(Pass), is_name_sane(Acc)} of
+ {true, true, true} ->
+ call(Pid, {user, User, Pass, Acc}, atom);
+ _ ->
+ {error, euser}
+ end.
%%--------------------------------------------------------------------------
@@ -216,7 +226,12 @@ user(Pid, User, Pass, Acc) ->
'ok' | {'error', Reason :: 'eacct' | common_reason()}.
account(Pid, Acc) ->
- call(Pid, {account, Acc}, atom).
+ case is_name_sane(Acc) of
+ true ->
+ call(Pid, {account, Acc}, atom);
+ _ ->
+ {error, eacct}
+ end.
%%--------------------------------------------------------------------------
@@ -262,7 +277,12 @@ lpwd(Pid) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
cd(Pid, Dir) ->
- call(Pid, {cd, Dir}, atom).
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {cd, Dir}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -305,7 +325,12 @@ ls(Pid) ->
{'error', Reason :: restriction_reason() | common_reason()}.
ls(Pid, Dir) ->
- call(Pid, {dir, long, Dir}, string).
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {dir, long, Dir}, string);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -333,7 +358,12 @@ nlist(Pid) ->
{'error', Reason :: restriction_reason() | common_reason()}.
nlist(Pid, Dir) ->
- call(Pid, {dir, short, Dir}, string).
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {dir, short, Dir}, string);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -349,7 +379,12 @@ nlist(Pid, Dir) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
rename(Pid, Old, New) ->
- call(Pid, {rename, Old, New}, string).
+ case {is_name_sane(Old), is_name_sane(New)} of
+ {true, true} ->
+ call(Pid, {rename, Old, New}, string);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -365,7 +400,12 @@ rename(Pid, Old, New) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
delete(Pid, File) ->
- call(Pid, {delete, File}, string).
+ case is_name_sane(File) of
+ true ->
+ call(Pid, {delete, File}, string);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -380,7 +420,12 @@ delete(Pid, File) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
mkdir(Pid, Dir) ->
- call(Pid, {mkdir, Dir}, atom).
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {mkdir, Dir}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -395,7 +440,12 @@ mkdir(Pid, Dir) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
rmdir(Pid, Dir) ->
- call(Pid, {rmdir, Dir}, atom).
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {rmdir, Dir}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -437,7 +487,12 @@ recv(Pid, RemotFileName) ->
'ok' | {'error', Reason :: term()}.
recv(Pid, RemotFileName, LocalFileName) ->
- call(Pid, {recv, RemotFileName, LocalFileName}, atom).
+ case is_name_sane(RemotFileName) of
+ true ->
+ call(Pid, {recv, RemotFileName, LocalFileName}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -456,7 +511,12 @@ recv(Pid, RemotFileName, LocalFileName) ->
{'error', Reason :: restriction_reason() | common_reason()}.
recv_bin(Pid, RemoteFile) ->
- call(Pid, {recv_bin, RemoteFile}, bin).
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {recv_bin, RemoteFile}, bin);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -473,7 +533,12 @@ recv_bin(Pid, RemoteFile) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
recv_chunk_start(Pid, RemoteFile) ->
- call(Pid, {recv_chunk_start, RemoteFile}, atom).
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {recv_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -521,7 +586,12 @@ send(Pid, LocalFileName) ->
shortage_reason()}.
send(Pid, LocalFileName, RemotFileName) ->
- call(Pid, {send, LocalFileName, RemotFileName}, atom).
+ case is_name_sane(RemotFileName) of
+ true ->
+ call(Pid, {send, LocalFileName, RemotFileName}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -541,7 +611,12 @@ send(Pid, LocalFileName, RemotFileName) ->
shortage_reason()}.
send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
- call(Pid, {send_bin, Bin, RemoteFile}, atom);
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {send_bin, Bin, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end;
send_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
@@ -559,7 +634,12 @@ send_bin(_Pid, _Bin, _RemoteFile) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
send_chunk_start(Pid, RemoteFile) ->
- call(Pid, {send_chunk_start, RemoteFile}, atom).
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {send_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -575,7 +655,12 @@ send_chunk_start(Pid, RemoteFile) ->
'ok' | {'error', Reason :: term()}.
append_chunk_start(Pid, RemoteFile) ->
- call(Pid, {append_chunk_start, RemoteFile}, atom).
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {append_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -683,7 +768,12 @@ append(Pid, LocalFileName) ->
'ok' | {'error', Reason :: term()}.
append(Pid, LocalFileName, RemotFileName) ->
- call(Pid, {append, LocalFileName, RemotFileName}, atom).
+ case is_name_sane(RemotFileName) of
+ true ->
+ call(Pid, {append, LocalFileName, RemotFileName}, atom);
+ _ ->
+ {error, efnamena}
+ end.
%%--------------------------------------------------------------------------
@@ -705,7 +795,12 @@ append(Pid, LocalFileName, RemotFileName) ->
shortage_reason()}.
append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
- call(Pid, {append_bin, Bin, RemoteFile}, atom);
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {append_bin, Bin, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end;
append_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
@@ -2302,6 +2397,15 @@ send_bin(State, Bin) ->
mk_cmd(Fmt, Args) ->
[io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok.
+is_name_sane([]) ->
+ true;
+is_name_sane([?CR| _]) ->
+ false;
+is_name_sane([?LF| _]) ->
+ false;
+is_name_sane([_| Rest]) ->
+ is_name_sane(Rest).
+
pwd_result(Lines) ->
{_, [?DOUBLE_QUOTE | Rest]} =
lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines),
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index 35f21cc..daee1bd 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -1266,6 +1266,8 @@ read_log_6035([]) ->
%%--------------------------------------------------------------------
do_user(Pid) ->
{error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS),
+ {error, euser} = ftp:user(Pid, ?FTP_USER++"\r\nPASS "++?FTP_PASS, ?FTP_PASS),
+ {error, euser} = ftp:user(Pid, ?FTP_USER, ?FTP_PASS++"\r\nCWD ."),
ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS),
ok.
@@ -1278,6 +1280,7 @@ do_pwd(Pid) ->
do_cd(Pid) ->
ok = ftp:cd(Pid, "/pub"),
{error, epath} = ftp:cd(Pid, ?BAD_DIR),
+ {error, efnamena} = ftp:cd(Pid, "/pub\r\nCWD ."),
ok.
do_lcd(Pid, Dir) ->
@@ -1294,11 +1297,14 @@ do_ls(Pid) ->
%% directory, but can also be a filename or a group
%% of files (including wildcards).
{ok, _} = ftp:ls(Pid, "incom*"),
+ %% but \r\n can't be in the wildcard
+ {error, efnamena} = ftp:ls(Pid, "incoming\r\nCWD ."),
ok.
do_nlist(Pid, WildcardSupport) ->
{ok, _} = ftp:nlist(Pid),
{ok, _} = ftp:nlist(Pid, "incoming"),
+ {error, efnamena} = ftp:ls(Pid, "incoming\r\nCWD ."),
%% neither nlist nor ls operates on a directory
%% they operate on a pathname, which *can* be a
%% directory, but can also be a filename or a group
@@ -1324,6 +1330,8 @@ do_rename(Pid, Config) ->
ftp:delete(Pid, NewLFile), % reset
ok = ftp:send(Pid, LFile),
{error, epath} = ftp:rename(Pid, NewLFile, LFile),
+ {error, efnamena} = ftp:rename(Pid, NewLFile++"\r\nRNTO "++LFile++"\r\nRNFR "++NewLFile, LFile),
+ {error, efnamena} = ftp:rename(Pid, NewLFile, LFile++"\r\nCWD ."),
ok = ftp:rename(Pid, LFile, NewLFile),
ftp:delete(Pid, LFile), % cleanup
ftp:delete(Pid, NewLFile), % cleanup
@@ -1338,6 +1346,7 @@ do_delete(Pid, Config) ->
ok = ftp:cd(Pid, "incoming"),
ok = ftp:lcd(Pid, PrivDir),
ftp:delete(Pid,LFile), % reset
+ {error, efnamena} = ftp:delete(Pid,LFile++"\r\nCWD ."),
ok = ftp:send(Pid, LFile),
ok = ftp:delete(Pid,LFile),
ok.
@@ -1348,6 +1357,8 @@ do_mkdir(Pid) ->
integer_to_list(B) ++ "_" ++ integer_to_list(C),
ok = ftp:cd(Pid, "incoming"),
{ok, CurrDir} = ftp:pwd(Pid),
+ {error, efnamena} = ftp:mkdir(Pid, NewDir++"\r\nCWD ."),
+ {error, efnamena} = ftp:rmdir(Pid, NewDir++"\r\nCWD ."),
ok = ftp:mkdir(Pid, NewDir),
ok = ftp:cd(Pid, NewDir),
ok = ftp:cd(Pid, CurrDir),
@@ -1363,6 +1374,7 @@ do_send(Pid, Config) ->
ok = file:write_file(AbsLFile, list_to_binary(Contents)),
ok = ftp:cd(Pid, "incoming"),
ok = ftp:lcd(Pid, PrivDir),
+ {error, efnamena} = ftp:send(Pid, LFile, RFile++"1\r\nCWD ."),
ok = ftp:send(Pid, LFile, RFile),
{ok, RFilesString} = ftp:nlist(Pid),
RFiles = split(RFilesString),
@@ -1392,6 +1404,7 @@ do_append(Pid, Config) ->
ftp:delete(Pid, RFile),
ftp:delete(Pid, LFile),
+ {error, efnamena} = ftp:append(Pid, LFile, RFile++"1\r\nCWD ."),
ok = ftp:append(Pid, LFile, RFile),
ok = ftp:append(Pid, LFile, RFile),
ok = ftp:append(Pid, LFile),
@@ -1413,6 +1426,7 @@ do_send_bin(Pid, Config) ->
Bin = list_to_binary(Contents),
ok = ftp:cd(Pid, "incoming"),
{error, enotbinary} = ftp:send_bin(Pid, Contents, File),
+ {error, efnamena} = ftp:send_bin(Pid, Bin, File++"1\r\nCWD ."),
ok = ftp:send_bin(Pid, Bin, File),
{ok, RFilesString} = ftp:nlist(Pid),
RFiles = split(RFilesString),
@@ -1426,6 +1440,7 @@ do_append_bin(Pid, Config) ->
Bin = list_to_binary(Contents),
ok = ftp:cd(Pid, "incoming"),
{error, enotbinary} = ftp:append_bin(Pid, Contents, File),
+ {error, efnamena} = ftp:append_bin(Pid, Bin, File++"1\r\nCWD ."),
ok = ftp:append_bin(Pid, Bin, File),
ok = ftp:append_bin(Pid, Bin, File),
%% Control the contents of the file
@@ -1438,6 +1453,7 @@ do_send_chunk(Pid, Config) ->
Contents = "ftp_SUITE test ...",
Bin = list_to_binary(Contents),
ok = ftp:cd(Pid, "incoming"),
+ {error, efnamena} = ftp:send_chunk_start(Pid, File++"1\r\nCWD ."),
ok = ftp:send_chunk_start(Pid, File),
{error, echunk} = ftp:cd(Pid, "incoming"),
{error, enotbinary} = ftp:send_chunk(Pid, Contents),
@@ -1454,6 +1470,7 @@ do_append_chunk(Pid, Config) ->
File = ?config(file, Config),
Contents = ["ER","LE","RL"],
ok = ftp:cd(Pid, "incoming"),
+ {error, efnamena} = ftp:append_chunk_start(Pid, File++"1\r\nCWD ."),
ok = ftp:append_chunk_start(Pid, File),
{error, enotbinary} = ftp:append_chunk(Pid, lists:nth(1,Contents)),
ok = ftp:append_chunk(Pid,list_to_binary(lists:nth(1,Contents))),
@@ -1480,6 +1497,7 @@ do_recv(Pid, Config) ->
ok = file:delete(AbsFile), % cleanup
test_server:sleep(100),
ok = ftp:lcd(Pid, PrivDir),
+ {error, efnamena} = ftp:recv(Pid, File++"\r\nCWD ."),
ok = ftp:recv(Pid, File),
{ok, Files} = file:list_dir(PrivDir),
true = lists:member(File, Files),
@@ -1495,6 +1513,7 @@ do_recv_bin(Pid, Config) ->
ok = ftp:cd(Pid, "incoming"),
ok = ftp:send_bin(Pid, Bin1, File),
test_server:sleep(100),
+ {error, efnamena} = ftp:recv_bin(Pid, File++"\r\nCWD ."),
{ok, Bin2} = ftp:recv_bin(Pid, File),
ok = ftp:delete(Pid, File), % cleanup
Contents2 = binary_to_list(Bin2),
@@ -1520,6 +1539,7 @@ do_recv_chunk(Pid, Config) ->
ok = ftp:send_bin(Pid, Bin1, File),
test_server:sleep(100),
{error, "ftp:recv_chunk_start/2 not called"} = recv_chunk(Pid, <<>>),
+ {error, efnamena} = ftp:recv_chunk_start(Pid, File++"\r\nCWD ."),
ok = ftp:recv_chunk_start(Pid, File),
{ok, Contents2} = recv_chunk(Pid, <<>>),
ok = ftp:delete(Pid, File), % cleanup

View file

@ -0,0 +1,63 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Sat, 8 Nov 2014 15:11:04 +0300
Subject: [PATCH] Introduce os:getenv/2
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 9122267..7ec1f8e 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -100,6 +100,19 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</desc>
</func>
<func>
+ <name name="getenv" arity="2"/>
+ <fsummary>Get the value of an environment variable</fsummary>
+ <desc>
+ <p>Returns the <c><anno>Value</anno></c> of the environment variable
+ <c><anno>VarName</anno></c>, or <c>DefaultValue</c> if the environment variable
+ is undefined.</p>
+ <p>If Unicode file name encoding is in effect (see the <seealso
+ marker="erts:erl#file_name_encoding">erl manual
+ page</seealso>), the strings (both <c><anno>VarName</anno></c> and
+ <c><anno>Value</anno></c>) may contain characters with codepoints > 255.</p>
+ </desc>
+ </func>
+ <func>
<name name="getpid" arity="0"/>
<fsummary>Return the process identifier of the emulator process</fsummary>
<desc>
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 9415593..d5ef994 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -26,7 +26,7 @@
%%% BIFs
--export([getenv/0, getenv/1, getpid/0, putenv/2, timestamp/0, unsetenv/1]).
+-export([getenv/0, getenv/1, getenv/2, getpid/0, putenv/2, timestamp/0, unsetenv/1]).
-spec getenv() -> [string()].
@@ -39,6 +39,19 @@ getenv() -> erlang:nif_error(undef).
getenv(_) ->
erlang:nif_error(undef).
+-spec getenv(VarName, DefaultValue) -> Value when
+ VarName :: string(),
+ DefaultValue :: string(),
+ Value :: string().
+
+getenv(VarName, DefaultValue) ->
+ case os:getenv(VarName) of
+ false ->
+ DefaultValue;
+ Value ->
+ Value
+ end.
+
-spec getpid() -> Value when
Value :: string().

View file

@ -0,0 +1,99 @@
From: Sergei Golovan <sgolovan@debian.org>
Date: Sun, 30 Nov 2014 20:20:41 +0300
Subject: [PATCH] Patch removes support for SSLv3 protocol because it is proved
to be insecure and nobody should use it anymore.
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 1d74faf..912acc2 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -123,7 +123,7 @@
<p><c>sslsocket() - opaque to the user. </c></p>
- <p><c>protocol() = sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2' </c></p>
+ <p><c>protocol() = tlsv1 | 'tlsv1.1' | 'tlsv1.2' </c></p>
<p><c>ciphers() = [ciphersuite()] | string() (according to old API)</c></p>
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index 0ee5b23..c65f8a3 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -47,10 +47,10 @@
</p>
<p>Note that the environment parameters can be set on the command line,
for instance,</p>
- <p><c>erl ... -ssl protocol_version '[sslv3, tlsv1]' ...</c>.
+ <p><c>erl ... -ssl protocol_version '[tlsv1.1, tlsv1]' ...</c>.
</p>
<taglist>
- <tag><c><![CDATA[protocol_version = [sslv3|tlsv1] <optional>]]></c>.</tag>
+ <tag><c><![CDATA[protocol_version = [tlsv1|tlsv1.1|tlsv1.2] <optional>]]></c>.</tag>
<item>
<p>Protocol that will be supported by started clients and
servers. If this option is not set it will default to all
@@ -58,6 +58,9 @@
Note that this option may be overridden by the version option
to ssl:connect/[2,3] and ssl:listen/2.
</p>
+ <p>For Debian GNU/Linux distribution the sslv3 protocol was
+ disabled due to its security issues.
+ </p>
</item>
<tag><c><![CDATA[session_lifetime = integer() <optional>]]></c></tag>
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 0186f9f..6f84830 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -67,8 +67,8 @@
-define(TRUE, 0).
-define(FALSE, 1).
--define(ALL_SUPPORTED_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
--define(MIN_SUPPORTED_VERSIONS, ['tlsv1.1', tlsv1, sslv3]).
+-define(ALL_SUPPORTED_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1]).
+-define(MIN_SUPPORTED_VERSIONS, ['tlsv1.1', tlsv1]).
-define(ALL_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
-define(MIN_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index c17fa53..f4be9be 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -144,6 +144,7 @@
%% }).
-define(LOWEST_MAJOR_SUPPORTED_VERSION, 3).
+-define(LOWEST_MINOR_SUPPORTED_VERSION, 1).
-record(generic_stream_cipher, {
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 8810755..3c5c7e9 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -269,13 +269,19 @@ supported_protocol_versions([_|_] = Vsns) ->
%%
%%--------------------------------------------------------------------
is_acceptable_version({N,_})
- when N >= ?LOWEST_MAJOR_SUPPORTED_VERSION ->
+ when N > ?LOWEST_MAJOR_SUPPORTED_VERSION ->
+ true;
+is_acceptable_version({N,M})
+ when N == ?LOWEST_MAJOR_SUPPORTED_VERSION andalso M >= ?LOWEST_MINOR_SUPPORTED_VERSION ->
true;
is_acceptable_version(_) ->
false.
is_acceptable_version({N,_} = Version, Versions)
- when N >= ?LOWEST_MAJOR_SUPPORTED_VERSION ->
+ when N > ?LOWEST_MAJOR_SUPPORTED_VERSION ->
+ lists:member(Version, Versions);
+is_acceptable_version({N,M} = Version, Versions)
+ when N == ?LOWEST_MAJOR_SUPPORTED_VERSION andalso M >= ?LOWEST_MINOR_SUPPORTED_VERSION ->
lists:member(Version, Versions);
is_acceptable_version(_,_) ->
false.

View file

@ -0,0 +1,566 @@
From: John Eckersberg <jeckersb@redhat.com>
Date: Fri, 7 Aug 2015 11:39:27 -0400
Subject: [PATCH] R16B03-1 backport of TLS-1.0 padding check
commit 519b07bca04bdd8585b48f2de6b7124ca6455358
Author: Ingela Anderton Andin <ingela@erlang.org>
Date: Tue Jan 13 15:16:20 2015 +0100
ssl: Reenable padding check for TLS-1.0 and provide backwards compatible
disable option
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 912acc2..e496eb1 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -334,11 +334,23 @@ fun(srp, Username :: string(), UserState :: term()) ->
</p>
</item>
+ <tag>{padding_check, boolean()}</tag>
+ <item>
+ <p> This option only affects TLS-1.0 connections.
+ If set to false it disables the block cipher padding check
+ to be able to interoperate with legacy software.
+ </p>
+
+ <warning><p> Using this option makes TLS vulnerable to
+ the Poodle attack</p></warning>
+
+ </item>
+
</taglist>
-
+
</section>
-
- <section>
+
+ <section>
<title>SSL OPTION DESCRIPTIONS - CLIENT SIDE</title>
<p>Options described here are client specific or has a slightly different
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index b0a7976..49dc9d7 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2013-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
@@ -140,7 +140,7 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
= ConnnectionStates0) ->
CompressAlg = SecParams#security_parameters.compression_algorithm,
{PlainFragment, Mac, ReadState1} = ssl_record:decipher(dtls_v1:corresponding_tls_version(Version),
- CipherFragment, ReadState0),
+ CipherFragment, ReadState0, true),
MacHash = calc_mac_hash(Type, Version, Epoch, Seq, PlainFragment, ReadState1),
case ssl_record:is_correct_mac(Mac, MacHash) of
true ->
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index a7fd9f5..802d29d 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -640,7 +640,8 @@ handle_options(Opts0, _Role) ->
make_next_protocol_selector(
handle_option(client_preferred_next_protocols, Opts, undefined)),
log_alert = handle_option(log_alert, Opts, true),
- server_name_indication = handle_option(server_name_indication, Opts, undefined)
+ server_name_indication = handle_option(server_name_indication, Opts, undefined),
+ padding_check = proplists:get_value(padding_check, Opts, true)
},
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
@@ -652,7 +653,8 @@ handle_options(Opts0, _Role) ->
reuse_session, reuse_sessions, ssl_imp,
cb_info, renegotiate_at, secure_renegotiate, hibernate_after,
erl_dist, next_protocols_advertised,
- client_preferred_next_protocols, log_alert, server_name_indication],
+ client_preferred_next_protocols, log_alert, server_name_indication,
+ padding_check],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
@@ -840,6 +842,8 @@ validate_option(server_name_indication, disable) ->
disable;
validate_option(server_name_indication, undefined) ->
undefined;
+validate_option(padding_check, Value) when is_boolean(Value) ->
+ Value;
validate_option(Opt, Value) ->
throw({error, {options, {Opt, Value}}}).
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index b2077c6..e546e37 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -33,7 +33,7 @@
-include_lib("public_key/include/public_key.hrl").
-export([security_parameters/2, security_parameters/3, suite_definition/1,
- decipher/5, cipher/5,
+ decipher/6, cipher/5,
suite/1, suites/1, ec_keyed_suites/0, anonymous_suites/0, psk_suites/1, srp_suites/0,
openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1,
hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2]).
@@ -127,15 +127,16 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
{T, CS0#cipher_state{iv=NextIV}}.
%%--------------------------------------------------------------------
--spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(), tls_version()) ->
+-spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(),
+ tls_version(), boolean()) ->
{binary(), binary(), #cipher_state{}} | #alert{}.
%%
%% Description: Decrypts the data and the MAC using cipher described
%% by cipher_enum() and updating the cipher state.
%%-------------------------------------------------------------------
-decipher(?NULL, _HashSz, CipherState, Fragment, _) ->
+decipher(?NULL, _HashSz, CipherState, Fragment, _, _) ->
{Fragment, <<>>, CipherState};
-decipher(?RC4, HashSz, CipherState, Fragment, _) ->
+decipher(?RC4, HashSz, CipherState, Fragment, _, _) ->
State0 = case CipherState#cipher_state.state of
undefined -> crypto:stream_init(rc4, CipherState#cipher_state.key);
S -> S
@@ -155,23 +156,23 @@ decipher(?RC4, HashSz, CipherState, Fragment, _) ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end;
-decipher(?DES, HashSz, CipherState, Fragment, Version) ->
+decipher(?DES, HashSz, CipherState, Fragment, Version, PaddingCheck) ->
block_decipher(fun(Key, IV, T) ->
crypto:block_decrypt(des_cbc, Key, IV, T)
- end, CipherState, HashSz, Fragment, Version);
-decipher(?'3DES', HashSz, CipherState, Fragment, Version) ->
+ end, CipherState, HashSz, Fragment, Version, PaddingCheck);
+decipher(?'3DES', HashSz, CipherState, Fragment, Version, PaddingCheck) ->
block_decipher(fun(<<K1:8/binary, K2:8/binary, K3:8/binary>>, IV, T) ->
crypto:block_decrypt(des3_cbc, [K1, K2, K3], IV, T)
- end, CipherState, HashSz, Fragment, Version);
-decipher(?AES, HashSz, CipherState, Fragment, Version) ->
+ end, CipherState, HashSz, Fragment, Version, PaddingCheck);
+decipher(?AES, HashSz, CipherState, Fragment, Version, PaddingCheck) ->
block_decipher(fun(Key, IV, T) when byte_size(Key) =:= 16 ->
crypto:block_decrypt(aes_cbc128, Key, IV, T);
(Key, IV, T) when byte_size(Key) =:= 32 ->
crypto:block_decrypt(aes_cbc256, Key, IV, T)
- end, CipherState, HashSz, Fragment, Version).
+ end, CipherState, HashSz, Fragment, Version, PaddingCheck).
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
- HashSz, Fragment, Version) ->
+ HashSz, Fragment, Version, PaddingCheck) ->
try
Text = Fun(Key, IV, Fragment),
NextIV = next_iv(Fragment, IV),
@@ -179,7 +180,7 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
Content = GBC#generic_block_cipher.content,
Mac = GBC#generic_block_cipher.mac,
CipherState1 = CipherState0#cipher_state{iv=GBC#generic_block_cipher.next_iv},
- case is_correct_padding(GBC, Version) of
+ case is_correct_padding(GBC, Version, PaddingCheck) of
true ->
{Content, Mac, CipherState1};
false ->
@@ -1266,16 +1267,18 @@ generic_stream_cipher_from_bin(T, HashSz) ->
#generic_stream_cipher{content=Content,
mac=Mac}.
-%% For interoperability reasons we do not check the padding content in
-%% SSL 3.0 and TLS 1.0 as it is not strictly required and breaks
-%% interopability with for instance Google.
is_correct_padding(#generic_block_cipher{padding_length = Len,
- padding = Padding}, {3, N})
- when N == 0; N == 1 ->
- Len == byte_size(Padding);
-%% Padding must be check in TLS 1.1 and after
+ padding = Padding}, {3, 0}, _) ->
+ Len == byte_size(Padding); %% Only length check is done in SSL 3.0 spec
+%% For interoperability reasons it is possible to disable
+%% the padding check when using TLS 1.0, as it is not strictly required
+%% in the spec (only recommended), howerver this makes TLS 1.0 vunrable to the Poodle attack
+%% so by default this clause will not match
+is_correct_padding(GenBlockCipher, {3, 1}, false) ->
+ is_correct_padding(GenBlockCipher, {3, 0}, false);
+%% Padding must be checked in TLS 1.1 and after
is_correct_padding(#generic_block_cipher{padding_length = Len,
- padding = Padding}, _) ->
+ padding = Padding}, _, _) ->
Len == byte_size(Padding) andalso
list_to_binary(lists:duplicate(Len, Len)) == Padding.
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 6f84830..8c12141 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -114,7 +114,8 @@
next_protocols_advertised = undefined, %% [binary()],
next_protocol_selector = undefined, %% fun([binary()]) -> binary())
log_alert :: boolean(),
- server_name_indication = undefined
+ server_name_indication = undefined,
+ padding_check = true
}).
-record(config, {ssl, %% SSL parameters
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 018c8be..ed9efe2 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2013-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
@@ -48,7 +48,7 @@
-export([compress/3, uncompress/3, compressions/0]).
%% Payload encryption/decryption
--export([cipher/4, decipher/3, is_correct_mac/2]).
+-export([cipher/4, decipher/4, is_correct_mac/2]).
%%====================================================================
%% Internal application API
@@ -372,7 +372,7 @@ cipher(Version, Fragment,
ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MacHash, Fragment, Version),
{CipherFragment, WriteState0#connection_state{cipher_state = CipherS1}}.
%%--------------------------------------------------------------------
--spec decipher(tls_version(), binary(), #connection_state{}) -> {binary(), binary(), #connection_state{}}.
+-spec decipher(tls_version(), binary(), #connection_state{}, boolean()) -> {binary(), binary(), #connection_state{}}.
%%
%% Description: Payload decryption
%%--------------------------------------------------------------------
@@ -382,8 +382,8 @@ decipher(Version, CipherFragment,
BulkCipherAlgo,
hash_size = HashSz},
cipher_state = CipherS0
- } = ReadState) ->
- case ssl_cipher:decipher(BulkCipherAlgo, HashSz, CipherS0, CipherFragment, Version) of
+ } = ReadState, PaddingCheck) ->
+ case ssl_cipher:decipher(BulkCipherAlgo, HashSz, CipherS0, CipherFragment, Version, PaddingCheck) of
{PlainFragment, Mac, CipherS1} ->
CS1 = ReadState#connection_state{cipher_state = CipherS1},
{PlainFragment, Mac, CS1};
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index ffa04ee..007c9b1 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-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
@@ -499,8 +499,9 @@ next_record(#state{protocol_buffers = #protocol_buffers{tls_packets = [], tls_ci
next_record(#state{protocol_buffers =
#protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
= Buffers,
- connection_states = ConnStates0} = State) ->
- case tls_record:decode_cipher_text(CT, ConnStates0) of
+ connection_states = ConnStates0,
+ ssl_options = #ssl_options{padding_check = Check}} = State) ->
+ case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
{Plain, ConnStates} ->
{Plain, State#state{protocol_buffers =
Buffers#protocol_buffers{tls_cipher_texts = Rest},
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 3c5c7e9..dd99d10 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-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
@@ -34,7 +34,7 @@
-export([get_tls_records/2]).
%% Decoding
--export([decode_cipher_text/2]).
+-export([decode_cipher_text/3]).
%% Encoding
-export([encode_plain_text/4]).
@@ -137,7 +137,7 @@ encode_plain_text(Type, Version, Data,
{CipherText, ConnectionStates#connection_states{current_write = WriteState#connection_state{sequence_number = Seq +1}}}.
%%--------------------------------------------------------------------
--spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
+-spec decode_cipher_text(#ssl_tls{}, #connection_states{}, boolean()) ->
{#ssl_tls{}, #connection_states{}}| #alert{}.
%%
%% Description: Decode cipher text
@@ -164,6 +164,33 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end.
+decode_cipher_text(#ssl_tls{type = Type, version = Version,
+ fragment = CipherFragment} = CipherText,
+ #connection_states{current_read =
+ #connection_state{
+ compression_state = CompressionS0,
+ sequence_number = Seq,
+ security_parameters=
+ #security_parameters{compression_algorithm=CompAlg}
+ } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
+ case ssl_record:decipher(Version, CipherFragment, ReadState0, PaddingCheck) of
+ {PlainFragment, Mac, ReadState1} ->
+ MacHash = calc_mac_hash(Type, Version, PlainFragment, ReadState1),
+ case ssl_record:is_correct_mac(Mac, MacHash) of
+ true ->
+ {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
+ PlainFragment, CompressionS0),
+ ConnnectionStates = ConnnectionStates0#connection_states{
+ current_read = ReadState1#connection_state{
+ sequence_number = Seq + 1,
+ compression_state = CompressionS1}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+ #alert{} = Alert ->
+ Alert
+ end.
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
tls_version() | tls_atom_version().
diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
index 45e9178..3433f9a 100644
--- a/lib/ssl/test/ssl_cipher_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_SUITE.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
@@ -38,7 +38,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [aes_decipher_good, aes_decipher_good_tls11, aes_decipher_fail, aes_decipher_fail_tls11].
+ [aes_decipher_good, aes_decipher_fail, padding_test].
groups() ->
[].
@@ -73,93 +73,122 @@ end_per_testcase(_TestCase, Config) ->
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
aes_decipher_good() ->
- [{doc,"Decipher a known cryptotext."}].
+ [{doc,"Decipher a known cryptotext using a correct key"}].
aes_decipher_good(Config) when is_list(Config) ->
HashSz = 32,
- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
- Content = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56, "HELLO\n">>,
- Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
- Version = {3,0},
- {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
- Version1 = {3,1},
- {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
- ok.
+ CipherState = correct_cipher_state(),
+ decipher_check_good(HashSz, CipherState, {3,0}),
+ decipher_check_good(HashSz, CipherState, {3,1}),
+ decipher_check_good(HashSz, CipherState, {3,2}),
+ decipher_check_good(HashSz, CipherState, {3,3}).
%%--------------------------------------------------------------------
-
-aes_decipher_good_tls11() ->
- [{doc,"Decipher a known TLS 1.1 cryptotext."}].
-
-%% the fragment is actuall a TLS 1.1 record, with
-%% Version = TLS 1.1, we get the correct NextIV in #cipher_state
-aes_decipher_good_tls11(Config) when is_list(Config) ->
- HashSz = 32,
- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
- Content = <<"HELLO\n">>,
- NextIV = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>,
- Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
- Version = {3,2},
- {Content, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
- Version1 = {3,2},
- {Content, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
- ok.
-
-%%--------------------------------------------------------------------
-
aes_decipher_fail() ->
- [{doc,"Decipher a known cryptotext."}].
+ [{doc,"Decipher a known cryptotext using a incorrect key"}].
-%% same as above, last byte of key replaced
aes_decipher_fail(Config) when is_list(Config) ->
HashSz = 32,
- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
- Version = {3,0},
- {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
- 32 = byte_size(Content),
- 32 = byte_size(Mac),
- Version1 = {3,1},
- {Content1, Mac1, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
- 32 = byte_size(Content1),
- 32 = byte_size(Mac1),
- ok.
+ CipherState = incorrect_cipher_state(),
+ decipher_check_fail(HashSz, CipherState, {3,0}),
+ decipher_check_fail(HashSz, CipherState, {3,1}),
+ decipher_check_fail(HashSz, CipherState, {3,2}),
+ decipher_check_fail(HashSz, CipherState, {3,3}).
%%--------------------------------------------------------------------
-
-aes_decipher_fail_tls11() ->
- [{doc,"Decipher a known TLS 1.1 cryptotext."}].
-
-%% same as above, last byte of key replaced
-%% stricter padding checks in TLS 1.1 mean we get an alert instead
-aes_decipher_fail_tls11(Config) when is_list(Config) ->
- HashSz = 32,
- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
- Version = {3,2},
- #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} =
- ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
- Version1 = {3,3},
- #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} =
- ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
- ok.
-
+padding_test(Config) when is_list(Config) ->
+ HashSz = 16,
+ CipherState = correct_cipher_state(),
+ pad_test(HashSz, CipherState, {3,0}),
+ pad_test(HashSz, CipherState, {3,1}),
+ pad_test(HashSz, CipherState, {3,2}),
+ pad_test(HashSz, CipherState, {3,3}).
+
+%%--------------------------------------------------------------------
+% Internal functions --------------------------------------------------------
%%--------------------------------------------------------------------
+decipher_check_good(HashSz, CipherState, Version) ->
+ {Content, NextIV, Mac} = content_nextiv_mac(Version),
+ {Content, Mac, _} =
+ ssl_cipher:decipher(?AES_CBC, HashSz, CipherState, aes_fragment(Version), Version, true).
+
+decipher_check_fail(HashSz, CipherState, Version) ->
+ {Content, NextIV, Mac} = content_nextiv_mac(Version),
+ true = {Content, Mac, #cipher_state{iv = NextIV}} =/=
+ ssl_cipher:decipher(?AES_CBC, HashSz, CipherState, aes_fragment(Version), Version, true).
+
+pad_test(HashSz, CipherState, {3,0} = Version) ->
+ %% 3.0 does not have padding test
+ {Content, NextIV, Mac} = badpad_content_nextiv_mac(Version),
+ {Content, Mac, #cipher_state{iv = NextIV}} =
+ ssl_cipher:decipher(?AES_CBC, HashSz, CipherState, badpad_aes_fragment({3,0}), {3,0}, true),
+ {Content, Mac, #cipher_state{iv = NextIV}} =
+ ssl_cipher:decipher(?AES_CBC, HashSz, CipherState, badpad_aes_fragment({3,0}), {3,0}, false);
+pad_test(HashSz, CipherState, {3,1} = Version) ->
+ %% 3.1 should have padding test, but may be disabled
+ {Content, NextIV, Mac} = badpad_content_nextiv_mac(Version),
+ BadCont = badpad_content(Content),
+ {Content, Mac, #cipher_state{iv = NextIV}} =
+ ssl_cipher:decipher(?AES_CBC, HashSz, CipherState, badpad_aes_fragment({3,1}) , {3,1}, false),
+ {BadCont, Mac, #cipher_state{iv = NextIV}} =
+ ssl_cipher:decipher(?AES_CBC, HashSz, CipherState, badpad_aes_fragment({3,1}), {3,1}, true);
+pad_test(HashSz, CipherState, Version) ->
+ %% 3.2 and 3.3 must have padding test
+ {Content, NextIV, Mac} = badpad_content_nextiv_mac(Version),
+ BadCont = badpad_content(Content),
+ {BadCont, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES_CBC, HashSz, CipherState,
+ badpad_aes_fragment(Version), Version, false),
+ {BadCont, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES_CBC, HashSz, CipherState,
+ badpad_aes_fragment(Version), Version, true).
+
+aes_fragment({3,N}) when N == 0; N == 1->
+ <<197,9,6,109,242,87,80,154,85,250,110,81,119,95,65,185,53,206,216,153,246,169,
+ 119,177,178,238,248,174,253,220,242,81,33,0,177,251,91,44,247,53,183,198,165,
+ 63,20,194,159,107>>;
+
+aes_fragment(_) ->
+ <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>.
+
+badpad_aes_fragment({3,N}) when N == 0; N == 1 ->
+ <<186,139,125,10,118,21,26,248,120,108,193,104,87,118,145,79,225,55,228,10,105,
+ 30,190,37,1,88,139,243,210,99,65,41>>;
+badpad_aes_fragment(_) ->
+ <<137,31,14,77,228,80,76,103,183,125,55,250,68,190,123,131,117,23,229,180,207,
+ 94,121,137,117,157,109,99,113,61,190,138,131,229,201,120,142,179,172,48,77,
+ 234,19,240,33,38,91,93>>.
+
+content_nextiv_mac({3,N}) when N == 0; N == 1 ->
+ {<<"HELLO\n">>,
+ <<72,196,247,97,62,213,222,109,210,204,217,186,172,184, 197,148>>,
+ <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>};
+content_nextiv_mac(_) ->
+ {<<"HELLO\n">>,
+ <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>,
+ <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>}.
+
+badpad_content_nextiv_mac({3,N}) when N == 0; N == 1 ->
+ {<<"HELLO\n">>,
+ <<225,55,228,10,105,30,190,37,1,88,139,243,210,99,65,41>>,
+ <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>
+ };
+badpad_content_nextiv_mac(_) ->
+ {<<"HELLO\n">>,
+ <<133,211,45,189,179,229,56,86,11,178,239,159,14,160,253,140>>,
+ <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>
+ }.
+
+badpad_content(Content) ->
+ %% BadContent will fail mac test
+ <<16#F0, Content/binary>>.
+
+correct_cipher_state() ->
+ #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>}.
+
+incorrect_cipher_state() ->
+ #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>}.
+

View file

@ -0,0 +1,31 @@
From: John Eckersberg <jeckersb@redhat.com>
Date: Wed, 16 Dec 2015 11:03:42 -0500
Subject: [PATCH] Add patch to crash dump on large distribution
https://bugzilla.redhat.com/show_bug.cgi?id=1291822
https://bugzilla.redhat.com/show_bug.cgi?id=1291855
https://bugzilla.redhat.com/show_bug.cgi?id=1291856
https://bugzilla.redhat.com/show_bug.cgi?id=1291857
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 6ecf3f0..7d1f4ea 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1880,7 +1880,7 @@ dist_port_command(Port *prt, ErtsDistOutputBuf *obuf)
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if (size > (Uint) INT_MAX)
- erl_exit(ERTS_ABORT_EXIT,
+ erl_exit(ERTS_DUMP_EXIT,
"Absurdly large distribution output data buffer "
"(%beu bytes) passed.\n",
size);
@@ -1919,7 +1919,7 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf)
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
if (size > (Uint) INT_MAX)
- erl_exit(ERTS_ABORT_EXIT,
+ erl_exit(ERTS_DUMP_EXIT,
"Absurdly large distribution output data buffer "
"(%beu bytes) passed.\n",
size);

View file

@ -0,0 +1,891 @@
From: Danil Zagoskin <stolen@yandex-team.ru>
Date: Sat, 2 May 2015 00:40:53 +0300
Subject: [PATCH] kernel: inet6_tcp_dist: reuse inet_tcp_dist code
inet6_tcp_dist module is an old copy of inet_tcp_dist with changed
address family.
New features (such as listening port range, interface and generic
options) are implemented in inet_tcp_dist only, inet6_tcp_dist looks
abandoned (it does not even have tests).
This patch makes inet_tcp_dist internals work with abstract driver,
and inet6_tcp_dist becomes just a thin wrapper for it.
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index c714b2b..b31f05b 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.erl
@@ -24,10 +24,29 @@
-export([controlling_process/2]).
-export([fdopen/2]).
+-export([family/0, mask/2, parse_address/1]).
-export([getserv/1, getaddr/1, getaddr/2, getaddrs/1, getaddrs/2]).
-include("inet_int.hrl").
+%% my address family
+family() -> inet6.
+
+%% Apply netmask on address
+mask({M1,M2,M3,M4,M5,M6,M7,M8}, {IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8}) ->
+ {M1 band IP1,
+ M2 band IP2,
+ M3 band IP3,
+ M4 band IP4,
+ M5 band IP5,
+ M6 band IP6,
+ M7 band IP7,
+ M8 band IP8 }.
+
+%% Parse address string
+parse_address(Host) ->
+ inet_parse:ipv6strict_address(Host).
+
%% inet_tcp port lookup
getserv(Port) when is_integer(Port) -> {ok, Port};
getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,tcp).
diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl
index 2cb0e10..1488bf4 100644
--- a/lib/kernel/src/inet6_tcp_dist.erl
+++ b/lib/kernel/src/inet6_tcp_dist.erl
@@ -23,28 +23,6 @@
-export([listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1, is_node_name/1]).
-%% internal exports
-
--export([accept_loop/2,do_accept/6,do_setup/6, getstat/1,tick/1]).
-
--import(error_logger,[error_msg/2]).
-
--include("net_address.hrl").
-
-
-
--define(to_port(Socket, Data, Opts),
- case inet6_tcp:send(Socket, Data, Opts) of
- {error, closed} ->
- self() ! {tcp_closed, Socket},
- {error, closed};
- R ->
- R
- end).
-
-
--include("dist.hrl").
--include("dist_util.hrl").
%% ------------------------------------------------------------
%% Select this protocol based on node name
@@ -52,14 +30,7 @@
%% ------------------------------------------------------------
select(Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_, Host] ->
- case inet:getaddr(Host,inet6) of
- {ok,_} -> true;
- _ -> false
- end;
- _ -> false
- end.
+ inet_tcp_dist:gen_select(inet6_tcp, Node).
%% ------------------------------------------------------------
%% Create the listen socket, i.e. the port that this erlang
@@ -67,59 +38,14 @@ select(Node) ->
%% ------------------------------------------------------------
listen(Name) ->
- case inet6_tcp:listen(0, [{active, false}, {packet,2}]) of
- {ok, Socket} ->
- TcpAddress = get_tcp_address(Socket),
- {_,Port} = TcpAddress#net_address.address,
- case erl_epmd:register_node(Name, Port) of
- {ok, Creation} ->
- {ok, {Socket, TcpAddress, Creation}};
- Error ->
- Error
- end;
- Error ->
- Error
- end.
+ inet_tcp_dist:gen_listen(inet6_tcp, Name).
%% ------------------------------------------------------------
%% Accepts new connection attempts from other Erlang nodes.
%% ------------------------------------------------------------
accept(Listen) ->
- spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]).
-
-accept_loop(Kernel, Listen) ->
- case inet6_tcp:accept(Listen) of
- {ok, Socket} ->
- Kernel ! {accept,self(),Socket,inet6,tcp},
- controller(Kernel, Socket),
- accept_loop(Kernel, Listen);
- Error ->
- exit(Error)
- end.
-
-controller(Kernel, Socket) ->
- receive
- {Kernel, controller, Pid} ->
- flush_controller(Pid, Socket),
- inet6_tcp:controlling_process(Socket, Pid),
- flush_controller(Pid, Socket),
- Pid ! {self(), controller};
- {Kernel, unsupported_protocol} ->
- exit(unsupported_protocol)
- end.
-
-flush_controller(Pid, Socket) ->
- receive
- {tcp, Socket, Data} ->
- Pid ! {tcp, Socket, Data},
- flush_controller(Pid, Socket);
- {tcp_closed, Socket} ->
- Pid ! {tcp_closed, Socket},
- flush_controller(Pid, Socket)
- after 0 ->
- ok
- end.
+ inet_tcp_dist:gen_accept(inet6_tcp, Listen).
%% ------------------------------------------------------------
%% Accepts a new connection attempt from another Erlang node.
@@ -127,85 +53,7 @@ flush_controller(Pid, Socket) ->
%% ------------------------------------------------------------
accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- spawn_opt(?MODULE, do_accept,
- [self(), AcceptPid, Socket, MyNode, Allowed, SetupTime],
- [link, {priority, max}]).
-
-do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- receive
- {AcceptPid, controller} ->
- Timer = dist_util:start_timer(SetupTime),
- case check_ip(Socket) of
- true ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- allowed = Allowed,
- f_send = fun(S,D) -> inet6_tcp:send(S,D) end,
- f_recv = fun(S,N,T) -> inet6_tcp:recv(S,N,T)
- end,
- f_setopts_pre_nodeup =
- fun(S) ->
- inet:setopts(S,
- [{active, false},
- {packet, 4},
- nodelay()])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- inet:setopts(S,
- [{active, true},
- {deliver, port},
- {packet, 4},
- nodelay()])
- end,
- f_getll = fun(S) ->
- inet:getll(S)
- end,
- f_address = fun get_remote_id/2,
- mf_tick = fun ?MODULE:tick/1,
- mf_getstat = fun ?MODULE:getstat/1
- },
- dist_util:handshake_other_started(HSData);
- {false,IP} ->
- error_msg("** Connection attempt from "
- "disallowed IP ~w ** ~n", [IP]),
- ?shutdown(no_node)
- end
- end.
-
-
-%% we may not always want the nodelay behaviour
-%% for performance reasons
-
-nodelay() ->
- case application:get_env(kernel, dist_nodelay) of
- undefined ->
- {nodelay, true};
- {ok, true} ->
- {nodelay, true};
- {ok, false} ->
- {nodelay, false};
- _ ->
- {nodelay, true}
- end.
-
-
-%% ------------------------------------------------------------
-%% Get remote information about a Socket.
-%% ------------------------------------------------------------
-
-get_remote_id(Socket, Node) ->
- {ok, Address} = inet:peername(Socket),
- [_, Host] = split_node(atom_to_list(Node), $@, []),
- #net_address {
- address = Address,
- host = Host,
- protocol = tcp,
- family = inet6 }.
+ inet_tcp_dist:gen_accept_connection(inet6_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime).
%% ------------------------------------------------------------
%% Setup a new connection to another Erlang node.
@@ -213,214 +61,13 @@ get_remote_id(Socket, Node) ->
%% ------------------------------------------------------------
setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- spawn_opt(?MODULE, do_setup,
- [self(), Node, Type, MyNode, LongOrShortNames, SetupTime],
- [link, {priority, max}]).
-
-do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- ?trace("~p~n",[{?MODULE,self(),setup,Node}]),
- [Name, Address] = splitnode(Node, LongOrShortNames),
- case inet:getaddr(Address, inet6) of
- {ok, Ip} ->
- Timer = dist_util:start_timer(SetupTime),
- case erl_epmd:port_please(Name, Ip) of
- {port, TcpPort, Version} ->
- ?trace("port_please(~p) -> version ~p~n",
- [Node,Version]),
- dist_util:reset_timer(Timer),
- case inet6_tcp:connect(Ip, TcpPort,
- [{active, false},
- {packet,2}]) of
- {ok, Socket} ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- other_node = Node,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- other_version = Version,
- f_send = fun inet6_tcp:send/2,
- f_recv = fun inet6_tcp:recv/3,
- f_setopts_pre_nodeup =
- fun(S) ->
- inet:setopts
- (S,
- [{active, false},
- {packet, 4},
- nodelay()])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- inet:setopts
- (S,
- [{active, true},
- {deliver, port},
- {packet, 4},
- nodelay()])
- end,
- f_getll = fun inet:getll/1,
- f_address =
- fun(_,_) ->
- #net_address {
- address = {Ip,TcpPort},
- host = Address,
- protocol = tcp,
- family = inet6}
- end,
- mf_tick = fun ?MODULE:tick/1,
- mf_getstat = fun ?MODULE:getstat/1,
- request_type = Type
- },
- dist_util:handshake_we_started(HSData);
- _ ->
- %% Other Node may have closed since
- %% port_please !
- ?trace("other node (~p) "
- "closed since port_please.~n",
- [Node]),
- ?shutdown(Node)
- end;
- _ ->
- ?trace("port_please (~p) "
- "failed.~n", [Node]),
- ?shutdown(Node)
- end;
- __Other ->
- ?trace("inet_getaddr(~p) "
- "failed (~p).~n", [Node,__Other]),
- ?shutdown(Node)
- end.
+ inet_tcp_dist:gen_setup(inet6_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime).
%%
%% Close a socket.
%%
close(Socket) ->
inet6_tcp:close(Socket).
-
-
-%% If Node is illegal terminate the connection setup!!
-splitnode(Node, LongOrShortNames) ->
- case split_node(atom_to_list(Node), $@, []) of
- [Name|Tail] when Tail =/= [] ->
- Host = lists:append(Tail),
- case split_node(Host, $., []) of
- [_] when LongOrShortNames =:= longnames ->
- case inet_parse:ipv6strict_address(Host) of
- {ok, _} ->
- [Name, Host];
- _ ->
- error_msg("** System running to use "
- "fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node)
- end;
- L when length(L) > 1, LongOrShortNames =:= shortnames ->
- error_msg("** System NOT running to use fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
- _ ->
- [Name, Host]
- end;
- [_] ->
- error_msg("** Nodename ~p illegal, no '@' character **~n",
- [Node]),
- ?shutdown(Node);
- _ ->
- error_msg("** Nodename ~p illegal **~n", [Node]),
- ?shutdown(Node)
- end.
-
-split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])];
-split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]);
-split_node([], _, Ack) -> [lists:reverse(Ack)].
-
-%% ------------------------------------------------------------
-%% Fetch local information about a Socket.
-%% ------------------------------------------------------------
-get_tcp_address(Socket) ->
- {ok, Address} = inet:sockname(Socket),
- {ok, Host} = inet:gethostname(),
- #net_address {
- address = Address,
- host = Host,
- protocol = tcp,
- family = inet6
- }.
-
-%% ------------------------------------------------------------
-%% Do only accept new connection attempts from nodes at our
-%% own LAN, if the check_ip environment parameter is true.
-%% ------------------------------------------------------------
-check_ip(Socket) ->
- case application:get_env(check_ip) of
- {ok, true} ->
- case get_ifs(Socket) of
- {ok, IFs, IP} ->
- check_ip(IFs, IP);
- _ ->
- ?shutdown(no_node)
- end;
- _ ->
- true
- end.
-
-get_ifs(Socket) ->
- case inet:peername(Socket) of
- {ok, {IP, _}} ->
- case inet:getif(Socket) of
- {ok, IFs} -> {ok, IFs, IP};
- Error -> Error
- end;
- Error ->
- Error
- end.
-
-check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
- case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of
- {M, M} -> true;
- _ -> check_ip(IFs, PeerIP)
- end;
-check_ip([], PeerIP) ->
- {false, PeerIP}.
-mask({M1,M2,M3,M4,M5,M6,M7,M8}, {IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8}) ->
- {M1 band IP1,
- M2 band IP2,
- M3 band IP3,
- M4 band IP4,
- M5 band IP5,
- M6 band IP6,
- M7 band IP7,
- M8 band IP8 }.
-
is_node_name(Node) when is_atom(Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_,_Host] -> true;
- _ -> false
- end;
-is_node_name(_Node) ->
- false.
-tick(Sock) ->
- ?to_port(Sock,[],[force]).
-getstat(Socket) ->
- case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of
- {ok, Stat} ->
- split_stat(Stat,0,0,0);
- Error ->
- Error
- end.
-
-split_stat([{recv_cnt, R}|Stat], _, W, P) ->
- split_stat(Stat, R, W, P);
-split_stat([{send_cnt, W}|Stat], R, _, P) ->
- split_stat(Stat, R, W, P);
-split_stat([{send_pend, P}|Stat], R, W, _) ->
- split_stat(Stat, R, W, P);
-split_stat([], R, W, P) ->
- {ok, R, W, P}.
-
+ inet_tcp_dist:is_node_name(Node).
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index 4c2db16..71d35ca 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.erl
@@ -26,11 +26,25 @@
-export([controlling_process/2]).
-export([fdopen/2]).
+-export([family/0, mask/2, parse_address/1]).
-export([getserv/1, getaddr/1, getaddr/2, getaddrs/1, getaddrs/2]).
-
-include("inet_int.hrl").
+%% my address family
+family() -> inet.
+
+%% Apply netmask on address
+mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) ->
+ {M1 band IP1,
+ M2 band IP2,
+ M3 band IP3,
+ M4 band IP4}.
+
+%% Parse address string
+parse_address(Host) ->
+ inet_parse:ipv4strict_address(Host).
+
%% inet_tcp port lookup
getserv(Port) when is_integer(Port) -> {ok, Port};
getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,tcp).
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index 8005eff..0739cf3 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -23,9 +23,13 @@
-export([listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1, is_node_name/1]).
+%% Generalized dist API
+-export([gen_listen/2, gen_accept/2, gen_accept_connection/6,
+ gen_setup/6, gen_select/2]).
+
%% internal exports
--export([accept_loop/2,do_accept/6,do_setup/6,getstat/1,tick/1]).
+-export([accept_loop/3,do_accept/7,do_setup/7,getstat/1]).
-import(error_logger,[error_msg/2]).
@@ -33,15 +37,6 @@
--define(to_port(Socket, Data, Opts),
- case inet_tcp:send(Socket, Data, Opts) of
- {error, closed} ->
- self() ! {tcp_closed, Socket},
- {error, closed};
- R ->
- R
- end).
-
-include("dist.hrl").
-include("dist_util.hrl").
@@ -52,8 +47,15 @@
%% ------------------------------------------------------------
select(Node) ->
+ gen_select(inet_tcp, Node).
+
+gen_select(Driver, Node) ->
case split_node(atom_to_list(Node), $@, []) of
- [_,_Host] -> true;
+ [_, Host] ->
+ case inet:getaddr(Host, Driver:family()) of
+ {ok,_} -> true;
+ _ -> false
+ end;
_ -> false
end.
@@ -63,9 +65,12 @@ select(Node) ->
%% ------------------------------------------------------------
listen(Name) ->
- case do_listen([{active, false}, {packet,2}, {reuseaddr, true}]) of
+ gen_listen(inet_tcp, Name).
+
+gen_listen(Driver, Name) ->
+ case do_listen(Driver, [{active, false}, {packet,2}, {reuseaddr, true}]) of
{ok, Socket} ->
- TcpAddress = get_tcp_address(Socket),
+ TcpAddress = get_tcp_address(Driver, Socket),
{_,Port} = TcpAddress#net_address.address,
case erl_epmd:register_node(Name, Port) of
{ok, Creation} ->
@@ -77,7 +82,7 @@ listen(Name) ->
Error
end.
-do_listen(Options0) ->
+do_listen(Driver, Options) ->
{First,Last} = case application:get_env(kernel,inet_dist_listen_min) of
{ok,N} when is_integer(N) ->
case application:get_env(kernel,
@@ -90,46 +95,60 @@ do_listen(Options0) ->
_ ->
{0,0}
end,
- Options = case application:get_env(kernel, inet_dist_use_interface) of
- {ok, Ip} ->
- [{ip, Ip} | Options0];
- _ ->
- Options0
- end,
- do_listen(First, Last, [{backlog,128}|Options]).
-
-do_listen(First,Last,_) when First > Last ->
+ do_listen(Driver, First, Last, listen_options([{backlog,128}|Options])).
+
+do_listen(_Driver, First,Last,_) when First > Last ->
{error,eaddrinuse};
-do_listen(First,Last,Options) ->
- case inet_tcp:listen(First, Options) of
+do_listen(Driver, First,Last,Options) ->
+ case Driver:listen(First, Options) of
{error, eaddrinuse} ->
- do_listen(First+1,Last,Options);
+ do_listen(Driver, First+1,Last,Options);
Other ->
Other
end.
+listen_options(Opts0) ->
+ Opts1 =
+ case application:get_env(kernel, inet_dist_use_interface) of
+ {ok, Ip} ->
+ [{ip, Ip} | Opts0];
+ _ ->
+ Opts0
+ end,
+ case application:get_env(kernel, inet_dist_listen_options) of
+ {ok,ListenOpts} ->
+ erlang:display({inet_dist_listen_options, ListenOpts}),
+ ListenOpts ++ Opts1;
+ _ ->
+ Opts1
+ end.
+
+
%% ------------------------------------------------------------
%% Accepts new connection attempts from other Erlang nodes.
%% ------------------------------------------------------------
accept(Listen) ->
- spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]).
+ gen_accept(inet_tcp, Listen).
-accept_loop(Kernel, Listen) ->
- case inet_tcp:accept(Listen) of
+gen_accept(Driver, Listen) ->
+ spawn_opt(?MODULE, accept_loop, [Driver, self(), Listen], [link, {priority, max}]).
+
+accept_loop(Driver, Kernel, Listen) ->
+ case Driver:accept(Listen) of
{ok, Socket} ->
- Kernel ! {accept,self(),Socket,inet,tcp},
- controller(Kernel, Socket),
- accept_loop(Kernel, Listen);
+ Kernel ! {accept,self(),Socket,Driver:family(),tcp},
+ _ = controller(Driver, Kernel, Socket),
+ accept_loop(Driver, Kernel, Listen);
Error ->
exit(Error)
end.
-controller(Kernel, Socket) ->
+controller(Driver, Kernel, Socket) ->
receive
{Kernel, controller, Pid} ->
flush_controller(Pid, Socket),
- inet_tcp:controlling_process(Socket, Pid),
+ Driver:controlling_process(Socket, Pid),
flush_controller(Pid, Socket),
Pid ! {self(), controller};
{Kernel, unsupported_protocol} ->
@@ -154,15 +173,18 @@ flush_controller(Pid, Socket) ->
%% ------------------------------------------------------------
accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+ gen_accept_connection(inet_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime).
+
+gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
spawn_opt(?MODULE, do_accept,
- [self(), AcceptPid, Socket, MyNode, Allowed, SetupTime],
+ [Driver, self(), AcceptPid, Socket, MyNode, Allowed, SetupTime],
[link, {priority, max}]).
-do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
receive
{AcceptPid, controller} ->
Timer = dist_util:start_timer(SetupTime),
- case check_ip(Socket) of
+ case check_ip(Driver, Socket) of
true ->
HSData = #hs_data{
kernel_pid = Kernel,
@@ -171,9 +193,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
timer = Timer,
this_flags = 0,
allowed = Allowed,
- f_send = fun(S,D) -> inet_tcp:send(S,D) end,
- f_recv = fun(S,N,T) -> inet_tcp:recv(S,N,T)
- end,
+ f_send = fun Driver:send/2,
+ f_recv = fun Driver:recv/3,
f_setopts_pre_nodeup =
fun(S) ->
inet:setopts(S,
@@ -192,8 +213,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
f_getll = fun(S) ->
inet:getll(S)
end,
- f_address = fun get_remote_id/2,
- mf_tick = fun ?MODULE:tick/1,
+ f_address = fun(S, Node) -> get_remote_id(Driver, S, Node) end,
+ mf_tick = fun(S) -> tick(Driver, S) end,
mf_getstat = fun ?MODULE:getstat/1
},
dist_util:handshake_other_started(HSData);
@@ -224,13 +245,13 @@ nodelay() ->
%% ------------------------------------------------------------
%% Get remote information about a Socket.
%% ------------------------------------------------------------
-get_remote_id(Socket, Node) ->
+get_remote_id(Driver, Socket, Node) ->
case inet:peername(Socket) of
{ok,Address} ->
case split_node(atom_to_list(Node), $@, []) of
[_,Host] ->
#net_address{address=Address,host=Host,
- protocol=tcp,family=inet};
+ protocol=tcp,family=Driver:family()};
_ ->
%% No '@' or more than one '@' in node name.
?shutdown(no_node)
@@ -245,14 +266,18 @@ get_remote_id(Socket, Node) ->
%% ------------------------------------------------------------
setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
+ gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime).
+
+gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
spawn_opt(?MODULE, do_setup,
- [self(), Node, Type, MyNode, LongOrShortNames, SetupTime],
+ [Driver, self(), Node, Type, MyNode, LongOrShortNames, SetupTime],
[link, {priority, max}]).
-do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
+do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
?trace("~p~n",[{inet_tcp_dist,self(),setup,Node}]),
- [Name, Address] = splitnode(Node, LongOrShortNames),
- case inet:getaddr(Address, inet) of
+ [Name, Address] = splitnode(Driver, Node, LongOrShortNames),
+ AddressFamily = Driver:family(),
+ case inet:getaddr(Address, AddressFamily) of
{ok, Ip} ->
Timer = dist_util:start_timer(SetupTime),
case erl_epmd:port_please(Name, Ip) of
@@ -260,9 +285,11 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
?trace("port_please(~p) -> version ~p~n",
[Node,Version]),
dist_util:reset_timer(Timer),
- case inet_tcp:connect(Ip, TcpPort,
- [{active, false},
- {packet,2}]) of
+ case
+ Driver:connect(
+ Ip, TcpPort,
+ connect_options([{active, false}, {packet, 2}]))
+ of
{ok, Socket} ->
HSData = #hs_data{
kernel_pid = Kernel,
@@ -272,8 +299,8 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
timer = Timer,
this_flags = 0,
other_version = Version,
- f_send = fun inet_tcp:send/2,
- f_recv = fun inet_tcp:recv/3,
+ f_send = fun Driver:send/2,
+ f_recv = fun Driver:recv/3,
f_setopts_pre_nodeup =
fun(S) ->
inet:setopts
@@ -298,9 +325,9 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
address = {Ip,TcpPort},
host = Address,
protocol = tcp,
- family = inet}
+ family = AddressFamily}
end,
- mf_tick = fun ?MODULE:tick/1,
+ mf_tick = fun(S) -> tick(Driver, S) end,
mf_getstat = fun ?MODULE:getstat/1,
request_type = Type
},
@@ -324,6 +351,15 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
?shutdown(Node)
end.
+connect_options(Opts) ->
+ case application:get_env(kernel, inet_dist_connect_options) of
+ {ok,ConnectOpts} ->
+ erlang:display({inet_dist_connect_options, ConnectOpts}),
+ ConnectOpts ++ Opts;
+ _ ->
+ Opts
+ end.
+
%%
%% Close a socket.
%%
@@ -332,18 +368,23 @@ close(Socket) ->
%% If Node is illegal terminate the connection setup!!
-splitnode(Node, LongOrShortNames) ->
+splitnode(Driver, Node, LongOrShortNames) ->
case split_node(atom_to_list(Node), $@, []) of
[Name|Tail] when Tail =/= [] ->
Host = lists:append(Tail),
case split_node(Host, $., []) of
[_] when LongOrShortNames =:= longnames ->
- error_msg("** System running to use "
- "fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
+ case Driver:parse_address(Host) of
+ {ok, _} ->
+ [Name, Host];
+ _ ->
+ error_msg("** System running to use "
+ "fully qualified "
+ "hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown(Node)
+ end;
L when length(L) > 1, LongOrShortNames =:= shortnames ->
error_msg("** System NOT running to use fully qualified "
"hostnames **~n"
@@ -369,26 +410,26 @@ split_node([], _, Ack) -> [lists:reverse(Ack)].
%% ------------------------------------------------------------
%% Fetch local information about a Socket.
%% ------------------------------------------------------------
-get_tcp_address(Socket) ->
+get_tcp_address(Driver, Socket) ->
{ok, Address} = inet:sockname(Socket),
{ok, Host} = inet:gethostname(),
#net_address {
address = Address,
host = Host,
protocol = tcp,
- family = inet
+ family = Driver:family()
}.
%% ------------------------------------------------------------
%% Do only accept new connection attempts from nodes at our
%% own LAN, if the check_ip environment parameter is true.
%% ------------------------------------------------------------
-check_ip(Socket) ->
+check_ip(Driver, Socket) ->
case application:get_env(check_ip) of
{ok, true} ->
case get_ifs(Socket) of
{ok, IFs, IP} ->
- check_ip(IFs, IP);
+ check_ip(Driver, IFs, IP);
_ ->
?shutdown(no_node)
end;
@@ -407,20 +448,14 @@ get_ifs(Socket) ->
Error
end.
-check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
- case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of
+check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) ->
+ case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of
{M, M} -> true;
- _ -> check_ip(IFs, PeerIP)
+ _ -> check_ip(Driver, IFs, PeerIP)
end;
-check_ip([], PeerIP) ->
+check_ip(_Driver, [], PeerIP) ->
{false, PeerIP}.
-mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) ->
- {M1 band IP1,
- M2 band IP2,
- M3 band IP3,
- M4 band IP4}.
-
is_node_name(Node) when is_atom(Node) ->
case split_node(atom_to_list(Node), $@, []) of
[_, _Host] -> true;
@@ -429,8 +464,14 @@ is_node_name(Node) when is_atom(Node) ->
is_node_name(_Node) ->
false.
-tick(Sock) ->
- ?to_port(Sock,[],[force]).
+tick(Driver, Socket) ->
+ case Driver:send(Socket, [], [force]) of
+ {error, closed} ->
+ self() ! {tcp_closed, Socket},
+ {error, closed};
+ R ->
+ R
+ end.
getstat(Socket) ->
case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of

View file

@ -0,0 +1,737 @@
From: Michael Santos <michael.santos@gmail.com>
Date: Sun, 18 Oct 2015 16:20:37 -0400
Subject: [PATCH] epmd: support IPv6 node registration
Allow IPv6 nodes to register with and query epmd. On systems with
IPv6 support:
* epmd listens on both the IPv4 and IPv6 ANY or loopback sockets
* the epmd cli client connects to epmd over the IPv6 loopback
* distributed nodes started with "-proto_dist inet6_tcp" will register
with epmd over IPv6
To work on IPv6 capable systems that have IPv6 support disabled,
epmd ignores errors opening the socket if the protocol is not
supported. Similarly, the epmd client will fall back to IPv4 if the IPv6
socket is not available.
Update the minimum supported version of Windows to Windows Vista to
support IPv6.
diff --git a/erts/configure.in b/erts/configure.in
index d9bc1ec..756f3cb 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -424,7 +424,7 @@ case $host_os in
win32)
# The ethread library requires _WIN32_WINNT of at least 0x0403.
# -D_WIN32_WINNT=* from CPPFLAGS is saved in ETHR_DEFS.
- CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0501 -DWINVER=0x0501"
+ CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600 -DWINVER=0x0600"
;;
darwin*)
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE"
diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml
index 3e70054..3c9313e 100644
--- a/erts/doc/src/epmd.xml
+++ b/erts/doc/src/epmd.xml
@@ -36,7 +36,7 @@
<comsummary>
<p>Erlang Port Mapper Daemon</p>
<taglist>
- <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-port No] [-daemon] [-relaxed_command_check]]]></c></tag>
+ <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-address Addresses] [-port No] [-daemon] [-relaxed_command_check]]]></c></tag>
<item>
<p>Starts the port mapper daemon</p>
</item>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 528a2d9..0b8f821 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -381,6 +381,33 @@
similar to <c><![CDATA[code:add_pathsz/1]]></c>. See
<seealso marker="kernel:code">code(3)</seealso>.</p>
</item>
+ <tag><c><![CDATA[-path Dir1 Dir2 ...]]></c></tag>
+ <item>
+ <p>Replaces the path specified in the boot script. See
+ <seealso marker="sasl:script">script(4)</seealso>.</p>
+ </item>
+ <tag><c><![CDATA[-proto_dist Proto]]></c></tag>
+ <item>
+ <p>Specify a protocol for Erlang distribution.</p>
+ <taglist>
+ <tag><c>inet_tcp</c></tag>
+ <item>
+ <p>TCP over IPv4 (the default)</p>
+ </item>
+ <tag><c>inet_tls</c></tag>
+ <item>
+ <p>distribution over TLS/SSL</p>
+ </item>
+ <tag><c>inet6_tcp</c></tag>
+ <item>
+ <p>TCP over IPv6</p>
+ </item>
+ </taglist>
+ <p>For example, to start up IPv6 distributed nodes:</p>
+<pre>
+% <input>erl -name test@ipv6node.example.com -proto_dist inet6_tcp</input>
+</pre>
+ </item>
<tag><c><![CDATA[-remsh Node]]></c></tag>
<item>
<p>Starts Erlang with a remote shell connected to <c><![CDATA[Node]]></c>.</p>
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 1757fa9..ebae0a5 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -342,7 +342,7 @@ static void run_daemon(EpmdVars *g)
for (fd = 0; fd < g->max_conn ; fd++) /* close all files ... */
close(fd);
/* Syslog on linux will try to write to whatever if we dont
- inform it of that the log is closed. */
+ inform it that the log is closed. */
closelog();
/* These chouldn't be needed but for safety... */
diff --git a/erts/epmd/src/epmd_cli.c b/erts/epmd/src/epmd_cli.c
index 8817bde..ea7dac7 100644
--- a/erts/epmd/src/epmd_cli.c
+++ b/erts/epmd/src/epmd_cli.c
@@ -135,19 +135,33 @@ void epmd_call(EpmdVars *g,int what)
static int conn_to_epmd(EpmdVars *g)
{
struct EPMD_SOCKADDR_IN address;
+ size_t salen = 0;
int connect_sock;
-
- connect_sock = socket(FAMILY, SOCK_STREAM, 0);
- if (connect_sock<0)
- goto error;
+ unsigned short sport = g->port;
+
+#if defined(EPMD6)
+ SET_ADDR6(address, in6addr_loopback, sport);
+ salen = sizeof(struct sockaddr_in6);
+
+ connect_sock = socket(AF_INET6, SOCK_STREAM, 0);
+ if (connect_sock>=0) {
+
+ if (connect(connect_sock, (struct sockaddr*)&address, salen) == 0)
+ return connect_sock;
- { /* store port number in unsigned short */
- unsigned short sport = g->port;
- SET_ADDR(address, EPMD_ADDR_LOOPBACK, sport);
+ close(connect_sock);
}
+#endif
+ SET_ADDR(address, htonl(INADDR_LOOPBACK), sport);
+ salen = sizeof(struct sockaddr_in);
- if (connect(connect_sock, (struct sockaddr*)&address, sizeof address) < 0)
+ connect_sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (connect_sock<0)
goto error;
+
+ if (connect(connect_sock, (struct sockaddr*)&address, salen) < 0)
+ goto error;
+
return connect_sock;
error:
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 363923e..c6d9173 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -47,6 +47,7 @@
# ifndef WINDOWS_H_INCLUDES_WINSOCK2_H
# include <winsock2.h>
# endif
+# include <ws2tcpip.h>
# include <windows.h>
# include <process.h>
#endif
@@ -114,6 +115,10 @@
# include <systemd/sd-daemon.h>
#endif
+#if defined(HAVE_IN6) && defined(AF_INET6) && defined(HAVE_INET_PTON)
+# define EPMD6
+#endif
+
/* ************************************************************************ */
/* Replace some functions by others by making the function name a macro */
@@ -167,33 +172,53 @@
/* ************************************************************************ */
/* Macros that let us use IPv6 */
-#if defined(HAVE_IN6) && defined(AF_INET6) && defined(EPMD6)
+#if HAVE_IN6
+# if ! defined(HAVE_IN6ADDR_ANY) || ! HAVE_IN6ADDR_ANY
+# if HAVE_DECL_IN6ADDR_ANY_INIT
+static const struct in6_addr in6addr_any = { { IN6ADDR_ANY_INIT } };
+# else
+static const struct in6_addr in6addr_any =
+ { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
+# endif /* HAVE_IN6ADDR_ANY_INIT */
+# endif /* ! HAVE_DECL_IN6ADDR_ANY */
+
+# if ! defined(HAVE_IN6ADDR_LOOPBACK) || ! HAVE_IN6ADDR_LOOPBACK
+# if HAVE_DECL_IN6ADDR_LOOPBACK_INIT
+static const struct in6_addr in6addr_loopback =
+ { { IN6ADDR_LOOPBACK_INIT } };
+# else
+static const struct in6_addr in6addr_loopback =
+ { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } };
+# endif /* HAVE_IN6ADDR_LOOPBACK_INIT */
+# endif /* ! HAVE_DECL_IN6ADDR_LOOPBACK */
+#endif /* HAVE_IN6 */
+
+#define IS_ADDR_LOOPBACK(addr) ((addr).s_addr == htonl(INADDR_LOOPBACK))
+
+#if defined(EPMD6)
-#define EPMD_SOCKADDR_IN sockaddr_in6
-#define EPMD_IN_ADDR in6_addr
-#define EPMD_S_ADDR s6_addr
-#define EPMD_ADDR_LOOPBACK in6addr_loopback.s6_addr
-#define EPMD_ADDR_ANY in6addr_any.s6_addr
+#define EPMD_SOCKADDR_IN sockaddr_storage
#define FAMILY AF_INET6
-#define SET_ADDR(dst, addr, port) do { \
- memset((char*)&(dst), 0, sizeof(dst)); \
- memcpy((char*)&(dst).sin6_addr.s6_addr, (char*)&(addr), 16); \
- (dst).sin6_family = AF_INET6; \
- (dst).sin6_flowinfo = 0; \
- (dst).sin6_port = htons(port); \
+#define SET_ADDR6(dst, addr, port) do { \
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *)&(dst); \
+ memset(sa, 0, sizeof(dst)); \
+ sa->sin6_family = AF_INET6; \
+ sa->sin6_addr = (addr); \
+ sa->sin6_port = htons(port); \
} while(0)
-#define IS_ADDR_LOOPBACK(addr) \
- (memcmp((addr).s6_addr, in6addr_loopback.s6_addr, 16) == 0)
+#define SET_ADDR(dst, addr, port) do { \
+ struct sockaddr_in *sa = (struct sockaddr_in *)&(dst); \
+ memset(sa, 0, sizeof(dst)); \
+ sa->sin_family = AF_INET; \
+ sa->sin_addr.s_addr = (addr); \
+ sa->sin_port = htons(port); \
+ } while(0)
#else /* Not IP v6 */
#define EPMD_SOCKADDR_IN sockaddr_in
-#define EPMD_IN_ADDR in_addr
-#define EPMD_S_ADDR s_addr
-#define EPMD_ADDR_LOOPBACK htonl(INADDR_LOOPBACK)
-#define EPMD_ADDR_ANY htonl(INADDR_ANY)
#define FAMILY AF_INET
#define SET_ADDR(dst, addr, port) do { \
@@ -203,8 +228,6 @@
(dst).sin_port = htons(port); \
} while(0)
-#define IS_ADDR_LOOPBACK(addr) ((addr).s_addr == htonl(INADDR_LOOPBACK))
-
#endif /* Not IP v6 */
/* ************************************************************************ */
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 78524a6..28e30d4 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -70,6 +70,7 @@ static time_t current_time(EpmdVars*);
static Connection *conn_init(EpmdVars*);
static int conn_open(EpmdVars*,int);
+static int conn_local_peer_check(EpmdVars*, int);
static int conn_close_fd(EpmdVars*,int);
static void node_init(EpmdVars*);
@@ -200,10 +201,11 @@ void run(EpmdVars *g)
{
struct EPMD_SOCKADDR_IN iserv_addr[MAX_LISTEN_SOCKETS];
int listensock[MAX_LISTEN_SOCKETS];
- int num_sockets;
+ int num_sockets = 0;
int i;
int opt;
unsigned short sport = g->port;
+ int bound = 0;
node_init(g);
g->conn = conn_init(g);
@@ -246,64 +248,82 @@ void run(EpmdVars *g)
if (g->addresses != NULL && /* String contains non-separator characters if: */
g->addresses[strspn(g->addresses," ,")] != '\000')
{
- char *tmp;
- char *token;
- int loopback_ok = 0;
+ char *tmp = NULL;
+ char *token = NULL;
+
+ /* Always listen on the loopback. */
+ SET_ADDR(iserv_addr[num_sockets],htonl(INADDR_LOOPBACK),sport);
+ num_sockets++;
+#if defined(EPMD6)
+ SET_ADDR6(iserv_addr[num_sockets],in6addr_loopback,sport);
+ num_sockets++;
+#endif
- if ((tmp = (char *)malloc(strlen(g->addresses) + 1)) == NULL)
+ if ((tmp = strdup(g->addresses)) == NULL)
{
dbg_perror(g,"cannot allocate memory");
epmd_cleanup_exit(g,1);
}
- strcpy(tmp,g->addresses);
- for(token = strtok(tmp,", "), num_sockets = 0;
+ for(token = strtok(tmp,", ");
token != NULL;
- token = strtok(NULL,", "), num_sockets++)
+ token = strtok(NULL,", "))
{
- struct EPMD_IN_ADDR addr;
-#ifdef HAVE_INET_PTON
- int ret;
+ struct in_addr addr;
+#if defined(EPMD6)
+ struct in6_addr addr6;
+ struct sockaddr_storage *sa = &iserv_addr[num_sockets];
- if ((ret = inet_pton(FAMILY,token,&addr)) == -1)
+ if (inet_pton(AF_INET6,token,&addr6) == 1)
{
- dbg_perror(g,"cannot convert IP address to network format");
- epmd_cleanup_exit(g,1);
+ SET_ADDR6(iserv_addr[num_sockets],addr6,sport);
+ }
+ else if (inet_pton(AF_INET,token,&addr) == 1)
+ {
+ SET_ADDR(iserv_addr[num_sockets],addr.s_addr,sport);
+ }
+ else
+#else
+ if ((addr.s_addr = inet_addr(token)) != INADDR_NONE)
+ {
+ SET_ADDR(iserv_addr[num_sockets],addr.s_addr,sport);
}
- else if (ret == 0)
-#elif !defined(EPMD6)
- if ((addr.EPMD_S_ADDR = inet_addr(token)) == INADDR_NONE)
+ else
#endif
{
dbg_tty_printf(g,0,"cannot parse IP address \"%s\"",token);
epmd_cleanup_exit(g,1);
}
+#if defined(EPMD6)
+ if (sa->ss_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&addr6))
+ continue;
+
+ if (sa->ss_family == AF_INET)
+#endif
if (IS_ADDR_LOOPBACK(addr))
- loopback_ok = 1;
+ continue;
- if (num_sockets - loopback_ok == MAX_LISTEN_SOCKETS - 1)
+ num_sockets++;
+
+ if (num_sockets >= MAX_LISTEN_SOCKETS)
{
dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses",
MAX_LISTEN_SOCKETS);
epmd_cleanup_exit(g,1);
}
-
- SET_ADDR(iserv_addr[num_sockets],addr.EPMD_S_ADDR,sport);
}
free(tmp);
-
- if (!loopback_ok)
- {
- SET_ADDR(iserv_addr[num_sockets],EPMD_ADDR_LOOPBACK,sport);
- num_sockets++;
- }
}
else
{
- SET_ADDR(iserv_addr[0],EPMD_ADDR_ANY,sport);
- num_sockets = 1;
+ SET_ADDR(iserv_addr[num_sockets],htonl(INADDR_ANY),sport);
+ num_sockets++;
+#if defined(EPMD6)
+ SET_ADDR6(iserv_addr[num_sockets],in6addr_any,sport);
+ num_sockets++;
+#endif
}
#ifdef HAVE_SYSTEMD_SD_DAEMON_H
}
@@ -334,13 +354,39 @@ void run(EpmdVars *g)
#endif
for (i = 0; i < num_sockets; i++)
{
- if ((listensock[i] = socket(FAMILY,SOCK_STREAM,0)) < 0)
+ struct sockaddr *sa = (struct sockaddr *)&iserv_addr[i];
+#if defined(EPMD6)
+ size_t salen = (sa->sa_family == AF_INET6 ?
+ sizeof(struct sockaddr_in6) :
+ sizeof(struct sockaddr_in));
+#else
+ size_t salen = sizeof(struct sockaddr_in);
+#endif
+
+ if ((listensock[i] = socket(sa->sa_family,SOCK_STREAM,0)) < 0)
{
- dbg_perror(g,"error opening stream socket");
+ switch (errno) {
+ case EAFNOSUPPORT:
+ case EPROTONOSUPPORT:
+ continue;
+ default:
+ dbg_perror(g,"error opening stream socket");
+ epmd_cleanup_exit(g,1);
+ }
+ }
+ g->listenfd[bound++] = listensock[i];
+
+#if HAVE_DECL_IPV6_V6ONLY
+ opt = 1;
+ if (sa->sa_family == AF_INET6 &&
+ setsockopt(listensock[i],IPPROTO_IPV6,IPV6_V6ONLY,&opt,
+ sizeof(opt)) <0)
+ {
+ dbg_perror(g,"can't set IPv6 only socket option");
epmd_cleanup_exit(g,1);
}
- g->listenfd[i] = listensock[i];
-
+#endif
+
/*
* Note that we must not enable the SO_REUSEADDR on Windows,
* because addresses will be reused even if they are still in use.
@@ -372,8 +418,7 @@ void run(EpmdVars *g)
dbg_perror(g,"failed to set non-blocking mode of listening socket %d",
listensock[i]);
- if (bind(listensock[i], (struct sockaddr*) &iserv_addr[i],
- sizeof(iserv_addr[i])) < 0)
+ if (bind(listensock[i], (struct sockaddr*) &iserv_addr[i], salen) < 0)
{
if (errno == EADDRINUSE)
{
@@ -394,6 +439,11 @@ void run(EpmdVars *g)
}
select_fd_set(g, listensock[i]);
}
+ if (bound == 0) {
+ dbg_perror(g,"unable to bind any address");
+ epmd_cleanup_exit(g,1);
+ }
+ num_sockets = bound;
#ifdef HAVE_SYSTEMD_SD_DAEMON_H
}
sd_notifyf(0, "READY=1\n"
@@ -438,8 +488,8 @@ void run(EpmdVars *g)
}
for (i = 0; i < num_sockets; i++)
- if (FD_ISSET(listensock[i],&read_mask)) {
- if (do_accept(g, listensock[i]) && g->active_conn < g->max_conn) {
+ if (FD_ISSET(g->listenfd[i],&read_mask)) {
+ if (do_accept(g, g->listenfd[i]) && g->active_conn < g->max_conn) {
/*
* The accept() succeeded, and we have at least one file
* descriptor still free, which means that another accept()
@@ -1001,15 +1051,6 @@ static int conn_open(EpmdVars *g,int fd)
for (i = 0; i < g->max_conn; i++) {
if (g->conn[i].open == EPMD_FALSE) {
- struct sockaddr_in si;
- struct sockaddr_in di;
-#ifdef HAVE_SOCKLEN_T
- socklen_t st;
-#else
- int st;
-#endif
- st = sizeof(si);
-
g->active_conn++;
s = &g->conn[i];
@@ -1020,20 +1061,7 @@ static int conn_open(EpmdVars *g,int fd)
s->open = EPMD_TRUE;
s->keep = EPMD_FALSE;
- /* Determine if connection is from localhost */
- if (getpeername(s->fd,(struct sockaddr*) &si,&st) ||
- st < sizeof(si)) {
- /* Failure to get peername is regarded as non local host */
- s->local_peer = EPMD_FALSE;
- } else {
- /* Only 127.x.x.x and connections from the host's IP address
- allowed, no false positives */
- s->local_peer =
- (((((unsigned) ntohl(si.sin_addr.s_addr)) & 0xFF000000U) ==
- 0x7F000000U) ||
- (getsockname(s->fd,(struct sockaddr*) &di,&st) ?
- EPMD_FALSE : si.sin_addr.s_addr == di.sin_addr.s_addr));
- }
+ s->local_peer = conn_local_peer_check(g, s->fd);
dbg_tty_printf(g,2,(s->local_peer) ? "Local peer connected" :
"Non-local peer connected");
@@ -1041,7 +1069,7 @@ static int conn_open(EpmdVars *g,int fd)
s->got = 0;
s->mod_time = current_time(g); /* Note activity */
- s->buf = (char *)malloc(INBUF_SIZE);
+ s->buf = malloc(INBUF_SIZE);
if (s->buf == NULL) {
dbg_printf(g,0,"epmd: Insufficient memory");
@@ -1059,6 +1087,60 @@ static int conn_open(EpmdVars *g,int fd)
return EPMD_FALSE;
}
+static int conn_local_peer_check(EpmdVars *g, int fd)
+{
+ struct EPMD_SOCKADDR_IN si;
+ struct EPMD_SOCKADDR_IN di;
+
+ struct sockaddr_in *si4 = (struct sockaddr_in *)&si;
+ struct sockaddr_in *di4 = (struct sockaddr_in *)&di;
+
+#if defined(EPMD6)
+ struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&si;
+ struct sockaddr_in6 *di6 = (struct sockaddr_in6 *)&di;
+#endif
+
+#ifdef HAVE_SOCKLEN_T
+ socklen_t st;
+#else
+ int st;
+#endif
+
+ st = sizeof(si);
+
+ /* Determine if connection is from localhost */
+ if (getpeername(fd,(struct sockaddr*) &si,&st) ||
+ st > sizeof(si)) {
+ /* Failure to get peername is regarded as non local host */
+ return EPMD_FALSE;
+ }
+
+ /* Only 127.x.x.x and connections from the host's IP address
+ allowed, no false positives */
+#if defined(EPMD6)
+ if (si.ss_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&(si6->sin6_addr)))
+ return EPMD_TRUE;
+
+ if (si.ss_family == AF_INET)
+#endif
+ if ((((unsigned) ntohl(si4->sin_addr.s_addr)) & 0xFF000000U) ==
+ 0x7F000000U)
+ return EPMD_TRUE;
+
+ if (getsockname(fd,(struct sockaddr*) &di,&st))
+ return EPMD_FALSE;
+
+#if defined(EPMD6)
+ if (si.ss_family == AF_INET6)
+ return IN6_ARE_ADDR_EQUAL( &(si6->sin6_addr), &(di6->sin6_addr));
+ if (si.ss_family == AF_INET)
+#endif
+ return si4->sin_addr.s_addr == di4->sin_addr.s_addr;
+#if defined(EPMD6)
+ return EPMD_FALSE;
+#endif
+}
+
static int conn_close_fd(EpmdVars *g,int fd)
{
int i;
diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl
index cc24a55..8dfc21f 100644
--- a/erts/epmd/test/epmd_SUITE.erl
+++ b/erts/epmd/test/epmd_SUITE.erl
@@ -42,6 +42,7 @@
-export(
[
register_name/1,
+ register_name_ipv6/1,
register_names_1/1,
register_names_2/1,
register_duplicate_name/1,
@@ -108,7 +109,8 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [register_name, register_names_1, register_names_2,
+ [register_name, register_name_ipv6,
+ register_names_1, register_names_2,
register_duplicate_name, unicode_name, long_unicode_name,
get_port_nr, slow_get_port_nr,
unregister_others_name_1, unregister_others_name_2,
@@ -165,6 +167,24 @@ register_name(Config) when is_list(Config) ->
?line ok = close(Sock), % Unregister
ok.
+register_name_ipv6(doc) ->
+ ["Register a name over IPv6"];
+register_name_ipv6(suite) ->
+ [];
+register_name_ipv6(Config) when is_list(Config) ->
+ % Test if the host has an IPv6 loopback address
+ Res = gen_tcp:listen(0, [inet6, {ip, {0,0,0,0,0,0,0,1}}]),
+ case Res of
+ {ok,LSock} ->
+ gen_tcp:close(LSock),
+ ?line ok = epmdrun(),
+ ?line {ok,Sock} = register_node6("foobar6"),
+ ?line ok = close(Sock), % Unregister
+ ok;
+ _Error ->
+ {skip, "Host does not have an IPv6 loopback address"}
+ end.
+
register_names_1(doc) ->
["Register and unregister two nodes"];
register_names_1(suite) ->
@@ -238,13 +258,14 @@ register_node(Name) ->
register_node(Name,Port) ->
register_node_v2(Port,$M,0,5,5,Name,"").
+register_node6(Name) ->
+ register_node_v2({0,0,0,0,0,0,0,1},?DUMMY_PORT,$M,0,5,5,Name,"").
+
register_node_v2(Port, NodeType, Prot, HVsn, LVsn, Name, Extra) ->
- Utf8Name = unicode:characters_to_binary(Name),
- Req = [?EPMD_ALIVE2_REQ, put16(Port), NodeType, Prot,
- put16(HVsn), put16(LVsn),
- put16(size(Utf8Name)), binary_to_list(Utf8Name),
- size16(Extra), Extra],
- case send_req(Req) of
+ register_node_v2("localhost", Port, NodeType, Prot, HVsn, LVsn, Name, Extra).
+register_node_v2(Addr, Port, NodeType, Prot, HVsn, LVsn, Name, Extra) ->
+ Req = alive2_req(Port, NodeType, Prot, HVsn, LVsn, Name, Extra),
+ case send_req(Req, Addr) of
{ok,Sock} ->
case recv(Sock,4) of
{ok, [?EPMD_ALIVE2_RESP,_Res=0,_C0,_C1]} ->
@@ -1129,7 +1150,9 @@ send_direct(Sock, Bytes) ->
end.
send_req(Req) ->
- case connect() of
+ send_req(Req, "localhost").
+send_req(Req, Addr) ->
+ case connect(Addr) of
{ok,Sock} ->
case send(Sock, [size16(Req), Req]) of
ok ->
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index d511f2e..99ee635 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -250,7 +250,7 @@ case "$threads_disabled" in
;;
win32_threads)
EI_THREADS="true"
- THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0500 -DWINVER=0x0500"
+ THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0600 -DWINVER=0x0600"
;;
pthread)
EI_THREADS="true"
diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index 91af49f..21a3dec 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -31,7 +31,7 @@
%% External exports
-export([start/0, start_link/0, stop/0, port_please/2,
port_please/3, names/0, names/1,
- register_node/2, open/0, open/1, open/2]).
+ register_node/2, register_node/3, open/0, open/1, open/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -106,7 +106,9 @@ names1(HostName) ->
register_node(Name, PortNo) ->
- gen_server:call(erl_epmd, {register, Name, PortNo}, infinity).
+ register_node(Name, PortNo, inet).
+register_node(Name, PortNo, Family) ->
+ gen_server:call(erl_epmd, {register, Name, PortNo, Family}, infinity).
%%%----------------------------------------------------------------------
%%% Callback functions from gen_server
@@ -124,10 +126,10 @@ init(_) ->
-spec handle_call(calls(), term(), state()) ->
{'reply', term(), state()} | {'stop', 'shutdown', 'ok', state()}.
-handle_call({register, Name, PortNo}, _From, State) ->
+handle_call({register, Name, PortNo, Family}, _From, State) ->
case State#state.socket of
P when P < 0 ->
- case do_register_node(Name, PortNo) of
+ case do_register_node(Name, PortNo, Family) of
{alive, Socket, Creation} ->
S = State#state{socket = Socket,
port_no = PortNo,
@@ -210,8 +212,12 @@ open({A,B,C,D,E,F,G,H}=EpmdAddr, Timeout) when ?ip6(A,B,C,D,E,F,G,H) ->
close(Socket) ->
gen_tcp:close(Socket).
-do_register_node(NodeName, TcpPort) ->
- case open() of
+do_register_node(NodeName, TcpPort, Family) ->
+ Localhost = case Family of
+ inet -> open({127,0,0,1});
+ inet6 -> open({0,0,0,0,0,0,0,1})
+ end,
+ case Localhost of
{ok, Socket} ->
Name = to_string(NodeName),
Extra = "",
diff --git a/lib/wx/configure.in b/lib/wx/configure.in
index 3756786..be73888 100755
--- a/lib/wx/configure.in
+++ b/lib/wx/configure.in
@@ -163,14 +163,14 @@ case $host_os in
CPPFLAGS="$CPPFLAGS -D_MACOSX $PTHR_CFLAGS"
;;
mingw32)
- CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0500 -D_WINDOWS -D_UNICODE -DUNICODE"
- CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0500"
+ CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE"
+ CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
AC_MSG_WARN([Reverting to 32-bit time_t])
CPPFLAGS="$CPPFLAGS -D_USE_32BIT_TIME_T"
;;
win32)
- CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0500 -D_WINDOWS -D_UNICODE -DUNICODE"
- CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0500"
+ CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE"
+ CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
;;
*)
CFLAGS="$CFLAGS -Wno-deprecated-declarations"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,74 @@
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 25 Aug 2015 15:20:23 +0200
Subject: [PATCH] Teach sasl_report to limit crash reports
diff --git a/lib/sasl/src/sasl_report.erl b/lib/sasl/src/sasl_report.erl
index c3e6fed..aa84e4f 100644
--- a/lib/sasl/src/sasl_report.erl
+++ b/lib/sasl/src/sasl_report.erl
@@ -61,27 +61,53 @@ write_report2(IO, Fd, Head, supervisor_report, Report) ->
Context = sup_get(errorContext, Report),
Reason = sup_get(reason, Report),
Offender = sup_get(offender, Report),
- FmtString = " Supervisor: ~p~n Context: ~p~n Reason: "
- "~80.18p~n Offender: ~80.18p~n~n",
- write_report_action(IO, Fd, Head ++ FmtString,
- [Name,Context,Reason,Offender]);
+ {FmtString,Args} = supervisor_format([Name,Context,Reason,Offender]),
+ write_report_action(IO, Fd, Head, FmtString, Args);
write_report2(IO, Fd, Head, progress, Report) ->
Format = format_key_val(Report),
- write_report_action(IO, Fd, Head ++ "~s", [Format]);
+ write_report_action(IO, Fd, Head, "~s", [Format]);
write_report2(IO, Fd, Head, crash_report, Report) ->
- Format = proc_lib:format(Report),
- write_report_action(IO, Fd, Head ++ "~s", [Format]).
+ Depth = get_depth(),
+ Format = proc_lib:format(Report, latin1, Depth),
+ write_report_action(IO, Fd, Head, "~s", [Format]).
+
+supervisor_format(Args0) ->
+ case get_depth() of
+ unlimited ->
+ {" Supervisor: ~p~n"
+ " Context: ~p~n"
+ " Reason: ~80.18p~n"
+ " Offender: ~80.18p~n~n",
+ Args0};
+ Depth ->
+ [A,B,C,D] = Args0,
+ Args = [A,Depth,B,Depth,C,Depth,D,Depth],
+ {" Supervisor: ~P~n"
+ " Context: ~P~n"
+ " Reason: ~80.18P~n"
+ " Offender: ~80.18P~n~n",
+ Args}
+ end.
-write_report_action(io, Fd, Format, Args) ->
- io:format(Fd, Format, Args);
-write_report_action(io_lib, _Fd, Format, Args) ->
- io_lib:format(Format, Args).
+write_report_action(IO, Fd, Head, Format, Args) ->
+ S = [Head|io_lib:format(Format, Args)],
+ case IO of
+ io -> io:put_chars(Fd, S);
+ io_lib -> S
+ end.
format_key_val([{Tag,Data}|Rep]) ->
io_lib:format(" ~16w: ~p~n",[Tag,Data]) ++ format_key_val(Rep);
format_key_val(_) ->
[].
+get_depth() ->
+ case application:get_env(kernel, error_logger_format_depth) of
+ {ok, Depth} when is_integer(Depth) ->
+ max(10, Depth);
+ undefined ->
+ unlimited
+ end.
sup_get(Tag, Report) ->
case lists:keysearch(Tag, 1, Report) of

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Thu, 14 Jul 2016 17:51:16 +0300
Subject: [PATCH] Respect -proto_dist switch while connection to EPMD
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index 21a3dec..0ba695c 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -107,6 +107,10 @@ names1(HostName) ->
register_node(Name, PortNo) ->
register_node(Name, PortNo, inet).
+register_node(Name, PortNo, inet_tcp) ->
+ register_node(Name, PortNo, inet);
+register_node(Name, PortNo, inet6_tcp) ->
+ register_node(Name, PortNo, inet6);
register_node(Name, PortNo, Family) ->
gen_server:call(erl_epmd, {register, Name, PortNo, Family}, infinity).
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index 0739cf3..c64ddc8 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -72,7 +72,7 @@ gen_listen(Driver, Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Driver, Socket),
{_,Port} = TcpAddress#net_address.address,
- case erl_epmd:register_node(Name, Port) of
+ case erl_epmd:register_node(Name, Port, Driver) of
{ok, Creation} ->
{ok, {Socket, TcpAddress, Creation}};
Error ->

View file

@ -0,0 +1,38 @@
From: Dan Gudmundsson <dgud@erlang.org>
Date: Thu, 17 Mar 2016 10:23:41 +0100
Subject: [PATCH] mnesia: Send mnesia_down messages to waiting transactions
Mnesia didn't forward mnesia_down to transactions which where already
decided to be aborted, but that could lead to hanging transactions
still waiting for messages from the node which had stopped.
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index 17af0ca..329192e 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -1714,13 +1714,10 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, undo_prepare},
[{tid, Tid}]);
- {'EXIT', _, _} ->
+ {'EXIT', _MnesiaTM, Reason} ->
+ reply(Coord, {do_abort, Tid, self(), {bad_commit,Reason}}),
mnesia_recover:log_decision(D#decision{outcome = aborted}),
- ?eval_debug_fun({?MODULE, commit_participant, exit_log_abort},
- [{tid, Tid}]),
- mnesia_schema:undo_prepare_commit(Tid, C0),
- ?eval_debug_fun({?MODULE, commit_participant, exit_undo_prepare},
- [{tid, Tid}]);
+ mnesia_schema:undo_prepare_commit(Tid, C0);
Msg ->
verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
@@ -2236,8 +2233,6 @@ reconfigure_coordinators(N, [{Tid, [Store | _]} | Coordinators]) ->
true ->
send_mnesia_down(Tid, Store, N)
end;
- aborted ->
- ignore; % avoid spurious mnesia_down messages
_ ->
%% Tell the coordinator about the mnesia_down
send_mnesia_down(Tid, Store, N)

View file

@ -0,0 +1,139 @@
From: Anthony Ramine <n.oxyde@gmail.com>
Date: Sun, 8 Jun 2014 12:37:10 +0200
Subject: [PATCH] Fix a few javadoc errors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reported-by: Boris Mühmer
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java
index 9ba6a4a..7aa30ee 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java
@@ -266,7 +266,7 @@ public abstract class AbstractConnection extends Thread {
*
* @param dest
* the Erlang PID of the remote process.
- * @param msg
+ * @param payload
* the encoded message to send.
*
* @exception java.io.IOException
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java
index 8e8bd47..e7a9d10 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java
@@ -404,7 +404,7 @@ public class OtpConnection extends AbstractConnection {
*
* @param dest
* the Erlang PID of the remote process.
- * @param msg
+ * @param payload
* the encoded message to send.
*
* @exception java.io.IOException
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
index 7e3e2a7..84b1355 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
@@ -51,8 +51,8 @@ public class OtpErlangLong extends OtpErlangObject implements Serializable,
/**
* Create an Erlang integer from the given value.
*
- * @param val
- * the long value to use.
+ * @param v
+ * the big integer value to use.
*/
public OtpErlangLong(final BigInteger v) {
if (v == null) {
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java
index fe81ce3..f75e435 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java
@@ -162,7 +162,7 @@ public class OtpErlangPid extends OtpErlangObject implements Serializable,
* Determine if two PIDs are equal. PIDs are equal if their components are
* equal.
*
- * @param port
+ * @param o
* the other PID to compare to.
*
* @return true if the PIDs are equal, false otherwise.
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
index 6766b52..a5e202c 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
@@ -41,8 +41,6 @@ public class OtpErlangString extends OtpErlangObject implements Serializable,
/**
* Create an Erlang string from a list of integers.
- *
- * @return an Erlang string with Unicode code units.
*
* @throws OtpErlangException
* for non-proper and non-integer lists.
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
index 0fd93b0..4a4a1e7 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -69,6 +69,7 @@ package com.ericsson.otp.erlang;
* notify other parties in a timely manner.
* </p>
*
+ * <p>
* When retrieving messages from a mailbox that has received an exit signal, an
* {@link OtpErlangExit OtpErlangExit} exception will be raised. Note that the
* exception is queued in the mailbox along with other messages, and will not be
@@ -420,7 +421,6 @@ public class OtpMbox {
/**
* Equivalent to <code>exit(new OtpErlangAtom(reason))</code>.
- * </p>
*
* @see #exit(OtpErlangObject)
*/
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java
index 6f507bf..31a5d0f 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java
@@ -30,14 +30,14 @@ package com.ericsson.otp.erlang;
* </p>
*
* <p>
- * The header information that is available is as follows: <lu>
+ * The header information that is available is as follows: <ul>
* <li> a tag indicating the type of message
* <li> the intended recipient of the message, either as a
* {@link OtpErlangPid pid} or as a String, but never both.
* <li> (sometimes) the sender of the message. Due to some eccentric
* characteristics of the Erlang distribution protocol, not all messages have
* information about the sending process. In particular, only messages whose tag
- * is {@link OtpMsg#regSendTag regSendTag} contain sender information. </lu>
+ * is {@link OtpMsg#regSendTag regSendTag} contain sender information. </ul>
*
* <p>
* Message are sent using the Erlang external format (see separate
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
index 78f47aa..fd4eba3 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
@@ -202,7 +202,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
/**
* Write an array of bytes to the stream.
*
- * @param buf
+ * @param bytes
* the array of bytes to write.
*
*/
@@ -637,7 +637,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
* Write a positive short to the stream. The short is interpreted as a two's
* complement unsigned short even if it is negative.
*
- * @param s
+ * @param us
* the short to use.
*/
public void write_ushort(final short us) {

View file

@ -1,4 +1 @@
d27250e9ee98d6388e7f2e65379a0406 otp_src_R16B03-1.readme
eff44490c9bbae3a5c5741bec2390ba3 otp_doc_html_R16B03-1.tar.gz
39113c0d2515bdd8cd7e0f975a380122 otp_doc_man_R16B03-1.tar.gz
e5ece977375197338c1b93b3d88514f8 otp_src_R16B03-1.tar.gz e5ece977375197338c1b93b3d88514f8 otp_src_R16B03-1.tar.gz