Compare commits

..

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
40 changed files with 8503 additions and 2584 deletions

59
.gitignore vendored
View file

@ -1,7 +1,52 @@
/*.src.rpm
/*~
/otp-OTP-*.tar.gz
/otp_doc_html_R*.tar.gz
/otp_doc_man_R*.tar.gz
/otp_src_R*.readme
/otp_src_R*.tar.gz
otp_src_R14A.tar.gz
/otp_src_R14B.tar.gz
/otp_doc_html_R14B.tar.gz
/otp_doc_man_R14B.tar.gz
/otp_doc_html_R14B01.tar.gz
/otp_doc_man_R14B01.tar.gz
/otp_src_R14B01.tar.gz
/otp_doc_html_R14B02.tar.gz
/otp_doc_man_R14B02.tar.gz
/otp_src_R14B02.tar.gz
/otp_src_R14B03.tar.gz
/otp_doc_html_R14B03.tar.gz
/otp_doc_man_R14B03.tar.gz
/otp_src_R14B04.tar.gz
/otp_doc_html_R14B04.tar.gz
/otp_doc_man_R14B04.tar.gz
/otp_doc_html_R15B.tar.gz
/otp_doc_man_R15B.tar.gz
/otp_src_R15B.tar.gz
/otp_doc_html_R15B01.tar.gz
/otp_doc_man_R15B01.tar.gz
/otp_src_R15B01.tar.gz
/otp_doc_html_R15B02.tar.gz
/otp_doc_man_R15B02.tar.gz
/otp_src_R15B02.tar.gz
/otp_doc_html_R15B03-1.tar.gz
/otp_doc_man_R15B03-1.tar.gz
/otp_src_R15B03-1.readme
/otp_src_R15B03-1.tar.gz
/otp_doc_html_R16A_RELEASE_CANDIDATE.tar.gz
/otp_doc_man_R16A_RELEASE_CANDIDATE.tar.gz
/otp_src_R16A_RELEASE_CANDIDATE.tar.gz
/otp_src_R16A_RELEASE_CANDIDATE.readme
/otp_src_R16B.tar.gz
/otp_doc_html_R16B.tar.gz
/otp_doc_man_R16B.tar.gz
/otp_src_R16B01.tar.gz
/otp_doc_html_R16B01.tar.gz
/otp_doc_man_R16B01.tar.gz
/otp_src_R16B01.readme
/otp_src_R16B02.tar.gz
/otp_doc_html_R16B02.tar.gz
/otp_doc_man_R16B02.tar.gz
/otp_src_R16B02.readme
/otp_src_R16B03.tar.gz
/otp_doc_html_R16B03.tar.gz
/otp_doc_man_R16B03.tar.gz
/otp_src_R16B03.readme
/otp_src_R16B03-1.readme
/otp_doc_html_R16B03-1.tar.gz
/otp_doc_man_R16B03-1.tar.gz
/otp_src_R16B03-1.tar.gz

View file

@ -2,7 +2,7 @@
Description=Erlang Port Mapper Daemon Activation Socket
[Socket]
ListenStream=4369
ListenStream=127.0.0.1:4369
Accept=false
[Install]

View file

@ -2,7 +2,7 @@
Description=Erlang Port Mapper Daemon Activation Socket
[Socket]
ListenStream=%I
ListenStream=%i:4369
Accept=false
[Install]

File diff suppressed because it is too large Load diff

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Do not format man-pages and do not install miscellaneous
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index 42af9c87dc..c017e0a4ed 100644
index 5c1ce51..5a07855 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -552,10 +552,6 @@ endif
@@ -474,10 +474,6 @@ endif
ifneq ($(INSTALL_TOP_BIN),)
$(INSTALL_PROGRAM) $(INSTALL_TOP_BIN) "$(RELEASE_PATH)"
endif
@ -17,14 +17,14 @@ index 42af9c87dc..c017e0a4ed 100644
- $(INSTALL_DIR) "$(RELEASE_PATH)/misc"
- $(INSTALL_SCRIPT) $(INSTALL_MISC) "$(RELEASE_PATH)/misc"
-endif
ifneq ($(INSTALL_SRC),)
$(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/src"
$(INSTALL_DATA) $(INSTALL_SRC) "$(RELEASE_PATH)/erts-$(VSN)/src"
ifneq ($(INSTALL_ERL_OSE),)
$(INSTALL_DIR) "$(RELEASE_PATH)/build_erl_ose"
cd $(OSEETC) && $(TAR) erl_ose_$(SYSTEM_VSN).tar $(INSTALL_ERL_OSE)
diff --git a/erts/etc/unix/Install.src b/erts/etc/unix/Install.src
index b00dd09f1a..2147774f50 100644
index 8eb1db7..9e340bb 100644
--- a/erts/etc/unix/Install.src
+++ b/erts/etc/unix/Install.src
@@ -143,14 +143,5 @@ cp -p ../releases/%I_SYSTEM_VSN%/start_*.boot .
@@ -140,14 +140,5 @@ cp -p ../releases/%I_SYSTEM_VSN%/start_*.boot .
cp -p ../releases/%I_SYSTEM_VSN%/no_dot_erlang.boot .
cp -p $Name.boot start.boot
cp -p ../releases/%I_SYSTEM_VSN%/$Name.script start.script

View file

@ -5,15 +5,28 @@ Subject: [PATCH] Remove rpath
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index aedc9e7a13..b27c2aa01b 100644
index a20ddff..e890927 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -147,7 +147,7 @@ endif
endif
@@ -85,7 +85,7 @@ endif
DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
ifeq ($(DYNAMIC_OR_WIN_CRYPTO_LIB),yes)
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
-SSL_DED_LD_RUNTIME_LIBRARY_PATH = @SSL_DED_LD_RUNTIME_LIBRARY_PATH@
+SSL_DED_LD_RUNTIME_LIBRARY_PATH =
CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPTO_LIBNAME)
EXTRA_FLAGS = -DHAVE_DYNAMIC_CRYPTO_LIB
else
diff --git a/lib/crypto/priv/Makefile b/lib/crypto/priv/Makefile
index 0989f14..0d29444 100644
--- a/lib/crypto/priv/Makefile
+++ b/lib/crypto/priv/Makefile
@@ -60,7 +60,7 @@ OBJS = $(OBJDIR)/crypto.o
# ----------------------------------------------------
$(SO_NIFLIB): $(OBJS)
- $(SO_LD) $(SO_LDFLAGS) -L$(SO_SSL_LIBDIR) -Wl,-R$(SO_SSL_LIBDIR) \
+ $(SO_LD) $(SO_LDFLAGS) -L$(SO_SSL_LIBDIR) \
-o $@ $^ -lcrypto
$(DLL_NIFLIB): $(OBJS)

View file

@ -14,10 +14,10 @@ https://bugzilla.redhat.com/818419
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 82a6b6e87a..5f2fe8ba7d 100644
index 7023833..8bf8eb9 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -137,8 +137,6 @@ include $(ERL_TOP)/make/otp_release_targets.mk
@@ -107,8 +107,6 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
$(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib"
@ -26,34 +26,73 @@ index 82a6b6e87a..5f2fe8ba7d 100644
release_docs_spec:
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index e890927..1377654 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -160,13 +160,9 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
- $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj"
- $(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib"
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
- $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib"
endif
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index fa1ea3cd39..b977b6afe5 100644
index e36b39c..fd377bb 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -715,13 +715,11 @@ ifeq (@DYNAMIC_LIB@, yes)
endif
@@ -876,14 +876,14 @@ ifneq ($(EXE_TARGETS),)
$(INSTALL_PROGRAM) $(EXE_TARGETS) "$(RELSYSDIR)/bin"
endif
$(INSTALL_DATA) $(EXTRA) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) connect/*.[ch] "$(RELSYSDIR)/src/connect"
- $(INSTALL_DATA) decode/*.[ch] "$(RELSYSDIR)/src/decode"
- $(INSTALL_DATA) encode/*.[ch] "$(RELSYSDIR)/src/encode"
- $(INSTALL_DATA) epmd/*.[ch] "$(RELSYSDIR)/src/epmd"
- $(INSTALL_DATA) misc/*.[ch] "$(RELSYSDIR)/src/misc"
- $(INSTALL_DATA) global/*.[ch] "$(RELSYSDIR)/src/global"
- $(INSTALL_DATA) registry/*.[ch] "$(RELSYSDIR)/src/registry"
- $(INSTALL_DATA) legacy/*.[ch] "$(RELSYSDIR)/src/legacy"
- $(INSTALL_DATA) prog/*.[ch] "$(RELSYSDIR)/src/prog"
+ $(INSTALL_DATA) connect/*.h "$(RELSYSDIR)/src/connect"
+ $(INSTALL_DATA) decode/*.h "$(RELSYSDIR)/src/decode"
+ $(INSTALL_DATA) encode/*.h "$(RELSYSDIR)/src/encode"
+ $(INSTALL_DATA) epmd/*.h "$(RELSYSDIR)/src/epmd"
+ $(INSTALL_DATA) misc/*.h "$(RELSYSDIR)/src/misc"
+ $(INSTALL_DATA) registry/*.h "$(RELSYSDIR)/src/registry"
+ $(INSTALL_DATA) legacy/*.h "$(RELSYSDIR)/src/legacy"
+ $(INSTALL_DATA) prog/*.h "$(RELSYSDIR)/src/prog"
release_docs:
diff --git a/lib/ic/c_src/Makefile.in b/lib/ic/c_src/Makefile.in
index ed860ab..96206ae 100644
--- a/lib/ic/c_src/Makefile.in
+++ b/lib/ic/c_src/Makefile.in
@@ -144,12 +144,10 @@ $(OBJDIR)/%.o: %.c
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
$(INSTALL_DIR) "$(RELSYSDIR)/include"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
$(INSTALL_DIR) "$(RELEASE_PATH)/usr/include"
$(INSTALL_DIR) "$(RELEASE_PATH)/usr/lib"
- $(INSTALL_DATA) ic.c ic_tmo.c "$(RELSYSDIR)/c_src"
$(INSTALL_DATA) $(IDL_FILES) $(H_FILES) "$(RELSYSDIR)/include"
$(INSTALL_DATA) $(LIBRARY) "$(RELSYSDIR)/priv/lib"
$(INSTALL_DATA) $(IDL_FILES) $(H_FILES) "$(RELEASE_PATH)/usr/include"
diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in
index 3649e2c392..d8c5c68b99 100644
index 6111cf2..bd62e8b 100644
--- a/lib/megaco/src/flex/Makefile.in
+++ b/lib/megaco/src/flex/Makefile.in
@@ -251,7 +251,7 @@ release_spec: opt
@@ -270,7 +270,7 @@ release_spec: opt
$(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src/flex"
$(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
ifeq ($(ENABLE_MEGACO_FLEX_SCANNER),true)
@ -63,10 +102,10 @@ index 3649e2c392..d8c5c68b99 100644
endif
diff --git a/lib/odbc/c_src/Makefile.in b/lib/odbc/c_src/Makefile.in
index d1b26743a6..cf8faae1f5 100644
index 6572d28..c7093ae 100644
--- a/lib/odbc/c_src/Makefile.in
+++ b/lib/odbc/c_src/Makefile.in
@@ -129,11 +129,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
@@ -128,11 +128,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
ifdef EXE_TARGET
@ -79,10 +118,10 @@ index d1b26743a6..cf8faae1f5 100644
endif
diff --git a/lib/os_mon/c_src/Makefile.in b/lib/os_mon/c_src/Makefile.in
index 27b156a2c9..f11ff303b6 100644
index f84ccf7..05d194f 100644
--- a/lib/os_mon/c_src/Makefile.in
+++ b/lib/os_mon/c_src/Makefile.in
@@ -126,8 +126,6 @@ $(OBJDIR)/memsup.o: memsup.h
@@ -125,8 +125,6 @@ $(OBJDIR)/memsup.o: memsup.h
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
@ -91,3 +130,30 @@ index 27b156a2c9..f11ff303b6 100644
$(INSTALL_DIR) "$(RELSYSDIR)/priv/bin"
$(INSTALL_PROGRAM) $(TARGET_FILES) "$(RELSYSDIR)/priv/bin"
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index d315a90..7b4b9fb 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -177,9 +177,7 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
- $(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib"
release_docs_spec:
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index aea5686..a0c8883 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -189,8 +189,6 @@ include ../vsn.mk
RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(TOOLS_VSN)
release_spec: all
- $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
- $(INSTALL_DATA) $(EMEM_SRCS) $(EMEM_HEADERS) "$(RELSYSDIR)/c_src"
ifneq ($(PROGS),)
$(INSTALL_DIR) "$(RELSYSDIR)/bin"
$(INSTALL_PROGRAM) $(PROGS) "$(RELSYSDIR)/bin"

View file

@ -4,11 +4,24 @@ Subject: [PATCH] Do not install Java sources
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Makefile b/lib/ic/java_src/com/ericsson/otp/ic/Makefile
index 273614e..5b1fb57 100644
--- a/lib/ic/java_src/com/ericsson/otp/ic/Makefile
+++ b/lib/ic/java_src/com/ericsson/otp/ic/Makefile
@@ -112,8 +112,6 @@ docs:
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/java_src/com/ericsson/otp/ic"
- $(INSTALL_DATA) $(JAVA_FILES) "$(RELSYSDIR)/java_src/com/ericsson/otp/ic"
$(INSTALL_DIR) "$(RELSYSDIR)/priv"
$(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) "$(RELSYSDIR)/priv"
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
index 089cf4ab1a..404654a437 100644
index f476d45..44429a4 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
@@ -123,8 +123,6 @@ release release_docs release_tests release_html:
@@ -102,8 +102,6 @@ release release_docs release_tests release_html:
$(V_at)$(MAKE) $(MFLAGS) RELEASE_PATH="$(RELEASE_PATH)" $(TARGET_MAKEFILE) $@_spec
release_spec: opt
@ -16,4 +29,4 @@ index 089cf4ab1a..404654a437 100644
- $(V_at)$(INSTALL_DATA) $(JAVA_SRC) "$(RELSYSDIR)/java_src/com/ericsson/otp/erlang"
$(V_at)$(INSTALL_DIR) "$(RELSYSDIR)/priv"
$(V_at)$(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) "$(RELSYSDIR)/priv"
$(V_at)$(INSTALL_DIR) "$(RELSYSDIR)/ebin"

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Do not install nteventlog and related doc-files on non-win32
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/os_mon/doc/src/Makefile b/lib/os_mon/doc/src/Makefile
index 8e3882bfdc..ea999cf9c7 100644
index 08fd23e..5606cfc 100644
--- a/lib/os_mon/doc/src/Makefile
+++ b/lib/os_mon/doc/src/Makefile
@@ -31,11 +31,16 @@ APPLICATION=os_mon
@@ -35,12 +35,17 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
@ -21,32 +21,33 @@ index 8e3882bfdc..ea999cf9c7 100644
XML_REF3_FILES = cpu_sup.xml \
disksup.xml \
memsup.xml \
os_mon_mib.xml \
os_sup.xml \
- nteventlog.xml
+ $(NTEVENTLOG_DOCFILE)
XML_REF6_FILES = os_mon_app.xml
XML_REF6_FILES = os_mon_app.xml
diff --git a/lib/os_mon/src/Makefile b/lib/os_mon/src/Makefile
index e28fb12548..ee32f3946f 100644
index cd2dade..4e78cf8 100644
--- a/lib/os_mon/src/Makefile
+++ b/lib/os_mon/src/Makefile
@@ -34,7 +34,13 @@ RELSYSDIR = $(RELEASE_PATH)/lib/os_mon-$(VSN)
@@ -33,8 +33,13 @@ RELSYSDIR = $(RELEASE_PATH)/lib/os_mon-$(VSN)
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-MODULES= disksup memsup cpu_sup os_mon os_mon_mib os_sup os_mon_sysinfo nteventlog
+ifeq ($(findstring win32,$(TARGET)),win32)
+NTEVENTLOG=nteventlog
+else
+NTEVENTLOG=
+endif
+MODULES= disksup memsup cpu_sup os_mon os_mon_mib os_sup os_mon_sysinfo \
MODULES= disksup memsup cpu_sup os_mon os_mon_mib os_sup os_mon_sysinfo \
- nteventlog
+ $(NTEVENTLOG)
INCLUDE=../include
CSRC=../c_src
@@ -78,7 +84,11 @@ docs:
@@ -78,7 +83,11 @@ docs:
# ----------------------------------------------------
$(APP_TARGET): $(APP_SRC) ../vsn.mk

View file

@ -1,32 +0,0 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Wed, 2 Aug 2017 16:12:19 +0300
Subject: [PATCH] Add extra search directory
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 7327636751..2e92e77598 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -90,11 +90,17 @@ init(Ref, Parent, [Root,Mode]) ->
IPath =
case Mode of
interactive ->
- LibDir = filename:append(Root, "lib"),
- {ok,Dirs} = erl_prim_loader:list_dir(LibDir),
- Paths = make_path(LibDir, Dirs),
+ F = fun(R) ->
+ LD = filename:append(R, "lib"),
+ case erl_prim_loader:list_dir(LD) of
+ error -> [];
+ {ok, D} -> make_path(LD, D)
+ end
+ end,
+ Paths = F(Root),
+ SharedPaths = F("/usr/share/erlang"),
UserLibPaths = get_user_lib_dirs(),
- ["."] ++ UserLibPaths ++ Paths;
+ ["."] ++ UserLibPaths ++ Paths ++ SharedPaths;
_ ->
[]
end,

File diff suppressed because it is too large Load diff

View file

@ -1,31 +0,0 @@
From: Jan Pazdziora <jpazdziora@redhat.com>
Date: Thu, 10 May 2018 18:35:02 +0200
Subject: [PATCH] Avoid forking sed to get basename.
diff --git a/erts/etc/unix/erl.src.src b/erts/etc/unix/erl.src.src
index 536fa139d9..4dcffbc4c8 100644
--- a/erts/etc/unix/erl.src.src
+++ b/erts/etc/unix/erl.src.src
@@ -49,7 +49,7 @@ else
fi
BINDIR="$ROOTDIR/erts-%VSN%/bin"
EMU=%EMULATOR%%EMULATOR_NUMBER%
-PROGNAME=`basename "$0"`
+PROGNAME=${0##*/}
export EMU
export ROOTDIR
export BINDIR
diff --git a/erts/etc/unix/start_erl.src b/erts/etc/unix/start_erl.src
index 34e0369710..62e613bba1 100644
--- a/erts/etc/unix/start_erl.src
+++ b/erts/etc/unix/start_erl.src
@@ -37,7 +37,7 @@ VSN=`awk '{print $2}' $DataFile`
BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin
EMU=beam
-PROGNAME=`echo $0 | sed 's/.*\///'`
+PROGNAME=${0##*/}
export EMU
export ROOTDIR
export BINDIR

View file

@ -0,0 +1,61 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Sun, 21 Nov 2010 00:17:49 +0300
Subject: [PATCH] Ugly workaround for java-1.5.0-gcj which doesn't support
UNICODE fully
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
Fedora-Spec-Comment: Required only for el5, el6 on PowerPC
Fedora-Spec-Before: %if 0%{?el4}%{?el5}%{?el6}
Fedora-Spec-Before: %ifnarch %{ix86} x86_64
Fedora-Spec-After: %endif
Fedora-Spec-After: %endif
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangList.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangList.java
index 3456fd7..86cd411 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangList.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangList.java
@@ -389,19 +389,7 @@ public class OtpErlangList extends OtpErlangObject implements
*/
public String stringValue() throws OtpErlangException {
- if (! isProper()) {
- throw new OtpErlangException("Non-proper list: " + this);
- }
- final int[] values = new int[arity()];
- for (int i = 0; i < values.length; ++i) {
- final OtpErlangObject o = elementAt(i);
- if (! (o instanceof OtpErlangLong)) {
- throw new OtpErlangException("Non-integer term: " + o);
- }
- final OtpErlangLong l = (OtpErlangLong) o;
- values[i] = l.intValue();
- }
- return new String(values, 0, values.length);
+ throw new OtpErlangException("No UNICODE support in java-1.5.0-gcj");
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
index 9dc1728..76e380d 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
@@ -1112,17 +1112,8 @@ public class OtpInputStream extends ByteArrayInputStream {
case OtpExternal.nilTag:
return "";
case OtpExternal.listTag: // List when unicode +
- len = read4BE();
- intbuf = new int[len];
- for (int i = 0; i < len; i++) {
- intbuf[i] = read_int();
- if (! OtpErlangString.isValidCodePoint(intbuf[i])) {
- throw new OtpErlangDecodeException
- ("Invalid CodePoint: " + intbuf[i]);
- }
- }
- read_nil();
- return new String(intbuf, 0, intbuf.length);
+ throw new OtpErlangDecodeException(
+ "No UNICODE support in java-1.5.0-gcj");
default:
throw new OtpErlangDecodeException(
"Wrong tag encountered, expected " + OtpExternal.stringTag

View file

@ -0,0 +1,22 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Thu, 26 Sep 2013 22:01:03 +0400
Subject: [PATCH] Fix for armv7hl architecture
Taken from openSUSE:
* https://build.opensuse.org/package/view_file/devel:languages:erlang:Factory/erlang/fix-armv7hl.patch?expand=1
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/erts/configure.in b/erts/configure.in
index bad748d..230f27a 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -621,6 +621,7 @@ case $chk_arch_ in
armv5tejl) ARCH=arm;;
armv6l) ARCH=arm;;
armv7l) ARCH=arm;;
+ armv7hl) ARCH=arm;;
tile) ARCH=tile;;
*) ARCH=noarch;;
esac

