diff options
author | Micael Karlberg <[email protected]> | 2018-07-24 16:11:32 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2018-09-18 14:50:18 +0200 |
commit | b9237c96b2b86c82bb128625cc532b3528222560 (patch) | |
tree | 0207f6fc08722890675f17b6c126e25c9a9e70aa /erts | |
parent | 7d5b6e7bf640eb5d64679e3bf7b440b8e21e3a4d (diff) | |
download | otp-b9237c96b2b86c82bb128625cc532b3528222560.tar.gz otp-b9237c96b2b86c82bb128625cc532b3528222560.tar.bz2 otp-b9237c96b2b86c82bb128625cc532b3528222560.zip |
[socket-nif] Add support for socket (level ipv6) option addrform
Added support for the IPv6 socket option ADDRFORM.
Only allowed for IPv6 sockets that are connected and bound to a
v4-mapped-on-v6 address.
OTP-14831.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/socket_usage.xml | 8 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 54 | ||||
-rw-r--r-- | erts/preloaded/ebin/socket.beam | bin | 57952 -> 58020 bytes | |||
-rw-r--r-- | erts/preloaded/src/socket.erl | 8 |
4 files changed, 67 insertions, 3 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index 1423571f5c..8480af315e 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -412,6 +412,14 @@ <cell><em>Other</em></cell> </row> <row> + <cell>addrform</cell> + <cell>inet</cell> + <cell>yes</cell> + <cell>no</cell> + <cell>allowed only for IPv6 sockets that are connected and bound to a + v4-mapped-on-v6 address</cell> + </row> + <row> <cell>add_membership</cell> <cell>ipv6_mreq()</cell> <cell>yes</cell> diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 4d78e89a4f..f7053d77fa 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -537,6 +537,7 @@ typedef union { #define SOCKET_OPT_IP_TTL 32 #define SOCKET_OPT_IP_UNBLOCK_SOURCE 33 +#define SOCKET_OPT_IPV6_ADDRFORM 1 #define SOCKET_OPT_IPV6_ADD_MEMBERSHIP 2 #define SOCKET_OPT_IPV6_AUTHHDR 3 #define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6 @@ -1204,6 +1205,11 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, SocketDescriptor* descP, int eOpt, ERL_NIF_TERM eVal); +#if defined(IPV6_ADDRFORM) +static ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IPV6_ADD_MEMBERSHIP) static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env, SocketDescriptor* descP, @@ -5607,6 +5613,12 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, "\r\n", eOpt) ); switch (eOpt) { +#if defined(IPV6_ADDRFORM) + case SOCKET_OPT_IPV6_ADDRFORM: + result = nsetopt_lvl_ipv6_addrform(env, descP, eVal); + break; +#endif + #if defined(IPV6_ADD_MEMBERSHIP) case SOCKET_OPT_IPV6_ADD_MEMBERSHIP: result = nsetopt_lvl_ipv6_add_membership(env, descP, eVal); @@ -5725,6 +5737,48 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, } +#if defined(IPV6_ADDRFORM) +static +ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + ERL_NIF_TERM result; + int res, edomain, domain; + + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_addrform -> entry with" + "\r\n eVal: %T" + "\r\n", eVal) ); + + if (!GET_INT(env, eVal, &edomain)) + return esock_make_error(env, esock_atom_einval); + + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_addrform -> decode" + "\r\n edomain: %d" + "\r\n", edomain) ); + + if (!edomain2domain(edomain, &domain)) + return esock_make_error(env, esock_atom_einval); + + SSDBG( descP, ("SOCKET", "nsetopt_lvl_ipv6_addrform -> try set opt to %d\r\n", + domain) ); + + res = socket_setopt(descP->sock, + SOL_IPV6, IPV6_ADDRFORM, + &domain, sizeof(domain)); + + if (res != 0) + result = esock_make_error_errno(env, sock_errno()); + else + result = esock_atom_ok; + + return result; +} +#endif + + #if defined(IPV6_ADD_MEMBERSHIP) static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env, diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex cdc403055b..20f2cf659b 100644 --- a/erts/preloaded/ebin/socket.beam +++ b/erts/preloaded/ebin/socket.beam diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 82a51ee245..0c3a17b54d 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -635,7 +635,7 @@ -define(SOCKET_OPT_IP_TTL, 32). -define(SOCKET_OPT_IP_UNBLOCK_SOURCE, 33). -%% -define(SOCKET_OPT_IPV6_ADDFORM, 1). +-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). @@ -2254,6 +2254,8 @@ enc_setopt_value(ip, unblock_source, #{multiaddr := MA, enc_setopt_value(ip = L, Opt, V, _D, _T, _P) -> not_supported({L, Opt, V}); +enc_setopt_value(ipv6, addrform, inet = V, _D, _T, _P) -> + enc_domain(V); enc_setopt_value(ipv6, add_membership, #{multiaddr := MA, interface := IF} = V, _D, _T, _P) when ((is_tuple(MA) andalso (size(MA) =:= 8)) andalso @@ -2704,8 +2706,8 @@ enc_sockopt_key(ip = L, UnknownOpt, _Dir, _D, _T, _P) -> unknown({L, UnknownOpt}); %% IPv6 socket options -enc_sockopt_key(ipv6 = L, addrform = Opt, set = _Dir, _D, _T, _P) -> - not_supported({L, Opt}); +enc_sockopt_key(ipv6 = _L, addrform = _Opt, set = _Dir, _D, _T, _P) -> + ?SOCKET_OPT_IPV6_ADDRFORM; enc_sockopt_key(ipv6, add_membership = _Opt, set = _Dir, _D, _T, _P) -> ?SOCKET_OPT_IPV6_ADD_MEMBERSHIP; enc_sockopt_key(ipv6 = _L, authhdr = _Opt, _Dir, _D, T, _P) |