From 9ca6de6efbe844bcf7dc996cfcf51bcd50325007 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 24 Jul 2018 11:49:12 +0200 Subject: [socket-nif] Add support for socket (level ipv6) option dstopts Added support for the IPv6 socket option(s) DSTOPTS. The option returns with einval when calling setsockopt, so either you need to be a privileged user to update, or its not actually possible to update this option (even though it says nothing about that in the man page. It only talks about set). This is the same behaviour as with RTHDR and HOPLIMIT. On FreeBSD, it says that HOPOPTS requires superuser privileges. Needs furher checking. OTP-14831. --- erts/doc/src/socket_usage.xml | 7 ++++++ erts/emulator/nifs/common/socket_nif.c | 43 +++++++++++++++++++++++++++++++++ erts/preloaded/ebin/socket.beam | Bin 57388 -> 57468 bytes erts/preloaded/src/socket.erl | 11 ++++++--- 4 files changed, 57 insertions(+), 4 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index b13582dfbc..87b44f139f 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -432,6 +432,13 @@ no none + + dstopts + boolean() + yes + yes + type = dgram | raw, requires superuser privileges to update + hoplimit boolean() diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 42a9bc3cb6..9504643cb8 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -538,6 +538,7 @@ typedef union { #define SOCKET_OPT_IPV6_ADD_MEMBERSHIP 2 #define SOCKET_OPT_IPV6_AUTHHDR 3 #define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6 +#define SOCKET_OPT_IPV6_DSTOPTS 7 #define SOCKET_OPT_IPV6_HOPLIMIT 12 #define SOCKET_OPT_IPV6_HOPOPTS 13 #define SOCKET_OPT_IPV6_MTU 17 @@ -1213,6 +1214,11 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal); #endif +#if defined(IPV6_DSTOPTS) +static ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IPV6_HOPLIMIT) static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, SocketDescriptor* descP, @@ -1539,6 +1545,10 @@ static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env, SocketDescriptor* descP); #endif +#if defined(IPV6_DSTOPTS) +static ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env, + SocketDescriptor* descP); +#endif #if defined(IPV6_HOPLIMIT) static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, SocketDescriptor* descP); @@ -5581,6 +5591,12 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, break; #endif +#if defined(IPV6_DSTOPTS) + case SOCKET_OPT_IPV6_DSTOPTS: + result = nsetopt_lvl_ipv6_dstopts(env, descP, eVal); + break; +#endif + #if defined(IPV6_HOPLIMIT) case SOCKET_OPT_IPV6_HOPLIMIT: result = nsetopt_lvl_ipv6_hoplimit(env, descP, eVal); @@ -5692,6 +5708,17 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env, #endif +#if defined(IPV6_DSTOPTS) +static +ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + return nsetopt_bool_opt(env, descP, SOL_IPV6, IPV6_DSTOPTS, eVal); +} +#endif + + #if defined(IPV6_HOPLIMIT) static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, @@ -8157,6 +8184,12 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, break; #endif +#if defined(IPV6_DSTOPTS) + case SOCKET_OPT_IPV6_DSTOPTS: + result = ngetopt_lvl_ipv6_dstopts(env, descP); + break; +#endif + #if defined(IPV6_HOPLIMIT) case SOCKET_OPT_IPV6_HOPLIMIT: result = ngetopt_lvl_ipv6_hoplimit(env, descP); @@ -8241,6 +8274,16 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env, #endif +#if defined(IPV6_DSTOPTS) +static +ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env, + SocketDescriptor* descP) +{ + return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_DSTOPTS); +} +#endif + + #if defined(IPV6_HOPLIMIT) static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index da825abb98..17622c5341 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 3c0dc6e95b..2bab42267a 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -636,7 +636,7 @@ %% -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_DSTOPTS, 7). %% -define(SOCKET_OPT_IPV6_ESP_TRANS_LEVEL, 8). %% -define(SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL, 9). %% -define(SOCKET_OPT_IPV6_FAITH, 10). @@ -2255,6 +2255,9 @@ enc_setopt_value(ipv6, add_membership, #{multiaddr := MA, enc_setopt_value(ipv6, authhdr, V, _D, T, _P) when is_boolean(V) andalso ((T =:= dgram) orelse (T =:= raw)) -> V; +enc_setopt_value(ipv6, dstopts, V, _D, T, _P) + when is_boolean(V) andalso ((T =:= dgram) orelse (T =:= raw)) -> + V; enc_setopt_value(ipv6, drop_membership, #{multiaddr := MA, interface := IF} = V, _D, _T, _P) when ((is_tuple(MA) andalso (size(MA) =:= 8)) andalso @@ -2692,14 +2695,14 @@ enc_sockopt_key(ipv6 = L, checksum = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ipv6, drop_membership = _Opt, set = _Dir, _D, _T, _P) -> ?SOCKET_OPT_IPV6_DROP_MEMBERSHIP; -enc_sockopt_key(ipv6 = L, dstopts = Opt, set = _Dir, _D, T, _P) +enc_sockopt_key(ipv6 = _L, dstopts = _Opt, _Dir, _D, T, _P) when (T =:= dgram) orelse (T =:= raw) -> - not_supported({L, Opt}); + ?SOCKET_OPT_IPV6_DSTOPTS; enc_sockopt_key(ipv6 = L, esp_trans_level = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ipv6 = L, esp_network_level = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); -enc_sockopt_key(ipv6 = L, flowinfo = Opt, set = _Dir, _D, T, _P) +enc_sockopt_key(ipv6 = L, flowinfo = Opt, _Dir, _D, T, _P) when (T =:= dgram) orelse (T =:= raw) -> not_supported({L, Opt}); enc_sockopt_key(ipv6, hoplimit = _Opt, _Dir, _D, T, _P) -- cgit v1.2.3