View file

@ -1,25 +0,0 @@
From: Francois-Denis Gonthier <neumann@lostwebsite.net>
Date: Thu, 20 Sep 2018 15:01:18 +0300
Subject: [PATCH] Load man-pages from system-wide directory
Patch allows one to use standard man path with erl -man command.
(Erlang manual pages are placed to /usr/share/man/ hierarchy
as required by Debian policy.)
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 888df87e35..14272f06c6 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -716,8 +716,10 @@ int main(int argc, char **argv)
error("-man not supported on Windows");
#else
argv[i] = "man";
- erts_snprintf(tmpStr, sizeof(tmpStr), "%s/man", rootdir);
- set_env("MANPATH", tmpStr);
+ /*
+ * Conform to erlang-manpages content.
+ */
+ putenv(strsave("MANSECT=3erl:1:5:7"));
execvp("man", argv+i);
error("Could not execute the 'man' command.");
#endif

View file

@ -1,464 +0,0 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Thu, 19 Jun 2025 13:17:52 +0200
Subject: [PATCH] Add GDB tools
* https://github.com/erlang/otp-gdb-tools
* Commit 7b864f58c534699e4124e31ecfda86041b941037.
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/erts/etc/unix/gdb-tools/README.md b/erts/etc/unix/gdb-tools/README.md
new file mode 100644
index 0000000000..8a6cf92b1d
--- /dev/null
+++ b/erts/etc/unix/gdb-tools/README.md
@@ -0,0 +1,42 @@
+# Erlang/OTP GDB Tools
+
+This repository contains GDB tools that cannot
+be part of the main Erlang/OTP repository for licensing
+reasons. The tools are used when building and debugging
+Erlang/OTP with gdb and are installed as needed by the
+Erlang/OTP build system.
+
+Right now the only tool in this repository is the jit-reader
+which is a plugin to gdb that allows it to read the stack of
+Erlang processes when using the JIT. This allows commands
+such as `backtrace` to show Erlang stackframes. For example:
+
+```
+(gdb) bt
+#0 0x00007fffa40005ee in global::call_bif_shared ()
+#1 0x00007fffa411eaac in erl_eval:eval_lc1/7 () at erl_eval.erl:929
+#2 0x00007fffa411e7bc in erl_eval:eval_lc/7 () at erl_eval.erl:917
+#3 0x00007fffa4296528 in lists:map_1/2 () at lists.erl:2082
+#4 0x00007fffa4296554 in lists:map_1/2 () at lists.erl:2082
+#5 0x00007fffa4296554 in lists:map_1/2 () at lists.erl:2082
+#6 0x00007fffa4296554 in lists:map_1/2 () at lists.erl:2082
+.....
+#98 0x00007fffa4296554 in lists:map_1/2 () at lists.erl:2082
+#99 0x00007fffa4296554 in lists:map_1/2 () at lists.erl:2082
+#100 0x00007fffa4296554 in lists:map_1/2 () at lists.erl:2082
+#101 0x00007fffa42963d4 in lists:map/2 () at lists.erl:2077
+#102 0x00007fffa411e45c in erl_eval:do_apply/7 () at erl_eval.erl:904
+#103 0x00007fffa45f4c58 in shell:exprs/7 () at shell.erl:893
+#104 0x00007fffa45f42c4 in shell:eval_exprs/7 () at shell.erl:849
+#105 0x00007fffa45f3dac in shell:eval_loop/4 () at shell.erl:834
+#106 0x00007fffa40024b8 in erts_beamasm:normal_exit/0-CodeInfoPrologue ()
+Backtrace stopped: previous frame inner to this frame (corrupt stack?)
+(gdb)
+```
+
+## Updates of jit-reader
+
+When updating jit-reader you first need to update this repository
+and push the new version here. Then you need to run
+`./otp_build update_gdb_tools` in the Erlang/OTP repo for
+it to use the correct commit.
diff --git a/erts/etc/unix/gdb-tools/jit-reader.c b/erts/etc/unix/gdb-tools/jit-reader.c
new file mode 100644
index 0000000000..3c39c5540d
--- /dev/null
+++ b/erts/etc/unix/gdb-tools/jit-reader.c
@@ -0,0 +1,386 @@
+#include <gdb/jit-reader.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+/* Useful links
+ * - https://pwparchive.wordpress.com/2011/11/20/new-jit-interface-for-gdb/
+ * - https://sourceware.org/gdb/current/onlinedocs/gdb/Custom-Debug-Info.html
+ * - https://github.com/tetzank/asmjit-utilities
+ * - https://github.com/bminor/binutils-gdb/blob/master/gdb/testsuite/gdb.base/jitreader.c
+ */
+
+GDB_DECLARE_GPL_COMPATIBLE_READER
+
+#if 0
+#define HARD_DEBUG
+static FILE *log = NULL;
+#define LOG(...) do { fprintf(log, ##__VA_ARGS__); fflush(log); } while(0)
+#else
+#define LOG(...)
+#endif
+
+typedef enum {
+ X64_RBP = 6, /* Frame pointer iff native frames are enabled */
+ X64_RSP = 7, /* Stack pointer when using native stack */
+ X64_R12 = 12, /* Stack pointer when using non-native stack */
+ X64_R13 = 13, /* Current process */
+ X64_RIP = 16
+} X64Register;
+
+typedef enum {
+ /* Return address only */
+ ERTS_FRAME_LAYOUT_RA,
+ /* Frame pointer, return address */
+ ERTS_FRAME_LAYOUT_FP_RA
+} ErtsFrameLayout;
+
+struct emulator_info {
+ /* 0 = regular, 1 = frame pointers */
+ int frame_layout;
+ const void *normal_exit;
+};
+
+struct erlang_module_info {
+ uint64_t base_address;
+ uint32_t range_count;
+ uint32_t code_size;
+ /* Module name, including null terminator. */
+ uint16_t name_length;
+ char name[];
+ /* array of range_info structures */
+};
+
+struct range_info {
+ uint32_t start_offset;
+ uint32_t end_offset;
+ uint32_t line_count;
+ /* Range name, including null terminator. */
+ uint16_t name_length;
+ char name[];
+ /* array of line_info structures */
+};
+
+struct line_info {
+ uint32_t start_offset;
+ uint32_t line_number;
+ /* File name, including null terminator. */
+ uint16_t file_length;
+ char file[];
+};
+
+enum debug_info_header {
+ DEBUG_INFO_HEADER_EMULATOR = 0,
+ DEBUG_INFO_HEADER_MODULE = 1,
+};
+
+struct debug_info {
+ enum debug_info_header header;
+ union {
+ struct emulator_info emu;
+ struct erlang_module_info mod;
+ } payload;
+};
+
+typedef struct range {
+ GDB_CORE_ADDR start;
+ GDB_CORE_ADDR end;
+#ifdef HARD_DEBUG
+ char *name;
+#endif
+} range;
+
+typedef struct priv {
+ range *ranges;
+ int num_ranges;
+ ErtsFrameLayout frame_layout;
+ const void *normal_exit;
+} priv;
+
+static enum gdb_status read_module_info(struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ struct erlang_module_info *module_info) {
+ struct gdb_object *obj = cb->object_open(cb);
+ GDB_CORE_ADDR mod_start, mod_end;
+ char *symfile = (char*)module_info;
+ priv *priv = self->priv_data;
+
+ symfile += sizeof(*module_info) + module_info->name_length;
+
+ mod_start = module_info->base_address;
+ mod_end = mod_start + module_info->code_size;
+
+ priv->ranges = realloc(priv->ranges, (priv->num_ranges + 1) * sizeof(range));
+ priv->ranges[priv->num_ranges].start = mod_start;
+ priv->ranges[priv->num_ranges].end = mod_end;
+#ifdef HARD_DEBUG
+ priv->ranges[priv->num_ranges].name = strdup(module_info->name);
+#endif
+ priv->num_ranges += 1;
+
+ LOG("Add module `%s` (0x%lx, 0x%lx)\r\n",
+ module_info->name, mod_start, mod_end);
+
+ for (int range = 0; range < module_info->range_count; range++) {
+ struct range_info *range_info;
+ struct gdb_symtab *symtab;
+ GDB_CORE_ADDR begin, end;
+
+ range_info = (struct range_info *)symfile;
+ symfile += sizeof(*range_info) + range_info->name_length;
+
+ begin = mod_start + range_info->start_offset;
+ end = mod_start + range_info->end_offset;
+
+ LOG("Add range `%s` (0x%lx, 0x%lx), %u lines\r\n",
+ range_info->name,
+ begin, end,
+ range_info->line_count);
+
+ /* A bug in GDB < 9 forces us to open and close the symtab for each
+ * iteration. */
+ symtab = cb->symtab_open(cb, obj, module_info->name);
+ cb->block_open(cb, symtab, NULL, begin, end, range_info->name);
+ cb->symtab_close(cb, symtab);
+
+ for (int line = 0; line < range_info->line_count; line++) {
+ struct gdb_line_mapping line_mapping;
+ struct line_info *line_info;
+
+ line_info = (struct line_info *)symfile;
+ symfile += sizeof(*line_info) + line_info->file_length;
+
+ line_mapping.pc = mod_start + line_info->start_offset;
+ line_mapping.line = line_info->line_number;
+
+ LOG("\t%s:%u\r\n", line_info->file, line_info->line_number);
+
+ /* The symbol table must be opened and closed on every single line
+ * for file names to work properly, as there is no other way to
+ * tell GDB that a certain line belongs to a different file than
+ * the rest of the table. Sigh. */
+ symtab = cb->symtab_open(cb, obj, line_info->file);
+
+ cb->block_open(cb, symtab, NULL, line_mapping.pc, end,
+ range_info->name);
+ cb->line_mapping_add(cb, symtab, 1, &line_mapping);
+ cb->symtab_close(cb, symtab);
+ }
+ }
+
+ cb->object_close(cb, obj);
+
+ return GDB_SUCCESS;
+}
+
+static enum gdb_status read_emulator_info(struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ struct emulator_info *emulator_info) {
+ priv *priv = self->priv_data;
+
+ priv->frame_layout = emulator_info->frame_layout;
+ priv->normal_exit = emulator_info->normal_exit;
+
+ LOG("initialize: frame layout = %i\r\n", priv->frame_layout);
+
+ return GDB_SUCCESS;
+}
+
+static enum gdb_status read_debug_info(struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ void *memory, long memory_sz) {
+ struct debug_info *debug_info = memory;
+
+ (void)memory_sz;
+
+ switch (debug_info->header) {
+ case DEBUG_INFO_HEADER_EMULATOR:
+ return read_emulator_info(self, cb, &debug_info->payload.emu);
+ case DEBUG_INFO_HEADER_MODULE:
+ return read_module_info(self, cb, &debug_info->payload.mod);
+ }
+
+ return GDB_FAIL;
+}
+
+static void regfree(struct gdb_reg_value *reg) {
+ free(reg);
+}
+
+static struct range *get_range(priv *priv, GDB_CORE_ADDR rip) {
+ for (int i = 0; i < priv->num_ranges; i++) {
+ if (rip >= priv->ranges[i].start && rip < priv->ranges[i].end) {
+ return &priv->ranges[i];
+ }
+ }
+
+ return NULL;
+}
+
+static enum gdb_status unwind(struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb) {
+ GDB_CORE_ADDR rbp, rsp, rip;
+ struct range *range;
+ priv *priv;
+
+ rbp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RBP)->value;
+ rsp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RSP)->value;
+ rip = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RIP)->value;
+
+ priv = self->priv_data;
+ range = get_range(priv, rip);
+
+ /* Check that rip points to one of the addresses that we handle */
+ if (range) {
+ struct gdb_reg_value *prev_rbp, *prev_rsp, *prev_rip;
+
+ prev_rbp = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
+ prev_rsp = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
+ prev_rip = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
+
+ LOG("UNWIND match %s: rbp: 0x%lx rsp: 0x%lx rip: 0x%lx \r\n",
+ range->name, rbp, rsp, rip);
+
+ prev_rbp->free = &regfree;
+ prev_rbp->defined = 1;
+ prev_rbp->size = sizeof(char*);
+ prev_rsp->free = &regfree;
+ prev_rsp->defined = 1;
+ prev_rsp->size = sizeof(char*);
+ prev_rip->free = &regfree;
+ prev_rip->defined = 1;
+ prev_rip->size = sizeof(char*);
+
+ if (priv->frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ /* Frame pointers are enabled, which means that rbp will point to
+ * where we stored the previous frames rbp. Also the previous
+ * frames address will be at rbp + 8 and the previous frames rsp
+ * will be rbp + 16.
+ *
+ * 0x00: <- prev_rsp
+ * 0x08: prev call addr
+ * 0x10: prev rbp <- curr rbp
+ * 0x18: current frame
+ * 0x20: <- curr rip */
+ cb->target_read(rbp + 1 * sizeof(char*), &prev_rip->value,
+ sizeof(char*));
+ cb->target_read(rbp + 0 * sizeof(char*), &prev_rbp->value,
+ sizeof(char*));
+ *(GDB_CORE_ADDR*)prev_rsp->value = rbp + sizeof(char*[2]);
+ } else {
+ /* Normal frame layout, we need to scan the stack. */
+ cb->target_read(rsp, &prev_rip->value, sizeof(char*));
+
+ for (rsp += sizeof(char*); ; rsp += sizeof(char*)) {
+ cb->target_read(rsp, &prev_rip->value, sizeof(char*));
+
+ LOG("rsp: 0x%lx rip: 0x%lx\r\n",
+ rsp, *(GDB_CORE_ADDR*)prev_rip->value);
+
+ /* Check if it is a cp */
+ if ((*(GDB_CORE_ADDR*)prev_rip->value & 0x3) == 0) {
+ break;
+ }
+ }
+
+ *(GDB_CORE_ADDR*)prev_rsp->value = rsp;
+ *(GDB_CORE_ADDR*)prev_rbp->value = rsp - sizeof(char*);
+ }
+
+ if (*(GDB_CORE_ADDR*)prev_rip->value == (uintptr_t)priv->normal_exit) {
+ LOG("Normal exit\r\n");
+ *(GDB_CORE_ADDR*)prev_rsp->value = 0;
+ *(GDB_CORE_ADDR*)prev_rbp->value = 0;
+ } else {
+ LOG("UNWIND prev: rbp: 0x%lx rsp: 0x%lx rip: 0x%lx\r\n",
+ *(GDB_CORE_ADDR*)prev_rbp->value,
+ *(GDB_CORE_ADDR*)prev_rsp->value,
+ *(GDB_CORE_ADDR*)prev_rip->value);
+ }
+
+ cb->reg_set(cb, X64_RIP, prev_rip);
+ cb->reg_set(cb, X64_RSP, prev_rsp);
+ cb->reg_set(cb, X64_RBP, prev_rbp);
+
+ return GDB_SUCCESS;
+ }
+
+ LOG("UNWIND no match: rbp: 0x%lx rsp: 0x%lx rip: 0x%lx\r\n", rbp, rsp, rip);
+ return GDB_FAIL;
+}
+
+static struct gdb_frame_id get_frame_id(struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb){
+ struct gdb_frame_id frame = {0, 0};
+ GDB_CORE_ADDR rbp, rsp, rip;
+ struct range *range;
+ priv *priv;
+
+ rbp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RBP)->value;
+ rsp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RSP)->value;
+ rip = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RIP)->value;
+
+ priv = self->priv_data;
+ range = get_range(priv, rip);
+
+ LOG("FRAME: rip: 0x%lx rsp: 0x%lx rbp: 0x%lx \r\n", rip, rsp, rbp);
+
+ if (range) {
+ frame.code_address = rip;
+
+ if (priv->frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ frame.stack_address = rbp + sizeof(char*);
+ } else {
+ GDB_CORE_ADDR prev_rip;
+
+ for (rsp += sizeof(char*); ; rsp += sizeof(char*)) {
+ cb->target_read(rsp, &prev_rip, sizeof(char*));
+
+ LOG("rsp: 0x%lx rip: 0x%lx\r\n", rsp, prev_rip);
+
+ /* Check if it is a cp */
+ if ((prev_rip & 0x3) == 0) {
+ break;
+ }
+ }
+
+ frame.stack_address = rsp;
+ }
+ }
+
+ LOG("FRAME: code_address: 0x%lx stack_address: 0x%lx\r\n",
+ frame.code_address, frame.stack_address);
+
+ return frame;
+}
+
+static void destroy(struct gdb_reader_funcs *self){
+ free(self);
+}
+
+struct gdb_reader_funcs *gdb_init_reader(void){
+ struct gdb_reader_funcs *funcs = malloc(sizeof(struct gdb_reader_funcs));
+ priv *priv_data = malloc(sizeof(priv));
+
+ priv_data->num_ranges = 1;
+ priv_data->ranges = malloc(sizeof(range));
+ priv_data->ranges[0].start = 0;
+ priv_data->ranges[0].end = 0;
+
+ funcs->reader_version = GDB_READER_INTERFACE_VERSION;
+ funcs->priv_data = priv_data;
+
+ funcs->read = read_debug_info;
+ funcs->unwind = unwind;
+ funcs->get_frame_id = get_frame_id;
+ funcs->destroy = destroy;
+
+#ifdef HARD_DEBUG
+ log = fopen("/tmp/jit-reader.log","w+");
+ if (!log) fprintf(stderr,"Could not open /tmp/jit-reader.log");
+#endif
+
+ return funcs;
+}
diff --git a/erts/etc/unix/gdb-tools/jit-reader.mk b/erts/etc/unix/gdb-tools/jit-reader.mk
new file mode 100644
index 0000000000..8ef0bccec2
--- /dev/null
+++ b/erts/etc/unix/gdb-tools/jit-reader.mk
@@ -0,0 +1,9 @@
+EXTRA_LIBS = $(BINDIR)/jit-reader.so
+
+jit-reader: $(EXTRA_LIBS)
+
+$(OBJDIR)/jit-reader.o: $(GDB_TOOLS)/jit-reader.c $(GDB_TOOLS)/jit-reader.h
+ $(V_CC) $(DED_CFLAGS) -I$(ETC) -o $@ -c $<
+
+$(BINDIR)/jit-reader.so: $(OBJDIR)/jit-reader.o
+ $(V_LD) $(DED_LDFLAGS) -o $@ $^

