From 8d759e6f00b1cf834fe21654de3f53df706e8c0f Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 18 Jul 2018 10:23:45 +0200 Subject: [socket-nif] Add support for socket (level ipv6) option v6only Added support for the IPv6 option V6ONLY. OTP-14831 --- erts/emulator/nifs/common/socket_nif.c | 112 +++++++++++++++++++++++++++++++++ erts/preloaded/ebin/socket.beam | Bin 51376 -> 51436 bytes erts/preloaded/src/socket.erl | 8 ++- 3 files changed, 117 insertions(+), 3 deletions(-) diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 224dcc9ff6..15d43da9da 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -388,6 +388,7 @@ typedef union { #define SOCKET_OPT_IPV6_ADD_MEMBERSHIP 2 #define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6 #define SOCKET_OPT_IPV6_HOPLIMIT 12 +#define SOCKET_OPT_IPV6_V6ONLY 33 #define SOCKET_OPT_TCP_CONGESTION 1 #define SOCKET_OPT_TCP_CORK 2 @@ -1007,6 +1008,11 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal); #endif +#if defined(IPV6_V6ONLY) +static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, @@ -1221,6 +1227,11 @@ static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, SocketDescriptor* descP); #endif +#if defined(IPV6_V6ONLY) +static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, + SocketDescriptor* descP); +#endif + #endif // defined(SOL_IPV6) static ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env, SocketDescriptor* descP, @@ -4235,6 +4246,11 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, { ERL_NIF_TERM result; + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip -> entry with" + "\r\n opt: %d" + "\r\n", eOpt) ); + switch (eOpt) { #if defined(IP_ADD_MEMBERSHIP) case SOCKET_OPT_IP_ADD_MEMBERSHIP: @@ -4920,6 +4936,11 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, { ERL_NIF_TERM result; + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6 -> entry with" + "\r\n opt: %d" + "\r\n", eOpt) ); + switch (eOpt) { #if defined(IPV6_ADD_MEMBERSHIP) case SOCKET_OPT_IPV6_ADD_MEMBERSHIP: @@ -4939,6 +4960,12 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, break; #endif +#if defined(IPV6_V6ONLY) + case SOCKET_OPT_IPV6_V6ONLY: + result = nsetopt_lvl_ipv6_v6only(env, descP, eVal); + break; +#endif + default: result = esock_make_error(env, esock_atom_einval); break; @@ -4983,6 +5010,17 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, #endif +#if defined(IPV6_V6ONLY) +static +ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + return nsetopt_bool_opt(env, descP, SOL_IPV6, IPV6_V6ONLY, eVal); +} +#endif + + #if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, @@ -5046,6 +5084,11 @@ ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env, { ERL_NIF_TERM result; + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_tcp -> entry with" + "\r\n opt: %d" + "\r\n", eOpt) ); + switch (eOpt) { #if defined(TCP_CONGESTION) case SOCKET_OPT_TCP_CONGESTION: @@ -5126,6 +5169,11 @@ ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env, { ERL_NIF_TERM result; + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_udp -> entry with" + "\r\n opt: %d" + "\r\n", eOpt) ); + switch (eOpt) { #if defined(UDP_CORK) case SOCKET_OPT_UDP_CORK: @@ -5168,6 +5216,11 @@ ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env, { ERL_NIF_TERM result; + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_sctp -> entry with" + "\r\n opt: %d" + "\r\n", eOpt) ); + switch (eOpt) { #if defined(SCTP_AUTOCLOSE) case SOCKET_OPT_SCTP_AUTOCLOSE: @@ -5557,6 +5610,11 @@ ERL_NIF_TERM ngetopt(ErlNifEnv* env, result = ngetopt_level(env, descP, level, eOpt); } + SSDBG( descP, + ("SOCKET", "ngetopt -> done when" + "\r\n result: %T" + "\r\n", result) ); + return result; } @@ -5629,6 +5687,12 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, uint16_t valueType; SOCKOPTLEN_T valueSz; + SSDBG( descP, + ("SOCKET", "ngetopt_native -> entry with" + "\r\n level: %d" + "\r\n eOpt: %d" + "\r\n", level, eOpt) ); + /* * We should really make it possible to specify common specific types, * such as integer or boolean (instead of the size)... @@ -5654,6 +5718,11 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, result = esock_make_error(env, esock_atom_einval); } + SSDBG( descP, + ("SOCKET", "ngetopt_native -> done when" + "\r\n result: %T" + "\r\n", result) ); + return result; } @@ -5668,6 +5737,13 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, ERL_NIF_TERM result = enif_make_badarg(env); int res; + SSDBG( descP, + ("SOCKET", "ngetopt_native_unspec -> entry with" + "\r\n level: %d" + "\r\n opt: %d" + "\r\n valueSz: %d" + "\r\n", level, opt, valueSz) ); + if (valueSz == 0) { res = sock_getopt(descP->sock, level, opt, NULL, NULL); if (res != 0) @@ -5695,6 +5771,11 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, } } + SSDBG( descP, + ("SOCKET", "ngetopt_native_unspec -> done when" + "\r\n result: %T" + "\r\n", result) ); + return result; } @@ -5754,6 +5835,11 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, break; } + SSDBG( descP, + ("SOCKET", "ngetopt_level -> done when" + "\r\n result: %T" + "\r\n", result) ); + return result; } @@ -6599,6 +6685,11 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, { ERL_NIF_TERM result; + SSDBG( descP, + ("SOCKET", "ngetopt_lvl_ipv6 -> entry with" + "\r\n eOpt: %d" + "\r\n", eOpt) ); + switch (eOpt) { #if defined(IPV6_HOPLIMIT) case SOCKET_OPT_IPV6_HOPLIMIT: @@ -6606,11 +6697,22 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, break; #endif +#if defined(IPV6_V6ONLY) + case SOCKET_OPT_IPV6_V6ONLY: + result = ngetopt_lvl_ipv6_v6only(env, descP); + break; +#endif + default: result = esock_make_error(env, esock_atom_einval); break; } + SSDBG( descP, + ("SOCKET", "ngetopt_lvl_ipv6 -> done when" + "\r\n result: %T" + "\r\n", result) ); + return result; } @@ -6625,6 +6727,16 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, #endif +#if defined(IPV6_V6ONLY) +static +ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, + SocketDescriptor* descP) +{ + return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_V6ONLY); +} +#endif + + #endif // defined(SOL_IPV6) diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 79224124e5..307a94be4e 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 64e0e6ce5b..3e31326759 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -602,7 +602,7 @@ %% -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_IPV6_V6ONLY, 33). -define(SOCKET_OPT_TCP_CONGESTION, 1). -define(SOCKET_OPT_TCP_CORK, 2). @@ -2105,6 +2105,8 @@ enc_setopt_value(ipv6, drop_membership, #{multiaddr := MA, enc_setopt_value(ipv6, hoplimit, V, _D, T, _P) when is_boolean(V) andalso ((T =:= dgram) orelse (T =:= raw)) -> V; +enc_setopt_value(ipv6, v6only, V, _D, _T, _P) when is_boolean(V) -> + V; enc_setopt_value(ipv6 = L, Opt, V, _D, _T, _P) -> not_supported({L, Opt, V}); @@ -2490,8 +2492,8 @@ enc_sockopt_key(ipv6 = L, unicast_hops = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ipv6 = L, use_min_mtu = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); -enc_sockopt_key(ipv6 = L, v6only = Opt, _Dir, _D, _T, _P) -> - not_supported({L, Opt}); +enc_sockopt_key(ipv6 = _L, v6only = _Opt, _Dir, _D, _T, _P) -> + ?SOCKET_OPT_IPV6_V6ONLY; enc_sockopt_key(ipv6 = L, UnknownOpt, _Dir, _D, _T, _P) -> unknown({L, UnknownOpt}); -- cgit v1.2.3