From 00a2425bde77ddb9ae4c03b8c4e5470064773981 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 24 Jul 2018 16:40:55 +0200 Subject: [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. --- erts/doc/src/socket_usage.xml | 9 ++++- erts/emulator/nifs/common/socket_nif.c | 59 +++++++++++++++++++++++++++++++++ erts/preloaded/ebin/socket.beam | Bin 58020 -> 58076 bytes erts/preloaded/src/socket.erl | 33 +++++++++--------- lib/kernel/test/socket_server.erl | 4 ++- 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 @@ multicast_ttl - 0..255 + uint8() yes yes none @@ -351,6 +351,13 @@ yes type = raw + + recverr + boolean() + yes + yes + none + recvif boolean() 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 Binary files a/erts/preloaded/ebin/socket.beam and b/erts/preloaded/ebin/socket.beam 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]), -- cgit v1.2.3