View file

@ -0,0 +1,24 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Thu, 24 Oct 2013 16:44:22 +0400
Subject: [PATCH] TEMPORARILY disable ECC until dust settles
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 42fb172..eb99719 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -74,13 +74,6 @@
# define HAVE_DES_ede3_cfb_encrypt
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x009080ffL \
- && !defined(OPENSSL_NO_EC) \
- && !defined(OPENSSL_NO_ECDH) \
- && !defined(OPENSSL_NO_ECDSA)
-# define HAVE_EC
-#endif
-
#if defined(HAVE_EC)
#include <openssl/ec.h>
#include <openssl/ecdh.h>

View file

@ -0,0 +1,26 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Mon, 28 Oct 2013 17:11:11 +0400
Subject: [PATCH] Fix for powerpc architecture
Taken from openSUSE:
* https://build.opensuse.org/package/view_file/devel:languages:erlang:Factory/erlang/erlang-ppc.patch?expand=1
See also:
* https://bugzilla.redhat.com/1023960
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
diff --git a/erts/configure.in b/erts/configure.in
index 230f27a..9ad3671 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -612,6 +612,7 @@ case $chk_arch_ in
x86_64) ARCH=amd64;;
amd64) ARCH=amd64;;
macppc) ARCH=ppc;;
+ powerpc) ARCH=ppc;;
ppc) ARCH=ppc;;
ppc64) ARCH=ppc64;;
"Power Macintosh") ARCH=ppc;;

