From 6b01561dc13a0152f56da0a2c61ad88236f87de7 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 26 Jul 2018 11:07:05 +0200 Subject: [socket-nif] Add support for socket (level ip) option sendsrcaddr Added support for ip level socket option SENDSRCADDR. This option requires sendmsg to actually use, so we cannot test this fully at the moment. OTP-14831 --- erts/doc/src/socket_usage.xml | 11 ++++++ erts/emulator/nifs/common/socket_nif.c | 59 +++++++++++++++++++++++++++++++++ erts/preloaded/ebin/socket.beam | Bin 59660 -> 59768 bytes erts/preloaded/src/socket.erl | 9 +++-- lib/kernel/test/socket_server.erl | 12 ++++--- 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index f69aa75820..933341bd35 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -35,6 +35,10 @@

The socket interface (module) is basically an "thin" layer on top of the OS socket interface. It is assumed that, unless you have special needs, gen_[tcp|udp|sctp] should be sufficent.

+

Note that just because we have a documented and described option, + it does not mean that the OS supports it. So its recommended + that the user reads the platform specific documentation for the + option used.

@@ -428,6 +432,13 @@ yes type = raw + + sendsrcaddr + boolean() + yes + yes + none + tos ip_tos() diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 4ba94f4f60..13250349db 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -540,6 +540,7 @@ typedef union { #define SOCKET_OPT_IP_RECVTTL 26 #define SOCKET_OPT_IP_RETOPTS 27 #define SOCKET_OPT_IP_ROUTER_ALERT 28 +#define SOCKET_OPT_IP_SENDSRCADDR 29 // Same as IP_RECVDSTADDR? #define SOCKET_OPT_IP_TOS 30 #define SOCKET_OPT_IP_TRANSPARENT 31 #define SOCKET_OPT_IP_TTL 32 @@ -1218,6 +1219,11 @@ static ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal); #endif +#if defined(IP_SENDSRCADDR) +static ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IP_TOS) static ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env, SocketDescriptor* descP, @@ -1640,6 +1646,10 @@ static ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env, SocketDescriptor* descP); #endif +#if defined(IP_SENDSRCADDR) +static ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, + SocketDescriptor* descP); +#endif #if defined(IP_TOS) static ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env, SocketDescriptor* descP); @@ -5125,6 +5135,12 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, break; #endif +#if defined(IP_SENDSRCADDR) + case SOCKET_OPT_IP_SENDSRCADDR: + result = nsetopt_lvl_ip_sendsrcaddr(env, descP, eVal); + break; +#endif + #if defined(IP_TOS) case SOCKET_OPT_IP_TOS: result = nsetopt_lvl_ip_tos(env, descP, eVal); @@ -5808,6 +5824,25 @@ ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env, #endif +/* nsetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option + */ +#if defined(IP_SENDSRCADDR) +static +ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(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_SENDSRCADDR, eVal); +} +#endif + + /* nsetopt_lvl_ip_tos - Level IP TOS option */ #if defined(IP_TOS) @@ -8418,6 +8453,12 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, break; #endif +#if defined(IP_SENDSRCADDR) + case SOCKET_OPT_IP_SENDSRCADDR: + result = ngetopt_lvl_ip_sendsrcaddr(env, descP); + break; +#endif + #if defined(IP_TOS) case SOCKET_OPT_IP_TOS: result = ngetopt_lvl_ip_tos(env, descP); @@ -8846,6 +8887,24 @@ ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env, #endif +/* ngetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option + */ +#if defined(IP_SENDSRCADDR) +static +ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(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_SENDSRCADDR); +} +#endif + + /* ngetopt_lvl_ip_tos - Level IP TOS option */ #if defined(IP_TOS) diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 90cb657178..b2bd8f2728 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 68b7d3f4b0..1983c993a5 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -638,11 +638,11 @@ -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_SENDSRCADDR, 29). % FreeBSD -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_IP_UNBLOCK_SOURCE, 33). -define(SOCKET_OPT_IPV6_ADDRFORM, 1). -define(SOCKET_OPT_IPV6_ADD_MEMBERSHIP, 2). @@ -2316,6 +2316,9 @@ enc_setopt_value(ip, retopts, V, _D, _T, _P) enc_setopt_value(ip, router_alert, V, _D, _T, _P) when is_integer(V) -> V; +enc_setopt_value(ip, sendsrcaddr, V, _D, _T, _P) + when is_boolean(V) -> + V; enc_setopt_value(ip, tos, V, _D, _T, _P) when (V =:= lowdelay) orelse (V =:= throughput) orelse @@ -2776,6 +2779,8 @@ enc_sockopt_key(ip = _L, retopts = _Opt, _Dir, _D, T, _P) when (T =/= stream) -> ?SOCKET_OPT_IP_RETOPTS; enc_sockopt_key(ip, router_alert = _Opt, _Dir, _D, raw = _T, _P) -> ?SOCKET_OPT_IP_ROUTER_ALERT; +enc_sockopt_key(ip, sendsrcaddr = _Opt, _Dir, _D, _T, _P) -> + ?SOCKET_OPT_IP_SENDSRCADDR; %% On FreeBSD it specifies that this option is only valid %% for stream, dgram and "some" raw sockets... %% No such condition on linux (in the man page)... diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl index 3dad94b751..88b63ecf2d 100644 --- a/lib/kernel/test/socket_server.erl +++ b/lib/kernel/test/socket_server.erl @@ -644,6 +644,7 @@ handler_init(Manager, ID, Peek, Sock) -> RecvTOS = GIP4(recvtos), RecvTTL = GIP4(recvttl), % not stream RetOpts = GIP4(retopts), % not stream + SendSrcAddr = GIP4(sendsrcaddr), TOS = GIP4(tos), Transparent = GIP4(transparent), TTL = GIP4(ttl), @@ -691,6 +692,7 @@ handler_init(Manager, ID, Peek, Sock) -> "~n (ip) Recv TOS: ~s" "~n (ip) Recv TTL: ~s" "~n (ip) Ret Opts: ~s" + "~n (ip) Send Src Addr: ~s" "~n (ip) TOS: ~s" "~n (ip) Transparent: ~s" "~n (ip) TTL: ~s" @@ -713,7 +715,7 @@ handler_init(Manager, ID, Peek, Sock) -> FreeBind, MTU, MTUDisc, MALL, MIF4, MLoop4, MTTL, NF, PktInfo,RecvErr4, RecvIF, RecvOPTS, RecvOrigDstAddr, RecvTOS, RecvTTL, RetOpts, - TOS, Transparent, TTL, + SendSrcAddr, TOS, Transparent, TTL, MHops, MIF6, MLoop6, RecvErr6, RecvPktInfo, RtHdr, AuthHdr, HopLimit, HopOpts, DstOpts, FlowInfo, UHops]), @@ -724,14 +726,14 @@ handler_init(Manager, ID, Peek, Sock) -> socket = Sock}) end. -so(Sock, Lvl, Opt, Val) -> - ok = socket:setopt(Sock, Lvl, Opt, Val). +%% so(Sock, Lvl, Opt, Val) -> +%% ok = socket:setopt(Sock, Lvl, Opt, Val). %% soso(Sock, Opt, Val) -> %% so(Sock, socket, Opt, Val). -soip(Sock, Opt, Val) -> - so(Sock, ip, Opt, Val). +%% soip(Sock, Opt, Val) -> +%% so(Sock, ip, Opt, Val). %% soipv6(Sock, Opt, Val) -> %% so(Sock, ipv6, Opt, Val). -- cgit v1.2.3