aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-07-24 16:40:55 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commit00a2425bde77ddb9ae4c03b8c4e5470064773981 (patch)
treefe118b4be3b1ea5c2f61e9e1ad3cb7cc46fea276
parentb9237c96b2b86c82bb128625cc532b3528222560 (diff)
downloadotp-00a2425bde77ddb9ae4c03b8c4e5470064773981.tar.gz
otp-00a2425bde77ddb9ae4c03b8c4e5470064773981.tar.bz2
otp-00a2425bde77ddb9ae4c03b8c4e5470064773981.zip
[socket-nif] Add support for socket (level ip) option recverr
Added support for the IP socket option RECVERR. To actually make use of this option, we need the recvmsg function, which we don't have yet. Baby steps. OTP-14831.
-rw-r--r--erts/doc/src/socket_usage.xml9
-rw-r--r--erts/emulator/nifs/common/socket_nif.c59
-rw-r--r--erts/preloaded/ebin/socket.beambin58020 -> 58076 bytes
-rw-r--r--erts/preloaded/src/socket.erl33
-rw-r--r--lib/kernel/test/socket_server.erl4
5 files changed, 88 insertions, 17 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml
index 8480af315e..b791567c22 100644
--- a/erts/doc/src/socket_usage.xml
+++ b/erts/doc/src/socket_usage.xml
@@ -339,7 +339,7 @@
</row>
<row>
<cell>multicast_ttl</cell>
- <cell>0..255</cell>
+ <cell>uint8()</cell>
<cell>yes</cell>
<cell>yes</cell>
<cell>none</cell>
@@ -352,6 +352,13 @@
<cell>type = raw</cell>
</row>
<row>
+ <cell>recverr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
<cell>recvif</cell>
<cell>boolean()</cell>
<cell>yes</cell>
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index f7053d77fa..86a81c882b 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -528,6 +528,7 @@ typedef union {
#define SOCKET_OPT_IP_MULTICAST_LOOP 15
#define SOCKET_OPT_IP_MULTICAST_TTL 16
#define SOCKET_OPT_IP_NODEFRAG 17
+#define SOCKET_OPT_IP_RECVERR 20
#define SOCKET_OPT_IP_RECVIF 21
#define SOCKET_OPT_IP_RECVOPTS 23
#define SOCKET_OPT_IP_RECVTOS 25
@@ -1142,6 +1143,11 @@ static ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM eVal);
#endif
+#if defined(IP_RECVERR)
+static ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal);
+#endif
#if defined(IP_RECVIF)
static ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -1535,6 +1541,10 @@ static ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
static ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
SocketDescriptor* descP);
#endif
+#if defined(IP_RECVERR)
+static ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
+ SocketDescriptor* descP);
+#endif
#if defined(IP_RECVIF)
static ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
SocketDescriptor* descP);
@@ -4950,6 +4960,12 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
break;
#endif
+#if defined(IP_RECVERR)
+ case SOCKET_OPT_IP_RECVERR:
+ result = nsetopt_lvl_ip_recverr(env, descP, eVal);
+ break;
+#endif
+
#if defined(IP_RECVIF)
case SOCKET_OPT_IP_RECVIF:
result = nsetopt_lvl_ip_recvif(env, descP, eVal);
@@ -5308,6 +5324,25 @@ ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
#endif
+/* nsetopt_lvl_ip_recverr - Level IP RECVERR option
+ */
+#if defined(IP_RECVERR)
+static
+ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal)
+{
+#if defined(SOL_IP)
+ int level = SOL_IP;
+#else
+ int level = IPPROTO_IP;
+#endif
+
+ return nsetopt_bool_opt(env, descP, level, IP_RECVERR, eVal);
+}
+#endif
+
+
/* nsetopt_lvl_ip_recvif - Level IP RECVIF option
*/
#if defined(IP_RECVIF)
@@ -7910,6 +7945,12 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
break;
#endif
+#if defined(IP_RECVERR)
+ case SOCKET_OPT_IP_RECVERR:
+ result = ngetopt_lvl_ip_recverr(env, descP);
+ break;
+#endif
+
#if defined(IP_RECVIF)
case SOCKET_OPT_IP_RECVIF:
result = ngetopt_lvl_ip_recvif(env, descP);
@@ -8200,6 +8241,24 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
#endif
+/* ngetopt_lvl_ip_recverr - Level IP RECVERR option
+ */
+#if defined(IP_RECVERR)
+static
+ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+#if defined(SOL_IP)
+ int level = SOL_IP;
+#else
+ int level = IPPROTO_IP;
+#endif
+
+ return ngetopt_bool_opt(env, descP, level, IP_RECVERR);
+}
+#endif
+
+
/* ngetopt_lvl_ip_recvopt - Level IP RECVOPTS option
*/
#if defined(IP_RECVOPTS)
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index 20f2cf659b..e2b988f8a6 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index 0c3a17b54d..0a101008c6 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -620,7 +620,7 @@
-define(SOCKET_OPT_IP_NODEFRAG, 17).
%% -define(SOCKET_OPT_IP_OPTIONS, 18).
%% -define(SOCKET_OPT_IP_PKTINFO, 19).
-%% -define(SOCKET_OPT_IP_RECVERR, 20).
+-define(SOCKET_OPT_IP_RECVERR, 20).
-define(SOCKET_OPT_IP_RECVIF, 21).
%% -define(SOCKET_OPT_IP_RECVDSTADDR, 22).
-define(SOCKET_OPT_IP_RECVOPTS, 23).
@@ -638,34 +638,34 @@
-define(SOCKET_OPT_IPV6_ADDRFORM, 1).
-define(SOCKET_OPT_IPV6_ADD_MEMBERSHIP, 2).
-define(SOCKET_OPT_IPV6_AUTHHDR, 3). % Obsolete?
-%% -define(SOCKET_OPT_IPV6_AUTH_LEVEL, 4).
-%% -define(SOCKET_OPT_IPV6_CHECKSUM, 5).
+%% -define(SOCKET_OPT_IPV6_AUTH_LEVEL, 4). % FreeBSD
+%% -define(SOCKET_OPT_IPV6_CHECKSUM, 5). % FreeBSD
-define(SOCKET_OPT_IPV6_DROP_MEMBERSHIP, 6).
-define(SOCKET_OPT_IPV6_DSTOPTS, 7).
-%% -define(SOCKET_OPT_IPV6_ESP_TRANS_LEVEL, 8).
-%% -define(SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL, 9).
-%% -define(SOCKET_OPT_IPV6_FAITH, 10).
+%% -define(SOCKET_OPT_IPV6_ESP_TRANS_LEVEL, 8). % FreeBSD
+%% -define(SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL, 9). % FreeBSD
+%% -define(SOCKET_OPT_IPV6_FAITH, 10). % FreeBSD
-define(SOCKET_OPT_IPV6_FLOWINFO, 11).
-define(SOCKET_OPT_IPV6_HOPLIMIT, 12).
-define(SOCKET_OPT_IPV6_HOPOPTS, 13).
-%% -define(SOCKET_OPT_IPV6_IPCOMP_LEVEL, 14).
-%% -define(SOCKET_OPT_IPV6_JOIN_GROUP, 15).
-%% -define(SOCKET_OPT_IPV6_LEAVE_GROUP, 16).
+%% -define(SOCKET_OPT_IPV6_IPCOMP_LEVEL, 14). % FreeBSD
+%% -define(SOCKET_OPT_IPV6_JOIN_GROUP, 15). % FreeBSD
+%% -define(SOCKET_OPT_IPV6_LEAVE_GROUP, 16). % FreeBSD
-define(SOCKET_OPT_IPV6_MTU, 17).
-define(SOCKET_OPT_IPV6_MTU_DISCOVER, 18).
-define(SOCKET_OPT_IPV6_MULTICAST_HOPS, 19).
-define(SOCKET_OPT_IPV6_MULTICAST_IF, 20).
-define(SOCKET_OPT_IPV6_MULTICAST_LOOP, 21).
-%% -define(SOCKET_OPT_IPV6_PORTRANGE, 22).
-%% -define(SOCKET_OPT_IPV6_PKTOPTIONS, 23).
+%% -define(SOCKET_OPT_IPV6_PORTRANGE, 22). % FreeBSD
+%% -define(SOCKET_OPT_IPV6_PKTOPTIONS, 23). % FreeBSD
%% -define(SOCKET_OPT_IPV6_RECVERR, 24).
-define(SOCKET_OPT_IPV6_RECVPKTINFO, 25). % On FreeBSD: PKTINFO
%% -define(SOCKET_OPT_IPV6_RECVTCLASS, 26).
-define(SOCKET_OPT_IPV6_ROUTER_ALERT, 27).
-define(SOCKET_OPT_IPV6_RTHDR, 28).
-%% -define(SOCKET_OPT_IPV6_TCLASS, 29).
+%% -define(SOCKET_OPT_IPV6_TCLASS, 29). % FreeBSD
-define(SOCKET_OPT_IPV6_UNICAST_HOPS, 30).
-%% -define(SOCKET_OPT_IPV6_USE_MIN_MTU, 31).
+%% -define(SOCKET_OPT_IPV6_USE_MIN_MTU, 31). % FreeBSD
-define(SOCKET_OPT_IPV6_V6ONLY, 32).
-define(SOCKET_OPT_TCP_CONGESTION, 1).
@@ -2219,6 +2219,9 @@ enc_setopt_value(ip, multicast_ttl, V, _D, _T, _P)
enc_setopt_value(ip, nodefrag, V, _D, _T, _P)
when is_boolean(V) ->
V;
+enc_setopt_value(ip, recverr, V, _D, _T, _P)
+ when is_boolean(V) ->
+ V;
enc_setopt_value(ip, recvif, V, _D, _T, _P)
when is_boolean(V) ->
V;
@@ -2672,8 +2675,8 @@ enc_sockopt_key(ip = L, pktinfo = Opt, _Dir, _D, _T, _P) ->
not_supported({L, Opt});
%% This require special code for accessing the errors.
%% via calling the recvmsg with the MSG_ERRQUEUE flag set,
-enc_sockopt_key(ip = L, recverr = Opt, _Dir, _D, _T, _P) ->
- not_supported({L, Opt});
+enc_sockopt_key(ip = _L, recverr = _Opt, _Dir, _D, _T, _P) ->
+ ?SOCKET_OPT_IP_RECVERR;
enc_sockopt_key(ip = _L, recvif = _Opt, _Dir, _D, T, _P)
when (T =:= dgram) orelse (T =:= raw) ->
?SOCKET_OPT_IP_RECVIF;
diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl
index 54e9244d19..43f6f5ac75 100644
--- a/lib/kernel/test/socket_server.erl
+++ b/lib/kernel/test/socket_server.erl
@@ -636,6 +636,7 @@ handler_init(Manager, ID, Peek, Sock) ->
MLoop4 = GIP4(multicast_loop),
MTTL = GIP4(multicast_ttl),
NF = GIP4(nodefrag), % raw only
+ RecvErr4 = GIP4(recverr),
RecvIF = GIP4(recvif), % Only dgram and raw (and FreeBSD)
RecvOPTS = GIP4(recvopts), % Not stream
RecvTOS = GIP4(recvtos),
@@ -675,6 +676,7 @@ handler_init(Manager, ID, Peek, Sock) ->
"~n (ip) Multicast Loop: ~s"
"~n (ip) Multicast TTL: ~s"
"~n (ip) Node Frag: ~s"
+ "~n (ip) Recv Err: ~s"
"~n (ip) Recv IF: ~s"
"~n (ip) Recv OPTS: ~s"
"~n (ip) Recv TOS: ~s"
@@ -695,7 +697,7 @@ handler_init(Manager, ID, Peek, Sock) ->
RcvBuf, RcvLW, RcvTO, SndBuf, SndLW, SndTO,
Linger, Timestamp,
FreeBind, MTU, MTUDisc, MALL, MIF4, MLoop4, MTTL,
- NF, RecvIF, RecvOPTS, RecvTOS, RecvTTL,
+ NF, RecvErr4, RecvIF, RecvOPTS, RecvTOS, RecvTTL,
MHops, MIF6, MLoop6, RecvPktInfo,
RtHdr, AuthHdr, HopLimit, HopOpts, DstOpts, FlowInfo,
UHops]),