View file

@ -0,0 +1,74 @@
From: "Matwey V. Kornilov" <matwey.kornilov@gmail.com>
Date: Tue, 17 Dec 2013 18:16:56 +0400
Subject: [PATCH] Add -systemd option to empd. Check for include
systemd/sd-daemon.h and wrap systemd code into ifdef-s.
diff --git a/erts/configure.in b/erts/configure.in
index 9ad3671..125e579 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -1565,6 +1565,8 @@ AC_CHECK_MEMBERS([struct ifreq.ifr_enaddr], [], [],
#endif
])
+AC_CHECK_HEADERS(systemd/sd-daemon.h)
+
dnl ----------------------------------------------------------------------
dnl Check the availability for libdlpi
dnl ----------------------------------------------------------------------
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 2d55b37..fc58882 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -175,6 +175,9 @@ int main(int argc, char** argv)
g->nodes.reg = g->nodes.unreg = g->nodes.unreg_tail = NULL;
g->nodes.unreg_count = 0;
g->active_conn = 0;
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ g->is_systemd = 0;
+#endif
for (i = 0; i < MAX_LISTEN_SOCKETS; i++)
g->listenfd[i] = -1;
@@ -248,8 +251,12 @@ int main(int argc, char** argv)
else
usage(g);
epmd_cleanup_exit(g,0);
- }
- else
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ } else if (strcmp(argv[0], "-systemd") == 0) {
+ g->is_systemd = 1;
+ argv++; argc--;
+#endif
+ } else
usage(g);
}
dbg_printf(g,1,"epmd running - daemon = %d",g->is_daemon);
@@ -454,6 +461,11 @@ static void usage(EpmdVars *g)
fprintf(stderr, " Forcibly unregisters a name with epmd\n");
fprintf(stderr, " (only allowed if -relaxed_command_check was given when \n");
fprintf(stderr, " epmd was started).\n");
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ fprintf(stderr, " -systemd\n");
+ fprintf(stderr, " Wait for socket from systemd. The option makes sense\n");
+ fprintf(stderr, " when started from .socket unit.\n");
+#endif
epmd_cleanup_exit(g,1);
}
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 656dbd1..bf1ddd8 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -321,6 +321,9 @@ typedef struct {
int listenfd[MAX_LISTEN_SOCKETS];
char *addresses;
char **argv;
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ int is_systemd;
+#endif
} EpmdVars;
void dbg_printf(EpmdVars*,int,const char*,...);

