From 8936b71f13b37559600afb5536ff7d7878b9ab0e Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 10 Jul 2018 13:42:28 +0200 Subject: [socket-nif] Add support for socket (level ip) option multicast_loop Added support for the IP option MULTICAST_LOOP. OTP-14831 --- erts/emulator/nifs/common/socket_nif.c | 89 +++++++++++++++++++---- erts/preloaded/ebin/socket.beam | Bin 43748 -> 43784 bytes erts/preloaded/src/socket.erl | 127 ++++++++++++++++++++++++++++----- lib/kernel/test/socket_server.erl | 18 +++-- 4 files changed, 198 insertions(+), 36 deletions(-) diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 82468c6e8f..95f29f3dd8 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -342,9 +342,9 @@ typedef union { #define SOCKET_OPT_LEVEL_UDP 5 #define SOCKET_OPT_LEVEL_SCTP 6 -#define SOCKET_OPT_OTP_DEBUG 0 -#define SOCKET_OPT_OTP_IOW 1 -#define SOCKET_OPT_OTP_CTRL_PROC 2 +#define SOCKET_OPT_OTP_DEBUG 1 +#define SOCKET_OPT_OTP_IOW 2 +#define SOCKET_OPT_OTP_CTRL_PROC 3 #define SOCKET_OPT_SOCK_ACCEPTCONN 1 #define SOCKET_OPT_SOCK_BROADCAST 4 @@ -362,22 +362,23 @@ typedef union { #define SOCKET_OPT_SOCK_SNDBUF 27 #define SOCKET_OPT_SOCK_TYPE 32 -#define SOCKET_OPT_IP_RECVTOS 25 -#define SOCKET_OPT_IP_ROUTER_ALERT 28 -#define SOCKET_OPT_IP_TOS 30 -#define SOCKET_OPT_IP_TTL 32 +#define SOCKET_OPT_IP_MULTICAST_LOOP 15 +#define SOCKET_OPT_IP_RECVTOS 25 +#define SOCKET_OPT_IP_ROUTER_ALERT 28 +#define SOCKET_OPT_IP_TOS 30 +#define SOCKET_OPT_IP_TTL 32 #define SOCKET_OPT_IPV6_HOPLIMIT 12 -#define SOCKET_OPT_TCP_CONGESTION 0 -#define SOCKET_OPT_TCP_CORK 1 -#define SOCKET_OPT_TCP_MAXSEG 2 -#define SOCKET_OPT_TCP_NODELAY 3 +#define SOCKET_OPT_TCP_CONGESTION 1 +#define SOCKET_OPT_TCP_CORK 2 +#define SOCKET_OPT_TCP_MAXSEG 3 +#define SOCKET_OPT_TCP_NODELAY 4 -#define SOCKET_OPT_UDP_CORK 0 +#define SOCKET_OPT_UDP_CORK 1 -#define SOCKET_OPT_SCTP_AUTOCLOSE 7 -#define SOCKET_OPT_SCTP_NODELAY 22 +#define SOCKET_OPT_SCTP_AUTOCLOSE 8 +#define SOCKET_OPT_SCTP_NODELAY 23 /* =================================================================== * @@ -843,6 +844,11 @@ static ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, SocketDescriptor* descP, int eOpt, ERL_NIF_TERM eVal); +#if defined(IP_MULTICAST_LOOP) +static ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IP_RECVTOS) static ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env, SocketDescriptor* descP, @@ -1011,6 +1017,10 @@ static ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, SocketDescriptor* descP, int eOpt); +#if defined(IP_MULTICAST_LOOP) +static ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env, + SocketDescriptor* descP); +#endif #if defined(IP_RECVTOS) static ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env, SocketDescriptor* descP); @@ -3936,6 +3946,12 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, ERL_NIF_TERM result; switch (eOpt) { +#if defined(IP_MULTICAST_LOOP) + case SOCKET_OPT_IP_MULTICAST_LOOP: + result = nsetopt_lvl_ip_multicast_loop(env, descP, eVal); + break; +#endif + #if defined(IP_RECVTOS) case SOCKET_OPT_IP_RECVTOS: result = nsetopt_lvl_ip_recvtos(env, descP, eVal); @@ -3969,6 +3985,25 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, } +/* nsetopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option + */ +#if defined(IP_MULTICAST_LOOP) +static +ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(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_MULTICAST_LOOP, eVal); +} +#endif + + /* nsetopt_lvl_ip_recvtos - Level IP RECVTOS option */ #if defined(IP_RECVTOS) @@ -5022,7 +5057,7 @@ ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env, if (res != 0) { result = esock_make_error_errno(env, res); } else { - ERL_NIF_TERM lOnOff = MKI(env, val.l_onoff); + ERL_NIF_TERM lOnOff = ((val.l_onoff) ? atom_true : atom_false); ERL_NIF_TERM lSecs = MKI(env, val.l_linger); ERL_NIF_TERM linger = MKT2(env, lOnOff, lSecs); @@ -5196,6 +5231,12 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, ERL_NIF_TERM result; switch (eOpt) { +#if defined(IP_MULTICAST_LOOP) + case SOCKET_OPT_IP_MULTICAST_LOOP: + result = ngetopt_lvl_ip_multicast_loop(env, descP); + break; +#endif + #if defined(IP_RECVTOS) case SOCKET_OPT_IP_RECVTOS: result = ngetopt_lvl_ip_recvtos(env, descP); @@ -5229,6 +5270,24 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, } +/* ngetopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option + */ +#if defined(IP_RECVTOS) +static +ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(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_MULTICAST_LOOP); +} +#endif + + /* ngetopt_lvl_ip_recvtos - Level IP RECVTOS option */ #if defined(IP_RECVTOS) diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 4e8c848539..0f49c421fa 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 278a3f17ad..d2ed733b3c 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -460,9 +460,9 @@ -define(SOCKET_OPT_LEVEL_UDP, 5). -define(SOCKET_OPT_LEVEL_SCTP, 6). --define(SOCKET_OPT_OTP_DEBUG, 0). --define(SOCKET_OPT_OTP_IOW, 1). --define(SOCKET_OPT_OTP_CTRL_PROC, 2). +-define(SOCKET_OPT_OTP_DEBUG, 1). +-define(SOCKET_OPT_OTP_IOW, 2). +-define(SOCKET_OPT_OTP_CTRL_PROC, 3). -define(SOCKET_OPT_SOCK_ACCEPTCONN, 1). %% -define(SOCKET_OPT_SOCK_ACCEPTFILTER, 2). @@ -497,22 +497,112 @@ %% -define(SOCKET_OPT_SOCK_TIMESTAMP, 31). -define(SOCKET_OPT_SOCK_TYPE, 32). --define(SOCKET_OPT_IP_RECVTOS, 25). --define(SOCKET_OPT_IP_ROUTER_ALERT, 28). --define(SOCKET_OPT_IP_TOS, 30). --define(SOCKET_OPT_IP_TTL, 32). - --define(SOCKET_OPT_IPV6_HOPLIMIT, 12). - --define(SOCKET_OPT_TCP_CONGESTION, 0). +%% -define(SOCKET_OPT_IP_ADD_MEMBERSHIP, 1). +%% -define(SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP, 2). +%% -define(SOCKET_OPT_IP_BLOCK_SOURCE, 3). +%% -define(SOCKET_OPT_IP_DONT_FRAG, 4). +%% -define(SOCKET_OPT_IP_DROP_MEMBERSHIP, 5). +%% -define(SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP, 6). +%% -define(SOCKET_OPT_IP_FREEBIND, 7). +%% -define(SOCKET_OPT_IP_HDRINCL, 8). +%% -define(SOCKET_OPT_IP_MINTTL, 9). +%% -define(SOCKET_OPT_IP_MSFILTER, 10). +%% -define(SOCKET_OPT_IP_MTU, 11). +%% -define(SOCKET_OPT_IP_MTU_DISCOVER, 12). +%% -define(SOCKET_OPT_IP_MULTICAST_ALL, 13). +%% -define(SOCKET_OPT_IP_MULTICAST_IF, 14). +-define(SOCKET_OPT_IP_MULTICAST_LOOP, 15). +%% -define(SOCKET_OPT_IP_MULTICAST_TTL, 16). +%% -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_RECVIF, 21). +%% -define(SOCKET_OPT_IP_RECVDSTADDR, 22). +%% -define(SOCKET_OPT_IP_RECVOPTS, 23). +%% -define(SOCKET_OPT_IP_RECVORIGDSTADDR, 24). +-define(SOCKET_OPT_IP_RECVTOS, 25). +%% -define(SOCKET_OPT_IP_RECVTTL, 26). +%% -define(SOCKET_OPT_IP_RETOPTS, 27). +-define(SOCKET_OPT_IP_ROUTER_ALERT, 28). +%% -define(SOCKET_OPT_IP_SNDSRCADDR, 29). +-define(SOCKET_OPT_IP_TOS, 30). +%% -define(SOCKET_OPT_IP_TRANSPARENT, 31). +-define(SOCKET_OPT_IP_TTL, 32). +-define(SOCKET_OPT_IP_UNBLOCK_SOURCE, 33). + +%% -define(SOCKET_OPT_IPV6_ADDFORM, 1). +%% -define(SOCKET_OPT_IPV6_ADD_MEMBERSHIP, 2). +%% -define(SOCKET_OPT_IPV6_AUTHHDR, 3). +%% -define(SOCKET_OPT_IPV6_AUTH_LEVEL, 4). +%% -define(SOCKET_OPT_IPV6_CHECKSUM, 5). +%% -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_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_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_PKTINFO, 23). +%% -define(SOCKET_OPT_IPV6_PKTOPTIONS, 24). +%% -define(SOCKET_OPT_IPV6_RECVERR, 25). +%% -define(SOCKET_OPT_IPV6_RECVPKTINFO, 26). +%% -define(SOCKET_OPT_IPV6_RECVTCLASS, 27). +%% -define(SOCKET_OPT_IPV6_ROUTER_ALERT, 28). +%% -define(SOCKET_OPT_IPV6_RTHDR, 29). +%% -define(SOCKET_OPT_IPV6_TCLASS, 30). +%% -define(SOCKET_OPT_IPV6_UNICAST_HOPS, 31). +%% -define(SOCKET_OPT_IPV6_USE_MIN_MTU, 32). +%% -define(SOCKET_OPT_IPV6_V6ONLY, 33). + +-define(SOCKET_OPT_TCP_CONGESTION, 1). -define(SOCKET_OPT_TCP_CORK, 2). -define(SOCKET_OPT_TCP_MAXSEG, 3). -define(SOCKET_OPT_TCP_NODELAY, 4). --define(SOCKET_OPT_UDP_CORK, 0). - --define(SOCKET_OPT_SCTP_AUTOCLOSE, 7). --define(SOCKET_OPT_SCTP_NODELAY, 22). +-define(SOCKET_OPT_UDP_CORK, 1). + +%% -define(SOCKET_OPT_SCTP_ADAPTION_LAYER, 1). +%% -define(SOCKET_OPT_SCTP_ASSOCINFO, 2). +%% -define(SOCKET_OPT_SCTP_AUTH_ACTIVE_KEY, 3). +%% -define(SOCKET_OPT_SCTP_AUTH_ASCONF, 4). +%% -define(SOCKET_OPT_SCTP_AUTH_CHUNK, 5). +%% -define(SOCKET_OPT_SCTP_AUTH_KEY, 6). +%% -define(SOCKET_OPT_SCTP_AUTH_DELETE_KEY, 7). +-define(SOCKET_OPT_SCTP_AUTOCLOSE, 8). +%% -define(SOCKET_OPT_SCTP_CONTEXT, 9). +%% -define(SOCKET_OPT_SCTP_DEFAULT_SEND_PARAMS, 10). +%% -define(SOCKET_OPT_SCTP_DELAYED_ACK_TIME, 11). +%% -define(SOCKET_OPT_SCTP_DISABLE_FRAGMENTS, 12). +%% -define(SOCKET_OPT_SCTP_HMAC_IDENT, 13). +%% -define(SOCKET_OPT_SCTP_EXPLICIT_EOR, 14). +%% -define(SOCKET_OPT_SCTP_FRAGMENT_INTERLEAVE, 15). +%% -define(SOCKET_OPT_SCTP_GET_PEER_ADDR_INFO, 16). +%% -define(SOCKET_OPT_SCTP_INITMSG, 17). +%% -define(SOCKET_OPT_SCTP_I_WANT_MAPPED_V4_ADDR, 18). +%% -define(SOCKET_OPT_SCTP_LOCAL_AUTH_CHUNKS, 19). +%% -define(SOCKET_OPT_SCTP_MAXSEG, 20). +%% -define(SOCKET_OPT_SCTP_MAXBURST, 21). +-define(SOCKET_OPT_SCTP_NODELAY, 22). +%% -define(SOCKET_OPT_SCTP_PARTIAL_DELIVERY_POINT, 23). +%% -define(SOCKET_OPT_SCTP_PEER_ADDR_PARAMS, 24). +%% -define(SOCKET_OPT_SCTP_PEER_AUTH_CHUNKS, 25). +%% -define(SOCKET_OPT_SCTP_PRIMARY_ADDR, 26). +%% -define(SOCKET_OPT_SCTP_RESET_STREAMS, 27). +%% -define(SOCKET_OPT_SCTP_RTOINFO, 28). +%% -define(SOCKET_OPT_SCTP_SET_PEER_PRIMARY_ADDR, 29). +%% -define(SOCKET_OPT_SCTP_STATUS, 30). +%% -define(SOCKET_OPT_SCTP_USE_EXT_RECVINFO, 31). -define(SOCKET_SHUTDOWN_HOW_READ, 0). -define(SOCKET_SHUTDOWN_HOW_WRITE, 1). @@ -1865,6 +1955,9 @@ enc_setopt_value(socket, sndbuf, V, _D, _T, _P) when is_integer(V) -> enc_setopt_value(socket = L, Opt, V, _D, _T, _P) -> not_supported({L, Opt, V}); +enc_setopt_value(ip, multicast_loop, V, _D, _T, _P) + when is_boolean(V) -> + V; enc_setopt_value(ip, recvtos, V, _D, _T, _P) when is_boolean(V) -> V; @@ -2157,8 +2250,8 @@ enc_sockopt_key(ip = L, multicast_all = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ip = L, multicast_if = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); -enc_sockopt_key(ip = L, multicast_loop = Opt, _Dir, _D, _T, _P) -> - not_supported({L, Opt}); +enc_sockopt_key(ip = _L, multicast_loop = _Opt, _Dir, _D, _T, _P) -> + ?SOCKET_OPT_IP_MULTICAST_LOOP; enc_sockopt_key(ip = L, multicast_ttl = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ip = L, nodefrag = Opt, _Dir, _D, raw = _T, _P) -> diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl index da5a2ca905..9c6ef47fbc 100644 --- a/lib/kernel/test/socket_server.erl +++ b/lib/kernel/test/socket_server.erl @@ -439,11 +439,21 @@ handler_init(Manager, ID, Peek, Sock) -> {ok, Type} = socket:getopt(Sock, socket, type), {ok, Proto} = socket:getopt(Sock, socket, protocol), {ok, OOBI} = socket:getopt(Sock, socket, oobinline), + {ok, SndBuf} = socket:getopt(Sock, socket, sndbuf), + {ok, RcvBuf} = socket:getopt(Sock, socket, rcvbuf), + {ok, Linger} = socket:getopt(Sock, socket, linger), + {ok, ML} = socket:getopt(Sock, ip, multicast_loop), i("got continue when: " - "~n Domain: ~p" - "~n Type: ~p" - "~n Protocol: ~p" - "~n OOBInline: ~p", [Domain, Type, Proto, OOBI]), + "~n (socket) Domain: ~p" + "~n (socket) Type: ~p" + "~n (socket) Protocol: ~p" + "~n (socket) OOBInline: ~p" + "~n (socket) SndBuf: ~p" + "~n (socket) RcvBuf: ~p" + "~n (socket) Linger: ~p" + "~n (ip) Multicast Loop: ~p", + [Domain, Type, Proto, + OOBI, SndBuf, RcvBuf, Linger, ML]), %% socket:setopt(Sock, otp, debug, true), handler_loop(#handler{peek = Peek, manager = Manager, -- cgit v1.2.3