aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/doc/src/code.xml2
-rw-r--r--lib/kernel/doc/src/config.xml2
-rw-r--r--lib/kernel/doc/src/disk_log.xml6
-rw-r--r--lib/kernel/doc/src/error_logger.xml15
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml2
-rw-r--r--lib/kernel/doc/src/inet.xml36
-rw-r--r--lib/kernel/doc/src/kernel_app.xml26
-rw-r--r--lib/kernel/doc/src/net_kernel.xml13
-rw-r--r--lib/kernel/doc/src/notes.xml10
-rw-r--r--lib/kernel/doc/src/os.xml7
-rw-r--r--lib/kernel/doc/src/seq_trace.xml2
-rw-r--r--lib/kernel/include/inet.hrl2
-rw-r--r--lib/kernel/src/Makefile1
-rw-r--r--lib/kernel/src/code.erl2
-rw-r--r--lib/kernel/src/disk_log.erl7
-rw-r--r--lib/kernel/src/disk_log.hrl6
-rw-r--r--lib/kernel/src/disk_log_1.erl28
-rw-r--r--lib/kernel/src/dist_ac.erl2
-rw-r--r--lib/kernel/src/dist_util.erl21
-rw-r--r--lib/kernel/src/erl_signal_handler.erl2
-rw-r--r--lib/kernel/src/error_logger.erl22
-rw-r--r--lib/kernel/src/file.erl2
-rw-r--r--lib/kernel/src/global.erl5
-rw-r--r--lib/kernel/src/group.erl3
-rw-r--r--lib/kernel/src/group_history.erl341
-rw-r--r--lib/kernel/src/inet.erl10
-rw-r--r--lib/kernel/src/inet_int.hrl3
-rw-r--r--lib/kernel/src/inet_parse.erl2
-rw-r--r--lib/kernel/src/inet_udp.erl2
-rw-r--r--lib/kernel/src/kernel.app.src1
-rw-r--r--lib/kernel/src/kernel.appup.src2
-rw-r--r--lib/kernel/src/kernel.erl4
-rw-r--r--lib/kernel/src/net_kernel.erl40
-rw-r--r--lib/kernel/src/os.erl2
-rw-r--r--lib/kernel/src/rpc.erl2
-rw-r--r--lib/kernel/test/application_SUITE.erl2
-rw-r--r--lib/kernel/test/code_SUITE.erl24
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl19
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl109
-rw-r--r--lib/kernel/test/erl_distribution_wb_SUITE.erl2
-rw-r--r--lib/kernel/test/error_logger_SUITE.erl2
-rw-r--r--lib/kernel/test/file_SUITE.erl2
-rw-r--r--lib/kernel/test/file_name_SUITE.erl4
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl8
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl4
-rw-r--r--lib/kernel/test/inet_SUITE.erl72
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl2
-rw-r--r--lib/kernel/test/multi_load_SUITE.erl2
-rw-r--r--lib/kernel/test/pg2_SUITE.erl2
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl2
-rw-r--r--lib/kernel/test/rpc_SUITE.erl2
51 files changed, 804 insertions, 87 deletions
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 878a450f0f..c94f612c01 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/doc/src/config.xml b/lib/kernel/doc/src/config.xml
index c10f11b187..fdb2d29f63 100644
--- a/lib/kernel/doc/src/config.xml
+++ b/lib/kernel/doc/src/config.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml
index aebeacee28..570d3ef9bd 100644
--- a/lib/kernel/doc/src/disk_log.xml
+++ b/lib/kernel/doc/src/disk_log.xml
@@ -968,6 +968,12 @@
<c>read_write</c>.
</p>
</item>
+ <tag><c>{quiet, Boolean}</c></tag>
+ <item>
+ <p>Specifies if messages will be sent to
+ <c>error_logger</c> on recoverable errors with
+ the log files. Defaults to <c>true</c>.</p>
+ </item>
</taglist>
<p><c>open/1</c> returns <c>{ok, <anno>Log</anno>}</c> if the
log file is successfully opened. If the file is
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index 814e8eac46..27db00819f 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -163,6 +163,19 @@ ok</pre>
</desc>
</func>
<func>
+ <name name="get_format_depth" arity="0"/>
+ <fsummary>Get the value of the Kernel application variable
+ <c>error_logger_format_depth</c>.</fsummary>
+ <desc>
+ <p>Returns <c>max(10, Depth)</c>, where <c>Depth</c> is the
+ value of
+ <seealso marker="kernel:kernel_app#error_logger_format_depth">
+ error_logger_format_depth</seealso>
+ in the Kernel application, if Depth is an integer. Otherwise,
+ <c>unlimited</c> is returned.</p>
+ </desc>
+ </func>
+ <func>
<name name="info_msg" arity="1"/>
<name name="info_msg" arity="2"/>
<fsummary>Send a standard information event to the error logger.</fsummary>
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index bef8096aed..070782e1f3 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 076e50cd10..b71e8a1e5d 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -75,8 +75,8 @@ Address ip_address()
------- ------------
::1 {0,0,0,0,0,0,0,1}
::192.168.42.2 {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
-FFFF::192.168.42.2
- {16#FFFF,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
+::FFFF:192.168.42.2
+ {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
3ffe:b80:1f8d:2:204:acff:fe17:bf38
{16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38}
fe80::204:acff:fe17:bf38
@@ -87,8 +87,8 @@ fe80::204:acff:fe17:bf38
<pre>
1> <input>inet:parse_address("192.168.42.2").</input>
{ok,{192,168,42,2}}
-2> <input>inet:parse_address("FFFF::192.168.42.2").</input>
-{ok,{65535,0,0,0,0,0,49320,10754}}</pre>
+2> <input>inet:parse_address("::FFFF:192.168.42.2").</input>
+{ok,{0,0,0,0,0,65535,49320,10754}}</pre>
</description>
<datatypes>
@@ -897,6 +897,32 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
<seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding/0</c></seealso>.</p></item>
</list>
</item>
+ <tag><c>{bind_to_device, Ifname :: binary()}</c></tag>
+ <item>
+ <p>Binds a socket to a specific network interface. This option
+ must be used in a function call that creates a socket, that is,
+ <seealso marker="gen_tcp#connect/3"><c>gen_tcp:connect/3,4</c></seealso>,
+ <seealso marker="gen_tcp#listen/2"><c>gen_tcp:listen/2</c></seealso>,
+ <seealso marker="gen_udp#open/1"><c>gen_udp:open/1,2</c></seealso>, or
+ <seealso marker="gen_sctp#open/0"><c>gen_sctp:open/0,1,2</c></seealso>.</p>
+ <p>Unlike <seealso marker="#getifaddrs/0"><c>getifaddrs/0</c></seealso>, Ifname
+ is encoded a binary. In the unlikely case that a system is using
+ non-7-bit-ASCII characters in network device names, special care
+ has to be taken when encoding this argument.</p>
+ <p>This option uses the Linux-specific socket option
+ <c>SO_BINDTODEVICE</c>, such as in Linux kernel 2.0.30 or later,
+ and therefore only exists when the runtime system
+ is compiled for such an operating system.</p>
+ <p>Before Linux 3.8, this socket option could be set, but could not retrieved
+ with <seealso marker="#getopts/2"><c>getopts/2</c></seealso>. Since Linux 3.8,
+ it is readable.</p>
+ <p>The virtual machine also needs elevated privileges, either
+ running as superuser or (for Linux) having capability
+ <c>CAP_NET_RAW</c>.</p>
+ <p>The primary use case for this option is to bind sockets into
+ <url href="http://www.kernel.org/doc/Documentation/networking/vrf.txt">Linux VRF instances</url>.
+ </p>
+ </item>
<tag><c>list</c></tag>
<item>
<p>Received <c>Packet</c> is delivered as a list.</p>
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index b342fff0d3..75e1e18d86 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -58,6 +58,7 @@
</section>
<section>
+ <marker id="erl_signal_server"/>
<title>OS Signal Event Handler</title>
<p>Asynchronous OS signals may be subscribed to via the Kernel applications event manager
(see <seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso> and
@@ -419,6 +420,29 @@ MaxT = TickTime + TickTime / 4</code>
using this service.</p>
<p>Defaults to <c>false</c>.</p>
</item>
+ <tag><c>shell_history = enabled | disabled </c></tag>
+ <item>
+ <p>Specifies whether shell history should be logged to disk
+ between usages of <c>erl</c>.</p>
+ </item>
+ <tag><c>shell_history_drop = [string()]</c></tag>
+ <item>
+ <p>Specific log lines that should not be persisted. For
+ example <c>["q().", "init:stop()."]</c> will allow to
+ ignore commands that shut the node down. Defaults to
+ <c>[]</c>.</p>
+ </item>
+ <tag><c>shell_history_file_bytes = integer()</c></tag>
+ <item>
+ <p>how many bytes the shell should remember. By default, the
+ value is set to 512kb, and the minimal value is 50kb.</p>
+ </item>
+ <tag><c>shell_history_path = string()</c></tag>
+ <item>
+ <p>Specifies where the shell history files will be stored.
+ defaults to the user's cache directory as returned by
+ <c>filename:basedir(user_cache, "erlang-history")</c>.</p>
+ </item>
<tag><c>shutdown_func = {Mod, Func}</c></tag>
<item>
<p>Where:</p>
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 4e2b0c69db..7ddb849824 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -64,6 +64,19 @@ $ <input>erl -sname foobar</input></pre>
by the magic cookie system, see section
<seealso marker="doc/reference_manual:distributed">Distributed Erlang</seealso>
in the Erlang Reference Manual.</p>
+ <warning>
+ <p>
+ Starting a distributed node without also specifying
+ <seealso marker="erts:erl#proto_dist"><c>-proto_dist inet_tls</c></seealso>
+ will expose the node to attacks that may give the attacker
+ complete access to the node and in extension the cluster.
+ When using un-secure distributed nodes, make sure that the
+ network is configured to keep potential attackers out.
+ See the <seealso marker="ssl:ssl_distribution">
+ Using SSL for Erlang Distribution</seealso> User's Guide
+ for details on how to setup a secure distributed node.
+ </p>
+ </warning>
</description>
<funcs>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index ad349c5aaf..7127a59a0c 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -166,6 +166,14 @@
<p>
Own Id: OTP-13564</p>
</item>
+ <item>
+ <p>
+ Rudimentary support for DSCP has been implemented
+ in the guise of a <c>tclass</c> socket option
+ for IPv6 sockets.</p>
+ <p>
+ Own Id: OTP-13582</p>
+ </item>
</list>
</section>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 6ba69d12a3..0e9add4161 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -174,8 +174,9 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
<tag><c>handle</c></tag>
<item>
- This signal will notify <c>erl_signal_server</c> when it is received by
- the Erlang runtime system.
+ This signal will notify
+ <seealso marker="kernel_app#erl_signal_server"><c>erl_signal_server</c></seealso>
+ when it is received by the Erlang runtime system.
</item>
</taglist>
</desc>
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index b80e87c118..197851021f 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2016</year>
+ <year>1998</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/include/inet.hrl b/lib/kernel/include/inet.hrl
index df788aca08..daa2e14b46 100644
--- a/lib/kernel/include/inet.hrl
+++ b/lib/kernel/include/inet.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 2a89faaf13..78aa6192a9 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -85,6 +85,7 @@ MODULES = \
global_group \
global_search \
group \
+ group_history \
heart \
hipe_unified_loader \
inet \
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 2a06d0cb15..9969021a6c 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 2ade7fd77a..70cbf1c87c 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -638,6 +638,8 @@ check_arg([{mode, read_only}|Tail], Res) ->
check_arg(Tail, Res#arg{mode = read_only});
check_arg([{mode, read_write}|Tail], Res) ->
check_arg(Tail, Res#arg{mode = read_write});
+check_arg([{quiet, Boolean}|Tail], Res) when is_boolean(Boolean) ->
+ check_arg(Tail, Res#arg{quiet = Boolean});
check_arg(Arg, _) ->
{error, {badarg, Arg}}.
@@ -1276,7 +1278,8 @@ compare_arg(_Attr, _Val, _A) ->
do_open(A) ->
#arg{type = Type, format = Format, name = Name, head = Head0,
file = FName, repair = Repair, size = Size, mode = Mode,
- version = V} = A,
+ quiet = Quiet, version = V} = A,
+ disk_log_1:set_quiet(Quiet),
Head = mk_head(Head0, Format),
case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of
{ok, Ret, Extra, FormatType, NoItems} ->
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 593dbb31ab..a362881f40 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -69,13 +69,14 @@
| {file, FileName :: file:filename()}
| {linkto, LinkTo :: none | pid()}
| {repair, Repair :: true | false | truncate}
- | {type, Type :: dlog_type}
+ | {type, Type :: dlog_type()}
| {format, Format :: dlog_format()}
| {size, Size :: dlog_size()}
| {distributed, Nodes :: [node()]}
| {notify, boolean()}
| {head, Head :: dlog_head_opt()}
| {head_func, MFA :: {atom(), atom(), list()}}
+ | {quiet, boolean()}
| {mode, Mode :: dlog_mode()}.
-type dlog_options() :: [dlog_option()].
-type dlog_repair() :: 'truncate' | boolean().
@@ -102,6 +103,7 @@
head = none,
mode = read_write :: dlog_mode(),
notify = false :: boolean(),
+ quiet = false :: boolean(),
options = [] :: dlog_options()}).
-record(cache, %% Cache for logged terms (per file descriptor).
diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl
index d83c30f35f..10c22e1ad6 100644
--- a/lib/kernel/src/disk_log_1.erl
+++ b/lib/kernel/src/disk_log_1.erl
@@ -37,6 +37,7 @@
-export([get_wrap_size/1]).
-export([is_head/1]).
-export([position/3, truncate_at/3, fwrite/4, fclose/2]).
+-export([set_quiet/1, is_quiet/0]).
-compile({inline,[{scan_f2,7}]}).
@@ -500,7 +501,10 @@ lh(H, _F) -> % cannot happen
repair(In, File) ->
FSz = file_size(File),
- error_logger:info_msg("disk_log: repairing ~tp ...\n", [File]),
+ case is_quiet() of
+ true -> ok;
+ _ -> error_logger:info_msg("disk_log: repairing ~tp ...\n", [File])
+ end,
Tmp = add_ext(File, "TMP"),
{ok, {_Alloc, Out, {0, _}, _FileSize}} = new_int_file(Tmp, none),
scan_f_read(<<>>, In, Out, File, FSz, Tmp, ?MAX_CHUNK_SIZE, 0, 0).
@@ -769,8 +773,11 @@ mf_int_chunk(Handle, {FileNo, Pos}, Bin, N) ->
NFileNo = inc(FileNo, Handle#handle.maxF),
case catch int_open(FName, true, read_only, any) of
{error, _Reason} ->
- error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
- [FName]),
+ case is_quiet() of
+ true -> ok;
+ _ -> error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
+ [FName])
+ end,
mf_int_chunk(Handle, {NFileNo, 0}, [], N);
{ok, {_Alloc, FdC, _HeadSize, _FileSize}} ->
case chunk(FdC, FName, Pos, Bin, N) of
@@ -797,9 +804,12 @@ mf_int_chunk_read_only(Handle, {FileNo, Pos}, Bin, N) ->
NFileNo = inc(FileNo, Handle#handle.maxF),
case catch int_open(FName, true, read_only, any) of
{error, _Reason} ->
- error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
- [FName]),
- mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N);
+ case is_quiet() of
+ true -> ok;
+ _ -> error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n",
+ [FName])
+ end,
+ mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N);
{ok, {_Alloc, FdC, _HeadSize, _FileSize}} ->
case do_chunk_read_only(FdC, FName, Pos, Bin, N) of
{NewFdC, eof} ->
@@ -1549,6 +1559,12 @@ fclose(#cache{fd = Fd, c = C}, FileName) ->
_ = write_cache_close(Fd, FileName, C),
file:close(Fd).
+set_quiet(Bool) ->
+ put(quiet, Bool).
+
+is_quiet() ->
+ get(quiet) =:= true.
+
%% -> {Reply, #cache{}}; Reply = ok | Error
write_cache(Fd, _FileName, []) ->
{ok, #cache{fd = Fd}};
diff --git a/lib/kernel/src/dist_ac.erl b/lib/kernel/src/dist_ac.erl
index e63c969b79..2a5cf0ba92 100644
--- a/lib/kernel/src/dist_ac.erl
+++ b/lib/kernel/src/dist_ac.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index d929179715..b3507e5d13 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -572,12 +572,25 @@ recv_name(#hs_data{socket = Socket, f_recv = Recv}) ->
?shutdown(no_node)
end.
-get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode]) ->
- {?u32(Flag1, Flag2, Flag3, Flag4), list_to_atom(OtherNode),
- ?u16(VersionA,VersionB)};
+get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode] = Data) ->
+ case is_valid_name(OtherNode) of
+ true ->
+ {?u32(Flag1, Flag2, Flag3, Flag4), list_to_atom(OtherNode),
+ ?u16(VersionA,VersionB)};
+ false ->
+ ?shutdown(Data)
+ end;
get_name(Data) ->
?shutdown(Data).
+is_valid_name(OtherNodeName) ->
+ case string:lexemes(OtherNodeName,"@") of
+ [_OtherNodeName,_OtherNodeHost] ->
+ true;
+ _else ->
+ false
+ end.
+
publish_type(Flags) ->
case Flags band ?DFLAG_PUBLISHED of
0 ->
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
index 8f924d2adc..22f235d4e4 100644
--- a/lib/kernel/src/erl_signal_handler.erl
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. 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
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index 3ee8e2c6e6..9bf8547745 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,8 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2]).
+-export([get_format_depth/0, limit_term/1]).
+
-define(buffer_size, 10).
%%-----------------------------------------------------------------
@@ -518,3 +520,21 @@ string_p1([H|T]) when is_list(H) ->
end;
string_p1([]) -> true;
string_p1(_) -> false.
+
+-spec limit_term(term()) -> term().
+
+limit_term(Term) ->
+ case get_format_depth() of
+ unlimited -> Term;
+ D -> io_lib:limit_term(Term, D)
+ end.
+
+-spec get_format_depth() -> 'unlimited' | pos_integer().
+
+get_format_depth() ->
+ case application:get_env(kernel, error_logger_format_depth) of
+ {ok, Depth} when is_integer(Depth) ->
+ max(10, Depth);
+ undefined ->
+ unlimited
+ end.
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 79e72cdc6d..933f2d5f65 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 5e8bc2ba5d..a9e92b28b8 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -447,7 +447,8 @@ info() ->
init([]) ->
process_flag(trap_exit, true),
_ = ets:new(global_locks, [set, named_table, protected]),
- _ = ets:new(global_names, [set, named_table, protected]),
+ _ = ets:new(global_names, [set, named_table, protected,
+ {read_concurrency, true}]),
_ = ets:new(global_names_ext, [set, named_table, protected]),
_ = ets:new(global_pid_names, [bag, named_table, protected]),
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index b5e73117dd..0eeaaad8d2 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -33,7 +33,7 @@ start(Drv, Shell, Options) ->
server(Drv, Shell, Options) ->
process_flag(trap_exit, true),
edlin:init(),
- put(line_buffer, proplists:get_value(line_buffer, Options, [])),
+ put(line_buffer, proplists:get_value(line_buffer, Options, group_history:load())),
put(read_mode, list),
put(user_drv, Drv),
put(expand_fun,
@@ -783,6 +783,7 @@ save_line_buffer("\n", Lines) ->
save_line_buffer(Line, [Line|_Lines]=Lines) ->
save_line_buffer(Lines);
save_line_buffer(Line, Lines) ->
+ group_history:add(Line),
save_line_buffer([Line|Lines]).
save_line_buffer(Lines) ->
diff --git a/lib/kernel/src/group_history.erl b/lib/kernel/src/group_history.erl
new file mode 100644
index 0000000000..5ca5e2d1dd
--- /dev/null
+++ b/lib/kernel/src/group_history.erl
@@ -0,0 +1,341 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(group_history).
+-export([load/0, add/1]).
+
+%% Make a minimal size that should encompass set of lines and then make
+%% a file rotation for N files of this size.
+-define(DEFAULT_HISTORY_FILE, "erlang-shell-log").
+-define(MAX_HISTORY_FILES, 10).
+-define(DEFAULT_SIZE, 1024*512). % 512 kb total default
+-define(DEFAULT_STATUS, disabled).
+-define(MIN_HISTORY_SIZE, (50*1024)). % 50 kb, in bytes
+-define(DEFAULT_DROP, []).
+-define(DISK_LOG_FORMAT, internal). % since we want repairs
+-define(LOG_NAME, '$#group_history').
+-define(VSN, {0,1,0}).
+
+%%%%%%%%%%%%%%
+%%% PUBLIC %%%
+%%%%%%%%%%%%%%
+
+%% @doc Loads the shell history from memory. This function should only be
+%% called from group:server/3 to inject itself in the previous commands
+%% stack.
+-spec load() -> [string()].
+load() ->
+ wait_for_kernel_safe_sup(),
+ case history_status() of
+ enabled ->
+ case open_log() of
+ {ok, ?LOG_NAME} ->
+ read_full_log(?LOG_NAME);
+ {repaired, ?LOG_NAME, {recovered, Good}, {badbytes, Bad}} ->
+ report_repairs(?LOG_NAME, Good, Bad),
+ read_full_log(?LOG_NAME);
+ {error, {need_repair, _FileName}} ->
+ repair_log(?LOG_NAME);
+ {error, {arg_mismatch, repair, true, false}} ->
+ repair_log(?LOG_NAME);
+ {error, {name_already_open, _}} ->
+ show_rename_warning(),
+ read_full_log(?LOG_NAME);
+ {error, {size_mismatch, Current, New}} ->
+ show_size_warning(Current, New),
+ resize_log(?LOG_NAME, Current, New),
+ load();
+ {error, {invalid_header, {vsn, Version}}} ->
+ upgrade_version(?LOG_NAME, Version),
+ load();
+ {error, Reason} ->
+ handle_open_error(Reason),
+ disable_history(),
+ []
+ end;
+ _ ->
+ []
+ end.
+
+%% @doc adds a log line to the erlang history log, if configured to do so.
+-spec add(iodata()) -> ok.
+add(Line) -> add(Line, history_status()).
+
+add(Line, enabled) ->
+ case lists:member(Line, to_drop()) of
+ false ->
+ case disk_log:log(?LOG_NAME, Line) of
+ ok ->
+ ok;
+ {error, no_such_log} ->
+ _ = open_log(), % a wild attempt we hope works!
+ disk_log:log(?LOG_NAME, Line);
+ {error, _Other} ->
+ % just ignore, we're too late
+ ok
+ end;
+ true ->
+ ok
+ end;
+add(_Line, disabled) ->
+ ok.
+
+%%%%%%%%%%%%%%%
+%%% PRIVATE %%%
+%%%%%%%%%%%%%%%
+
+%% Because loading the shell happens really damn early, processes we depend on
+%% might not be there yet. Luckily, the load function is called from the shell
+%% after a new process has been spawned, so we can block in here
+wait_for_kernel_safe_sup() ->
+ case whereis(kernel_safe_sup) of
+ undefined ->
+ timer:sleep(50),
+ wait_for_kernel_safe_sup();
+ _ ->
+ ok
+ end.
+
+%% Repair the log out of band
+repair_log(Name) ->
+ Opts = lists:keydelete(size, 1, log_options()),
+ case disk_log:open(Opts) of
+ {repaired, ?LOG_NAME, {recovered, Good}, {badbytes, Bad}} ->
+ report_repairs(?LOG_NAME, Good, Bad);
+ _ ->
+ ok
+ end,
+ _ = disk_log:close(Name),
+ load().
+
+%% Return whether the shell history is enabled or not
+-spec history_status() -> enabled | disabled.
+history_status() ->
+ case is_user() orelse application:get_env(kernel, shell_history) of
+ true -> disabled; % don't run for user proc
+ {ok, enabled} -> enabled;
+ undefined -> ?DEFAULT_STATUS;
+ _ -> disabled
+ end.
+
+%% Return whether the user process is running this
+-spec is_user() -> boolean().
+is_user() ->
+ case process_info(self(), registered_name) of
+ {registered_name, user} -> true;
+ _ -> false
+ end.
+
+%% Open a disk_log file while ensuring the required path is there.
+open_log() ->
+ Opts = log_options(),
+ _ = ensure_path(Opts),
+ disk_log:open(Opts).
+
+%% Return logger options
+log_options() ->
+ Path = find_path(),
+ File = filename:join([Path, ?DEFAULT_HISTORY_FILE]),
+ Size = find_wrap_values(),
+ [{name, ?LOG_NAME},
+ {file, File},
+ {repair, true},
+ {format, internal},
+ {type, wrap},
+ {size, Size},
+ {distributed, []},
+ {notify, false},
+ {head, {vsn, ?VSN}},
+ {quiet, true},
+ {mode, read_write}].
+
+-spec ensure_path([{file, string()} | {atom(), _}, ...]) -> ok | {error, term()}.
+ensure_path(Opts) ->
+ {file, Path} = lists:keyfind(file, 1, Opts),
+ filelib:ensure_dir(Path).
+
+%% @private read the logs from an already open file. Treat closed files
+%% as wrong and returns an empty list to avoid crash loops in the shell.
+-spec read_full_log(term()) -> [string()].
+read_full_log(Name) ->
+ case disk_log:chunk(Name, start) of
+ {error, no_such_log} ->
+ show_unexpected_close_warning(),
+ [];
+ eof ->
+ [];
+ {Cont, Logs} ->
+ lists:reverse(maybe_drop_header(Logs) ++ read_full_log(Name, Cont))
+ end.
+
+read_full_log(Name, Cont) ->
+ case disk_log:chunk(Name, Cont) of
+ {error, no_such_log} ->
+ show_unexpected_close_warning(),
+ [];
+ eof ->
+ [];
+ {NextCont, Logs} ->
+ maybe_drop_header(Logs) ++ read_full_log(Name, NextCont)
+ end.
+
+maybe_drop_header([{vsn, _} | Rest]) -> Rest;
+maybe_drop_header(Logs) -> Logs.
+
+-spec handle_open_error(_) -> ok.
+handle_open_error({arg_mismatch, OptName, CurrentVal, NewVal}) ->
+ show('$#erlang-history-arg-mismatch',
+ "Log file argument ~p changed value from ~p to ~p "
+ "and cannot be automatically updated. Please clear the "
+ "history files and try again.~n",
+ [OptName, CurrentVal, NewVal]);
+handle_open_error({not_a_log_file, FileName}) ->
+ show_invalid_file_warning(FileName);
+handle_open_error({invalid_index_file, FileName}) ->
+ show_invalid_file_warning(FileName);
+handle_open_error({invalid_header, Term}) ->
+ show('$#erlang-history-invalid-header',
+ "Shell history expects to be able to use the log files "
+ "which currently have unknown headers (~p) and may belong to "
+ "another mechanism. History logging will be "
+ "disabled.~n",
+ [Term]);
+handle_open_error({file_error, FileName, Reason}) ->
+ show('$#erlang-history-file-error',
+ "Error handling File ~s. Reason: ~p~n"
+ "History logging will be disabled.~n",
+ [FileName, Reason]);
+handle_open_error(Err) ->
+ show_unexpected_warning({disk_log, open, 1}, Err).
+
+find_wrap_values() ->
+ ConfSize = case application:get_env(kernel, shell_history_file_bytes) of
+ undefined -> ?DEFAULT_SIZE;
+ {ok, S} -> S
+ end,
+ SizePerFile = max(?MIN_HISTORY_SIZE, ConfSize div ?MAX_HISTORY_FILES),
+ FileCount = if SizePerFile > ?MIN_HISTORY_SIZE ->
+ ?MAX_HISTORY_FILES
+ ; SizePerFile =< ?MIN_HISTORY_SIZE ->
+ max(1, ConfSize div SizePerFile)
+ end,
+ {SizePerFile, FileCount}.
+
+report_repairs(_, _, 0) ->
+ %% just a regular close repair
+ ok;
+report_repairs(_, Good, Bad) ->
+ show('$#erlang-history-report-repairs',
+ "The shell history log file was corrupted and was repaired. "
+ "~p bytes were recovered and ~p were lost.~n", [Good, Bad]).
+
+resize_log(Name, _OldSize, NewSize) ->
+ show('$#erlang-history-resize-attempt',
+ "Attempting to resize the log history file to ~p...", [NewSize]),
+ Opts = lists:keydelete(size, 1, log_options()),
+ _ = case disk_log:open(Opts) of
+ {error, {need_repair, _}} ->
+ _ = repair_log(Name),
+ disk_log:open(Opts);
+ _ ->
+ ok
+ end,
+ case disk_log:change_size(Name, NewSize) of
+ ok ->
+ show('$#erlang-history-resize-result',
+ "ok~n", []);
+ {error, {new_size_too_small, _}} ->
+ show('$#erlang-history-resize-result',
+ "failed (new size is too small)~n", []),
+ disable_history();
+ {error, Reason} ->
+ show('$#erlang-history-resize-result',
+ "failed (~p)~n", [Reason]),
+ disable_history()
+ end.
+
+upgrade_version(_Name, Unsupported) ->
+ %% We only know of one version and can't support a newer one
+ show('$#erlang-history-upgrade',
+ "The version for the shell logs found on disk (~p) is "
+ "not supported by the current version (~p)~n",
+ [Unsupported, ?VSN]),
+ disable_history().
+
+disable_history() ->
+ show('$#erlang-history-disable', "Disabling shell history logging.~n", []),
+ application:set_env(kernel, shell_history, force_disabled).
+
+find_path() ->
+ case application:get_env(kernel, shell_history_path) of
+ undefined -> filename:basedir(user_cache, "erlang-history");
+ {ok, Path} -> Path
+ end.
+
+to_drop() ->
+ case application:get_env(kernel, shell_history_drop) of
+ undefined ->
+ application:set_env(kernel, shell_history_drop, ?DEFAULT_DROP),
+ ?DEFAULT_DROP;
+ {ok, V} when is_list(V) -> [Ln++"\n" || Ln <- V];
+ {ok, _} -> ?DEFAULT_DROP
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Output functions %%%
+%%%%%%%%%%%%%%%%%%%%%%%%
+show_rename_warning() ->
+ show('$#erlang-history-rename-warn',
+ "A history file with a different path has already "
+ "been started for the shell of this node. The old "
+ "name will keep being used for this session.~n",
+ []).
+
+show_invalid_file_warning(FileName) ->
+ show('$#erlang-history-invalid-file',
+ "Shell history expects to be able to use the file ~s "
+ "which currently exists and is not a file usable for "
+ "history logging purposes. History logging will be "
+ "disabled.~n", [FileName]).
+
+show_unexpected_warning({M,F,A}, Term) ->
+ show('$#erlang-history-unexpected-return',
+ "unexpected return value from ~p:~p/~p: ~p~n"
+ "shell history will be disabled for this session.~n",
+ [M,F,A,Term]).
+
+show_unexpected_close_warning() ->
+ show('$#erlang-history-unexpected-close',
+ "The shell log file has mysteriousy closed. Ignoring "
+ "currently unread history.~n", []).
+
+show_size_warning(_Current, _New) ->
+ show('$#erlang-history-size',
+ "The configured log history file size is different from "
+ "the size of the log file on disk.~n", []).
+
+show(Key, Format, Args) ->
+ case get(Key) of
+ undefined ->
+ io:format(standard_error, Format, Args),
+ put(Key, true),
+ ok;
+ true ->
+ ok
+ end.
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index f5c13ecdd7..6aef5476f1 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -702,7 +702,7 @@ connect_options() ->
header, active, packet, packet_size, buffer, mode, deliver, line_delimiter,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw,
- show_econnreset].
+ show_econnreset, bind_to_device].
connect_options(Opts, Mod) ->
BaseOpts =
@@ -770,7 +770,7 @@ listen_options() ->
header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send,
- packet_size, raw, show_econnreset].
+ packet_size, raw, show_econnreset, bind_to_device].
listen_options(Opts, Mod) ->
BaseOpts =
@@ -850,7 +850,7 @@ udp_options() ->
deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
add_membership, drop_membership, read_packets,raw,
- high_msgq_watermark, low_msgq_watermark].
+ high_msgq_watermark, low_msgq_watermark, bind_to_device].
udp_options(Opts, Mod) ->
@@ -919,6 +919,7 @@ sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf,
recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
+ bind_to_device,
% Other options are SCTP-specific (though they may be similar to their
% TCP and UDP counter-parts):
@@ -1055,7 +1056,6 @@ binary2filename(Bin) ->
Bin
end.
-
translate_ip(any, inet) -> {0,0,0,0};
translate_ip(loopback, inet) -> {127,0,0,1};
translate_ip(any, inet6) -> {0,0,0,0,0,0,0,0};
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 4e8f59a3b9..bc5b67f7bf 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -154,6 +154,7 @@
-define(INET_LOPT_TCP_SHOW_ECONNRESET, 39).
-define(INET_LOPT_LINE_DELIM, 40).
-define(INET_OPT_TCLASS, 41).
+-define(INET_OPT_BIND_TO_DEVICE, 42).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index 9b47199e08..0f5dc40553 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index c69791b9aa..1e624b9e90 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 25e4ddd95c..1128ee3ec5 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -44,6 +44,7 @@
global_group,
global_search,
group,
+ group_history,
heart,
hipe_unified_loader,
inet6_tcp,
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 2dc90e2b3e..77085b2064 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index b901da95b8..cba57088ec 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ init([]) ->
restart => permanent,
shutdown => 2000,
type => worker,
- modeules => [file, file_server, file_io_server, prim_file]},
+ modules => [file, file_server, file_io_server, prim_file]},
StdError = #{id => standard_error,
start => {standard_error, start_link, []},
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 0a9f9316b0..ddda396713 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1262,11 +1262,22 @@ create_name(Name, LongOrShortNames, Try) ->
{Head,Host1} = create_hostpart(Name, LongOrShortNames),
case Host1 of
{ok,HostPart} ->
- {ok,list_to_atom(Head ++ HostPart)};
+ case valid_name_head(Head) of
+ true ->
+ {ok,list_to_atom(Head ++ HostPart)};
+ false ->
+ error_logger:info_msg("Invalid node name!\n"
+ "Please check your configuration\n"),
+ {error, badarg}
+ end;
{error,long} when Try =:= 1 ->
%% It could be we haven't read domain name from resolv file yet
inet_config:do_load_resolv(os:type(), longnames),
create_name(Name, LongOrShortNames, 0);
+ {error, hostname_not_allowed} ->
+ error_logger:info_msg("Invalid node name!\n"
+ "Please check your configuration\n"),
+ {error, badarg};
{error,Type} ->
error_logger:info_msg(
lists:concat(["Can\'t set ",
@@ -1279,12 +1290,13 @@ create_name(Name, LongOrShortNames, Try) ->
create_hostpart(Name, LongOrShortNames) ->
{Head,Host} = split_node(Name),
Host1 = case {Host,LongOrShortNames} of
- {[$@,_|_],longnames} ->
- {ok,Host};
+ {[$@,_|_] = Host,longnames} ->
+ validate_hostname(Host);
{[$@,_|_],shortnames} ->
case lists:member($.,Host) of
true -> {error,short};
- _ -> {ok,Host}
+ _ ->
+ validate_hostname(Host)
end;
{_,shortnames} ->
case inet_db:gethostname() of
@@ -1304,6 +1316,24 @@ create_hostpart(Name, LongOrShortNames) ->
end,
{Head,Host1}.
+validate_hostname([$@|HostPart] = Host) ->
+ {ok, MP} = re:compile("^[!-ÿ]*$", [unicode]),
+ case re:run(HostPart, MP) of
+ {match, _} ->
+ {ok, Host};
+ nomatch ->
+ {error, hostname_not_allowed}
+ end.
+
+valid_name_head(Head) ->
+ {ok, MP} = re:compile("^[0-9A-Za-z_\\-]*$", [unicode]),
+ case re:run(Head, MP) of
+ {match, _} ->
+ true;
+ nomatch ->
+ false
+ end.
+
split_node(Name) ->
lists:splitwith(fun(C) -> C =/= $@ end, atom_to_list(Name)).
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 7e83b17add..0250783632 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index bd6ea26678..0e0b7dffa3 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index b4cf31b210..866043cfb4 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 088d851b09..6f8e949aac 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -107,14 +107,19 @@ init_per_testcase(big_boot_embedded, Config) ->
_Else ->
{skip, "Needs crypto!"}
end;
-init_per_testcase(on_load_embedded, Config) ->
+init_per_testcase(on_load_embedded, Config0) ->
LibRoot = code:lib_dir(),
LinkName = filename:join(LibRoot, "on_load_app-1.0"),
- [{link_name,LinkName}|Config];
+ Config = [{link_name,LinkName}|Config0],
+ init_per_testcase(Config);
init_per_testcase(_Func, Config) ->
+ init_per_testcase(Config).
+
+init_per_testcase(Config) ->
P = code:get_path(),
[{code_path, P}|Config].
+
end_per_testcase(module_status, Config) ->
code:purge(?TESTMOD),
code:delete(?TESTMOD),
@@ -1786,6 +1791,19 @@ do_normalized_paths([]) ->
%% Test that module_status/1 behaves as expected
module_status(_Config) ->
+ case test_server:is_cover() of
+ true ->
+ module_status();
+ false ->
+ %% Make sure that we terminate the cover server.
+ try
+ module_status()
+ after
+ cover:stop()
+ end
+ end.
+
+module_status() ->
%% basics
not_loaded = code:module_status(fubar), % nonexisting
{file, preloaded} = code:is_loaded(erlang),
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 079cc2f90f..2b11a0381f 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -2493,6 +2493,7 @@ error_repair(Conf) when is_list(Conf) ->
del(File, No),
ok = file:del_dir(Dir),
+ error_logger:add_report_handler(?MODULE, self()),
%% repair a file
P1 = pps(),
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
@@ -2509,6 +2510,8 @@ error_repair(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
true = (P1 == pps()),
del(File, No),
+ receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
+ after 1000 -> ct:fail(failed) end,
%% yet another repair
P2 = pps(),
@@ -2525,6 +2528,8 @@ error_repair(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
true = (P2 == pps()),
del(File, No),
+ receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
+ after 1000 -> ct:fail(failed) end,
%% Repair, large term
Big = term_to_binary(lists:duplicate(66000,$a)),
@@ -2540,6 +2545,8 @@ error_repair(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
Got = Big,
del(File, No),
+ receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
+ after 1000 -> ct:fail(failed) end,
%% A term a little smaller than a chunk, then big terms.
BigSmall = mk_bytes(1024*64-8-12),
@@ -2560,6 +2567,8 @@ error_repair(Conf) when is_list(Conf) ->
{type, halt}, {format, internal}]),
ok = disk_log:close(n),
file:delete(File),
+ receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
+ after 1000 -> ct:fail(failed) end,
%% The header is recovered.
{ok,n} =
@@ -2573,12 +2582,13 @@ error_repair(Conf) when is_list(Conf) ->
crash(File, 30),
{repaired,n,{recovered,3},{badbytes,15}} =
disk_log:open([{name, n}, {file, File}, {type, halt},
- {format, internal},{repair,true},
+ {format, internal},{repair,true}, {quiet, true},
{head_func, {?MODULE, head_fun, [{ok,"head"}]}}]),
["head",'of',terms] = get_all_terms(n),
ok = disk_log:close(n),
-
+ error_logger:delete_report_handler(?MODULE),
file:delete(File),
+ {messages, []} = process_info(self(), messages),
ok.
@@ -5007,6 +5017,9 @@ init(Tester) ->
handle_event({error_report, _GL, {Pid, crash_report, Report}}, Tester) ->
Tester ! {crash_report, Pid, Report},
{ok, Tester};
+handle_event({info_msg, _GL, {Pid, F,A}}, Tester) ->
+ Tester ! {info_msg, Pid, F, A},
+ {ok, Tester};
handle_event(_Event, State) ->
{ok, State}.
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 09c80a0956..bbfaa9d147 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,9 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([tick/1, tick_change/1, illegal_nodenames/1, hidden_node/1,
+-export([tick/1, tick_change/1,
+ nodenames/1, hostnames/1,
+ illegal_nodenames/1, hidden_node/1,
setopts/1,
table_waste/1, net_setuptime/1,
inet_dist_options_options/1,
@@ -53,7 +55,6 @@
-export([pinger/1]).
-
-define(DUMMY_NODE,dummy@test01).
%%-----------------------------------------------------------------
@@ -68,8 +69,8 @@ suite() ->
{timetrap,{minutes,4}}].
all() ->
- [tick, tick_change, illegal_nodenames, hidden_node,
- setopts,
+ [tick, tick_change, nodenames, hostnames, illegal_nodenames,
+ hidden_node, setopts,
table_waste, net_setuptime, inet_dist_options_options,
{group, monitor_nodes}].
@@ -179,7 +180,105 @@ table_waste(Config) when is_list(Config) ->
stop_node(N),
ok.
+%% Test that starting nodes with different legal name part works, and that illegal
+%% ones are filtered
+nodenames(Config) when is_list(Config) ->
+ legal("a1@b"),
+ legal("a-1@b"),
+ legal("a_1@b"),
+
+ illegal("cdé@a"),
+ illegal("te欢st@a").
+
+%% Test that starting nodes with different legal host part works, and that illegal
+%% ones are filtered
+hostnames(Config) when is_list(Config) ->
+ Host = gethostname(),
+ legal([$a,$@|atom_to_list(Host)]),
+ legal("1@b1"),
+ legal("b@b1-c"),
+ legal("c@b1_c"),
+ legal("d@b1#c"),
+ legal("f@::1"),
+ legal("g@1:bc3:4e3f:f20:0:1"),
+
+ case file:native_name_encoding() of
+ latin1 -> ignore;
+ _ -> legal("e@b1é")
+ end,
+ long_hostnames(net_kernel:longnames()),
+
+ illegal("h@testالع"),
+ illegal("i@языtest"),
+ illegal("j@te欢st").
+
+long_hostnames(true) ->
+ legal("[email protected]"),
+ legal("[email protected]"),
+ legal("[email protected]_c.d"),
+ legal("[email protected]"),
+ legal("[email protected]");
+long_hostnames(false) ->
+ illegal("[email protected]").
+
+legal(Name) ->
+ case test_node(Name) of
+ started ->
+ ok;
+ not_started ->
+ ct:fail("no ~p node started", [Name])
+ end.
+
+illegal(Name) ->
+ case test_node(Name, true) of
+ not_started ->
+ ok;
+ started ->
+ ct:fail("~p node started with illegal name", [Name])
+ end.
+test_node(Name) ->
+ test_node(Name, false).
+test_node(Name, Illigal) ->
+ ProgName = atom_to_list(lib:progname()),
+ Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++
+ " -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++
+ case Illigal of
+ true ->
+ " -eval \"timer:sleep(10000),init:stop().\"";
+ false ->
+ ""
+ end,
+ net_kernel:monitor_nodes(true),
+ BinCommand = unicode:characters_to_binary(Command, utf8),
+ Prt = open_port({spawn, BinCommand}, [stream]),
+ Node = list_to_atom(Name),
+ receive
+ {nodeup, Node} ->
+ net_kernel:monitor_nodes(false),
+ slave:stop(Node),
+ started
+ after 5000 ->
+ net_kernel:monitor_nodes(false),
+ not_started
+ end.
+
+long_or_short() ->
+ case net_kernel:longnames() of
+ true -> " -name ";
+ false -> " -sname "
+ end.
+
+% get the localhost's name, depending on the using name policy
+gethostname() ->
+ Hostname = case net_kernel:longnames() of
+ true->
+ net_adm:localhost();
+ _->
+ {ok, Name}=inet:gethostname(),
+ Name
+ end,
+ list_to_atom(Hostname).
%% Test that pinging an illegal nodename does not kill the node.
illegal_nodenames(Config) when is_list(Config) ->
diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl
index c1dc208cc1..03aaee56b7 100644
--- a/lib/kernel/test/erl_distribution_wb_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl
index bb01c2384d..2d26a7246c 100644
--- a/lib/kernel/test/error_logger_SUITE.erl
+++ b/lib/kernel/test/error_logger_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index b402f01758..119e1f24bb 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 10b6b105d0..899102c908 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -383,7 +383,7 @@ check_icky(Mod) ->
ok
end,
- _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir">>)),
+ _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir"/utf8>>)),
if
UniMode and (OS =/= win32) ->
{error,enoent} = Mod:set_cwd("åäö_dir");
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 92a74465b7..3f11e25b93 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -302,9 +302,9 @@ t_implicit_inet6(Config) when is_list(Config) ->
end.
t_implicit_inet6(Host, Addr) ->
- case gen_tcp:listen(0, [inet6]) of
+ Loopback = {0,0,0,0,0,0,0,1},
+ case gen_tcp:listen(0, [inet6, {ip,Loopback}]) of
{ok,S1} ->
- Loopback = {0,0,0,0,0,0,0,1},
io:format("~s ~p~n", ["::1",Loopback]),
implicit_inet6(S1, Loopback),
ok = gen_tcp:close(S1),
@@ -524,10 +524,10 @@ local_handshake(S, SAddr, C, CAddr) ->
t_accept_inet6_tclass(Config) when is_list(Config) ->
TClassOpt = {tclass,8#56 bsl 2}, % Expedited forwarding
- case gen_tcp:listen(0, [inet6,TClassOpt]) of
+ Loopback = {0,0,0,0,0,0,0,1},
+ case gen_tcp:listen(0, [inet6, {ip, Loopback}, TClassOpt]) of
{ok,L} ->
LPort = ok(inet:port(L)),
- Loopback = {0,0,0,0,0,0,0,1},
Sa = ok(gen_tcp:connect(Loopback, LPort, [])),
Sb = ok(gen_tcp:accept(L)),
[TClassOpt] = ok(inet:getopts(Sb, [tclass])),
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index 1029d7ef0a..836e0c5a05 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -717,9 +717,9 @@ implicit_inet6(Config) when is_list(Config) ->
implicit_inet6(Host, Addr) ->
Active = {active,false},
- case gen_udp:open(0, [inet6,Active]) of
+ Loopback = {0,0,0,0,0,0,0,1},
+ case gen_udp:open(0, [inet6,Active,{ip, Loopback}]) of
{ok,S1} ->
- Loopback = {0,0,0,0,0,0,0,1},
io:format("~s ~p~n", ["::1",Loopback]),
implicit_inet6(S1, Active, Loopback),
ok = gen_udp:close(S1),
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index f60c13d2e3..97f789b61c 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,8 @@
lookup_bad_search_option/1,
getif/1,
getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1,
- parse_strict_address/1, simple_netns/1, simple_netns_open/1]).
+ parse_strict_address/1, simple_netns/1, simple_netns_open/1,
+ simple_bind_to_device/1, simple_bind_to_device_open/1]).
-export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1,
kill_gethost/0, parallell_gethost/0, test_netns/0]).
@@ -58,7 +59,8 @@ all() ->
gethostnative_debug_level, gethostnative_soft_restart,
lookup_bad_search_option,
getif, getif_ifr_name_overflow, getservbyname_overflow,
- getifaddrs, parse_strict_address, simple_netns, simple_netns_open].
+ getifaddrs, parse_strict_address, simple_netns, simple_netns_open,
+ simple_bind_to_device, simple_bind_to_device_open].
groups() ->
[{parse, [], [parse_hosts, parse_address]}].
@@ -1247,3 +1249,67 @@ cmd(CmdString) ->
io:put_chars(["# ",CmdString,io_lib:nl()]),
io:put_chars([os:cmd(CmdString++" ; echo ' =>' $?")]),
ok.
+
+-define(CAP_NET_RAW, 13). %% from /usr/include/linux/capability.h
+
+can_bind_to_device({unix, linux}, {Major, _, _})
+ when Major > 2 ->
+ Status = os:cmd("cat /proc/self/status | grep CapEff"),
+ [_, CapEffStr] = string:tokens(Status, [$\n, $\t]),
+ CapEff = list_to_integer(CapEffStr, 16),
+ if CapEff band (1 bsl ?CAP_NET_RAW) =/= 0 ->
+ ok;
+ true ->
+ {skip,"insufficient capabilities, CAP_NET_RAW not granted"}
+ end;
+can_bind_to_device(_OS, _Version) ->
+ {skip,"socket option bind_to_device not supported on this OS or version"}.
+
+simple_bind_to_device(Config) when is_list(Config) ->
+ case can_bind_to_device(os:type(), os:version()) of
+ ok ->
+ {ok,U} = gen_udp:open(0),
+ jog_bind_to_device_opt(U),
+ ok = gen_udp:close(U),
+ %%
+ {ok,L} = gen_tcp:listen(0, []),
+ jog_bind_to_device_opt(L),
+ ok = gen_tcp:close(L),
+ %%
+ case gen_sctp:open() of
+ {ok,S} ->
+ jog_bind_to_device_opt(S),
+ ok = gen_sctp:close(S);
+ {error,eprotonosupport} ->
+ ok
+ end;
+ Other ->
+ Other
+ end.
+
+%% Smoke test bind_to_device support.
+simple_bind_to_device_open(Config) when is_list(Config) ->
+ case can_bind_to_device(os:type(), os:version()) of
+ ok ->
+ {ok,U} = gen_udp:open(0, [binary,{bind_to_device,<<"lo">>},inet]),
+ ok = gen_udp:close(U),
+ {ok,T} = gen_tcp:listen(0, [binary,{bind_to_device,<<"lo">>},inet]),
+ ok = gen_tcp:close(T),
+
+ case gen_sctp:open(0, [binary,{bind_to_device,<<"lo">>},inet]) of
+ {ok,S} ->
+ ok = gen_sctp:close(S);
+ {error,eprotonosupport} ->
+ ok
+ end;
+ Other ->
+ Other
+ end.
+
+jog_bind_to_device_opt(S) ->
+ %% This is just jogging the option mechanics
+ ok = inet:setopts(S, [{bind_to_device,<<>>}]),
+ {ok,[{bind_to_device,<<>>}]} = inet:getopts(S, [bind_to_device]),
+ ok = inet:setopts(S, [{bind_to_device,<<"lo">>}]),
+ {ok,[{bind_to_device,<<"lo">>}]} = inet:getopts(S, [bind_to_device]),
+ ok.
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index 322b9f30fe..9413cbd976 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -620,7 +620,7 @@ ipv6_v6only_close(Module, Socket) ->
%% Test using socket option ipv6_v6only for UDP.
use_ipv6_v6only_udp(Config) when is_list(Config) ->
- case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of
+ case gen_udp:open(0, [inet6,{ip,{0,0,0,0,0,0,0,1}}, {ipv6_v6only,true}]) of
{ok,S6} ->
case inet:getopts(S6, [ipv6_v6only]) of
{ok,[{ipv6_v6only,true}]} ->
diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl
index 920839f4f9..f3258ea520 100644
--- a/lib/kernel/test/multi_load_SUITE.erl
+++ b/lib/kernel/test/multi_load_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl
index 9460608a3e..acecd34ead 100644
--- a/lib/kernel/test/pg2_SUITE.erl
+++ b/lib/kernel/test/pg2_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 0c84a7d1cc..2f4330c217 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl
index d76c4097d8..a89a7600a2 100644
--- a/lib/kernel/test/rpc_SUITE.erl
+++ b/lib/kernel/test/rpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.