View file

@ -0,0 +1,111 @@
From: "Matwey V. Kornilov" <matwey.kornilov@gmail.com>
Date: Tue, 17 Dec 2013 18:57:54 +0400
Subject: [PATCH] Add systemd support to epmd
diff --git a/erts/configure.in b/erts/configure.in
index 125e579..d9bc1ec 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -969,6 +969,8 @@ AC_CHECK_LIB(dl, dlopen)
AC_CHECK_LIB(inet, main)
AC_CHECK_LIB(util, openpty)
+AC_CHECK_LIB(systemd-daemon, sd_listen_fds)
+
dnl Try to find a thread library.
dnl
dnl ETHR_LIB_NAME, ETHR_LIBS, ETHR_X_LIBS, ETHR_THR_LIB_BASE and ETHR_DEFS
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index bf1ddd8..363923e 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -110,6 +110,10 @@
#include <stdarg.h>
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+# include <systemd/sd-daemon.h>
+#endif
+
/* ************************************************************************ */
/* Replace some functions by others by making the function name a macro */
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 90df7cc..cb8ca96 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -208,6 +208,39 @@ void run(EpmdVars *g)
node_init(g);
g->conn = conn_init(g);
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ if (g->is_systemd)
+ {
+ int n;
+
+ dbg_printf(g,2,"try to obtain sockets from systemd");
+
+ n = sd_listen_fds(0);
+ if (n < 0)
+ {
+ dbg_perror(g,"cannot obtain sockets from systemd");
+ epmd_cleanup_exit(g,1);
+ }
+ else if (n == 0)
+ {
+ dbg_tty_printf(g,0,"systemd provides no sockets");
+ epmd_cleanup_exit(g,1);
+ }
+ else if (n > MAX_LISTEN_SOCKETS)
+ {
+ dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses", MAX_LISTEN_SOCKETS);
+ epmd_cleanup_exit(g,1);
+ }
+ num_sockets = n;
+ for (i = 0; i < num_sockets; i++)
+ {
+ g->listenfd[i] = listensock[i] = SD_LISTEN_FDS_START + i;
+ }
+ }
+ else
+ {
+#endif
+
dbg_printf(g,2,"try to initiate listening port %d", g->port);
if (g->addresses != NULL && /* String contains non-separator characters if: */
@@ -272,6 +305,9 @@ void run(EpmdVars *g)
SET_ADDR(iserv_addr[0],EPMD_ADDR_ANY,sport);
num_sockets = 1;
}
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ }
+#endif
#if !defined(__WIN32__)
/* We ignore the SIGPIPE signal that is raised when we call write
@@ -289,6 +325,13 @@ void run(EpmdVars *g)
FD_ZERO(&g->orig_read_mask);
g->select_fd_top = 0;
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ if (g->is_systemd)
+ for (i = 0; i < num_sockets; i++)
+ select_fd_set(g, listensock[i]);
+ else
+ {
+#endif
for (i = 0; i < num_sockets; i++)
{
if ((listensock[i] = socket(FAMILY,SOCK_STREAM,0)) < 0)
@@ -351,6 +394,9 @@ void run(EpmdVars *g)
}
select_fd_set(g, listensock[i]);
}
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ }
+#endif
dbg_tty_printf(g,2,"entering the main select() loop");

View file

@ -0,0 +1,45 @@
From: Peter Lemenkov <lemenkov@gmail.com>
Date: Fri, 6 Jun 2014 15:29:49 +0400
Subject: [PATCH] Added systemd notify support to EPMD
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
Conflicts:
erts/configure.in
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index fc58882..1757fa9 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -589,9 +589,11 @@ void epmd_cleanup_exit(EpmdVars *g, int exitval)
for(i=0; g->argv[i] != NULL; ++i)
free(g->argv[i]);
free(g->argv);
- }
-
-
+ }
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+ sd_notifyf(0, "STATUS=Exited.\n"
+ "ERRNO=%i", exitval);
+#endif // HAVE_SYSTEMD_SD_DAEMON_H
exit(exitval);
}
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index cb8ca96..78524a6 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -394,8 +394,11 @@ void run(EpmdVars *g)
}
select_fd_set(g, listensock[i]);
}
-#ifdef HAVE_SYSTEMD_SD_DAEMON_H
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H
}
+ sd_notifyf(0, "READY=1\n"
+ "STATUS=Processing port mapping requests...\n"
+ "MAINPID=%lu", (unsigned long) getpid());
#endif
dbg_tty_printf(g,2,"entering the main select() loop");

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

@ -17,6 +17,18 @@
#
# # start of autogenerated patch tag list
# # end of autogenerated patch tag list
# # start of autogenerated prep patch list
# # end of autogenerated prep patch list
#
# The following special comment lines in the git commit messages
# will be interpreted:
#
# Fedora-Spec-Comment: This patch only applies to EL6 builds
# Fedora-Spec-Before: %if 0%?el6}
# Fedora-Spec-After: %endif
#
# If there is no "Fedora-Spec-Comment:" line, we will use
# "Fedora specific patch".
# Command line parsing
otp_dir="${1:?'Fatal: otp git repo dir required'}"
@ -37,29 +49,44 @@ test -s "$tmpdir/patch-list.txt"
# Process patch files
echo "# start of autogenerated patch tag list" > "$tmpdir/patch-list-tags.txt"
echo "# start of autogenerated prep patch list" > "$tmpdir/patch-list-prep.txt"
n=1
while read patch
do
otppatch="$(dirname "$patch")/otp-$(basename "$patch")"
${SED-sed} -e '1d' -e '/^-- $/,$d' "$patch" > "$otppatch"
rm -f "$patch"
comment="$(sed -n 's/^Fedora-Spec-Comment:\s*//p' "$otppatch")"
if test "x$comment" = "x"; then comment="Fedora specific patch"; fi
echo "# ${comment}" >> "$tmpdir/patch-list-tags.txt"
echo "# $(sed -n 's/^Subject: \[PATCH\] //p' "$otppatch")" >> "$tmpdir/patch-list-tags.txt"
echo "Patch$n: $(basename "$otppatch")" >> "$tmpdir/patch-list-tags.txt"
base="$(basename "$patch" ".patch" | sed 's/^00[0-9][0-9]-//')"
backupext=".$(echo -n "$base" | tr -c -s '[:alnum:]' '_')"
sed -n 's/^Fedora-Spec-Before:\s*//p' "$otppatch" >> "$tmpdir/patch-list-prep.txt"
echo "%patch$n -p1 -b ${backupext}" >> "$tmpdir/patch-list-prep.txt"
sed -n 's/^Fedora-Spec-After:\s*//p' "$otppatch" >> "$tmpdir/patch-list-prep.txt"
n=$(($n + 1))
done < "$tmpdir/patch-list.txt"
echo "# end of autogenerated patch tag list" >> "$tmpdir/patch-list-tags.txt"
echo "# end of autogenerated prep patch list" >> "$tmpdir/patch-list-prep.txt"
# Create updated spec file
specfile="erlang.spec"
newspec1="${tmpdir}/${specfile}.new1"
newspec2="${tmpdir}/${specfile}.new2"
sed '/^# start of autogenerated patch tag list$/,$d' "$specfile" > "$newspec1"
cat "$tmpdir/patch-list-tags.txt" >> "$newspec1"
sed '1,/^# end of autogenerated patch tag list/d' "$specfile" >> "$newspec1"
sed '/^# start of autogenerated prep patch list$/,$d' "$newspec1" > "$newspec2"
cat "$tmpdir/patch-list-prep.txt" >> "$newspec2"
sed '1,/^# end of autogenerated prep patch list/d' "$newspec1" >> "$newspec2"
# Actually put all changes into git index
git rm -f otp-00*.patch
mv "$tmpdir/otp-00"*.patch .
git add otp-00*.patch
mv -f "$newspec1" "$specfile"
mv -f "$newspec2" "$specfile"
git add "$specfile"
rm -rf "$tmpdir"

View file

@ -1,174 +0,0 @@
import glob
import os
import re
import rpm
import sys
ts = rpm.TransactionSet()
packages = []
for arg in sys.argv[1:]:
packages += glob.glob(arg)
erlang_provides = {}
erlang_requires = {}
package_names = []
package_headers = {}
##
## Custom tweaks begins here
##
# These packages should be marked as noarch
package_noarch = [
"emacs-erlang",
"emacs-erlang-el",
"erlang-doc"]
# These are additional Requires which cannot be picked up automatically (yet).
# TODO these should be added automatically
package_additional_requires = {
"emacs-erlang": ["emacs-common-erlang = %{version}-%{release}", "emacs(bin) >= %{_emacs_version}" ],
"emacs-erlang-el": ["emacs-erlang = %{version}-%{release}"],
"erlang-dialyzer": ["graphviz"],
"erlang-erl_interface": ["%{name}-erts%{?_isa} = %{version}-%{release}"],
# This library (lksctp-tools) is dlopened so it can't be picked
# up automatically by the RPM dependency checker
"erlang-erts": ["lksctp-tools"],
"erlang-gs": ["tk"],
# Stores files/links in /usr/share/java so has to depend on jpackage-utils
"erlang-ic": ["jpackage-utils"],
# Stores files/links in /usr/share/java so has to depend on jpackage-utils
"erlang-jinterface": ["%{name}-erts%{?_isa} = %{version}-%{release}", "jpackage-utils"],
"erlang-wx": ["mesa-libGL", "mesa-libGLU"],
}
package_additional_buildrequires = {
"emacs-erlang": ["emacs", "emacs-el"],
"erlang-crypto": ["openssl-devel"],
"erlang-diameter": ["ed"],
# BEWARE. No fop for EPEL5, and only for x86/x86_64 in EPEL6,
# so we cannot regenerate docs here. (Un)Fortunately we dropped
# support for EPEL6 and older versions.
# FIXME add bootstrap condition first.
"erlang-doc": ["fop", "libxslt"],
"erlang-erts": ["lksctp-tools-devel", "m4", "ncurses-devel", "zlib-devel"],
"erlang-gs": ["tcl-devel", "tk-devel"],
# in EPEL6 on arches different from %{ix86} x86_64 we have to
# use java-devel-gcj, so technically this requirement makes it
# impossible to build Java support there. (Un)Fortunately we
# already dropped full support for EPEL6 and older versions.
"erlang-ic": ["java-devel"],
"erlang-jinterface": ["java-devel"],
"erlang-odbc": ["unixODBC-devel"],
}
package_additional_obsoletes = {
"erlang-erts": [
"erlang-appmon",
"erlang-docbuilder",
"erlang-inviso",
"erlang-pman",
"erlang-toolbar",
"erlang-tv"],
}
##
## Custom tweaks ends here
##
# To match 'erlang(asn1ct_eval_ext:transform_to_EXTERNAL1994/1)'
prog = re.compile("^erlang(.*:.*/\d+)")
rpmmask = re.compile(".*\.rpm")
# iterate over all rpms
for package in sorted([p for p in packages if rpmmask.match(p)]):
# A tricky part. We are processing packages, rebuilt with
# %{__erlang_provides_requires}. Otherwise we won't get information
# about imports/exports (until we learn how to parse Erlang BEAM file
# headers with Python.
fd = os.open(package, os.O_RDONLY)
h = ts.hdrFromFdno(fd)
os.close(fd)
rpm_name = h[rpm.RPMTAG_NAME]
# Let's calculate provides
# We'll create dictionary to speedup future use
# FIXME duplicate provides
local_provides = [p for p in h[rpm.RPMTAG_PROVIDENAME] if prog.match(p)]
erlang_provides.update({k: rpm_name for k in local_provides})
# Let's calculate requires
erlang_requires.update({rpm_name: [r for r in h[rpm.RPMTAG_REQUIRENAME] if prog.match(r) and not r in local_provides]})
package_headers.update({rpm_name: h})
package_names.append(rpm_name)
namemask = re.compile("^erlang-[a-zA-Z0-9_]*$")
print "### BEGIN OF AUTOGENERATED LIST ###"
print ""
for name in package_names:
h = package_headers[name]
if name == "erlang-doc":
# Additional ifdef just for this sub-package (see below)
print "%if %{with doc}"
if namemask.match(name):
print "%%package %s" % name.replace("erlang-", "")
else:
print "%%package -n %s" % name
print "Summary: %s" % h[rpm.RPMTAG_SUMMARY]
print "Group: %s" % h[rpm.RPMTAG_GROUP]
rawdeps = [erlang_provides.get(r, "Error: missing requires: %s" % r) for r in erlang_requires[name]]
deps = set()
dependency_add = deps.add
[x for x in rawdeps if not (x in deps or dependency_add(x))]
# Additional BuildRequires (if any):
for br in package_additional_buildrequires.get(name, []):
print "BuildRequires: %s" % br
# Add basic autogenerated Requires:
for r in sorted(deps):
#Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
print "Requires: %s%%{?_isa} = %%{version}-%%{release}" % r.replace("erlang-", "%{name}-")
# Add custom additional Requires (if any):
for r in package_additional_requires.get(name, []):
print "Requires: %s" % r
# Add custom additional Obsoletes (if any):
for os in package_additional_obsoletes.get(name, []):
print "Obsoletes: %s" % os
if name in package_noarch:
print "BuildArch: noarch"
print ""
if namemask.match(name):
print "%%description %s" % name.replace("erlang-", "")
else:
print "%%description -n %s" % name
print "%s" % h[rpm.RPMTAG_DESCRIPTION]
if name == "erlang-doc":
# Additional ifdef just for this sub-package (see above)
print "%endif"
print ""
print "### END OF AUTOGENERATED LIST ###"

View file

@ -1 +1 @@
SHA512 (otp-OTP-26.2.5.16.tar.gz) = 4e973be7e8ccad196d59759108a521535b0f046268eb0406f789a50f411fa27c9c11fcfb61a7218605bf1b32921bb52c52fc7c99917e1acfc0d3ed09437129b2
e5ece977375197338c1b93b3d88514f8 otp_src_R16B03-1.tar.gz