aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-07-24 11:08:20 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commit8b61022bdca354e541380391e3b0b2606f7af3f8 (patch)
tree41ed15ddee4429ef64661882e7394b7e0913a712
parentd7ca5ba9d8a7f094037878acfecb52b0bfbacc2e (diff)
downloadotp-8b61022bdca354e541380391e3b0b2606f7af3f8.tar.gz
otp-8b61022bdca354e541380391e3b0b2606f7af3f8.tar.bz2
otp-8b61022bdca354e541380391e3b0b2606f7af3f8.zip
[socket-nif] Add support for socket (level ipv6) option authhdr & hopopts
Added support for the IPv6 socket option(s) AUTHHDR and HOPOPTS. Its possible that the option is AUTHHDR is obsolete. It says so in the include files and when trying to get it (getsockopt) it returns with enoprotoopt. The option HOPOPTS 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.
-rw-r--r--erts/doc/src/socket_usage.xml18
-rw-r--r--erts/emulator/nifs/common/socket_nif.c102
-rw-r--r--erts/preloaded/ebin/socket.beambin57224 -> 57388 bytes
-rw-r--r--erts/preloaded/src/socket.erl27
-rw-r--r--lib/kernel/test/socket_server.erl9
5 files changed, 142 insertions, 14 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml
index b3ee38dbcb..b13582dfbc 100644
--- a/erts/doc/src/socket_usage.xml
+++ b/erts/doc/src/socket_usage.xml
@@ -419,6 +419,13 @@
<cell>none</cell>
</row>
<row>
+ <cell>authhdr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, obsolete?</cell>
+ </row>
+ <row>
<cell>drop_membership</cell>
<cell>ipv6_mreq()</cell>
<cell>yes</cell>
@@ -429,8 +436,15 @@
<cell>hoplimit</cell>
<cell>boolean()</cell>
<cell>yes</cell>
- <cell>no</cell>
- <cell>type = dgram | raw</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
+ </row>
+ <row>
+ <cell>hopopts</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
</row>
<row>
<cell>mtu</cell>
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index f4ac43a9cd..42a9bc3cb6 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -536,8 +536,10 @@ typedef union {
#define SOCKET_OPT_IP_UNBLOCK_SOURCE 33
#define SOCKET_OPT_IPV6_ADD_MEMBERSHIP 2
+#define SOCKET_OPT_IPV6_AUTHHDR 3
#define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6
#define SOCKET_OPT_IPV6_HOPLIMIT 12
+#define SOCKET_OPT_IPV6_HOPOPTS 13
#define SOCKET_OPT_IPV6_MTU 17
#define SOCKET_OPT_IPV6_MTU_DISCOVER 18
#define SOCKET_OPT_IPV6_MULTICAST_HOPS 19
@@ -1201,6 +1203,11 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM eVal);
#endif
+#if defined(IPV6_AUTHHDR)
+static ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal);
+#endif
#if defined(IPV6_DROP_MEMBERSHIP)
static ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -1211,6 +1218,11 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM eVal);
#endif
+#if defined(IPV6_HOPOPTS)
+static ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal);
+#endif
#if defined(IPV6_MTU)
static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -1523,10 +1535,18 @@ static ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
SocketDescriptor* descP,
int eOpt);
+#if defined(IPV6_AUTHHDR)
+static ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ SocketDescriptor* descP);
+#endif
#if defined(IPV6_HOPLIMIT)
static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
SocketDescriptor* descP);
#endif
+#if defined(IPV6_HOPOPTS)
+static ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ SocketDescriptor* descP);
+#endif
#if defined(IPV6_MTU)
static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
SocketDescriptor* descP);
@@ -1553,7 +1573,7 @@ static ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
#endif
#if defined(IPV6_RTHDR)
static ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- SocketDescriptor* descP);
+ SocketDescriptor* descP);
#endif
#if defined(IPV6_V6ONLY)
static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
@@ -5549,6 +5569,12 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
break;
#endif
+#if defined(IPV6_AUTHHDR)
+ case SOCKET_OPT_IPV6_AUTHHDR:
+ result = nsetopt_lvl_ipv6_authhdr(env, descP, eVal);
+ break;
+#endif
+
#if defined(IPV6_DROP_MEMBERSHIP)
case SOCKET_OPT_IPV6_DROP_MEMBERSHIP:
result = nsetopt_lvl_ipv6_drop_membership(env, descP, eVal);
@@ -5561,6 +5587,12 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
break;
#endif
+#if defined(IPV6_HOPOPTS)
+ case SOCKET_OPT_IPV6_HOPOPTS:
+ result = nsetopt_lvl_ipv6_hopopts(env, descP, eVal);
+ break;
+#endif
+
#if defined(IPV6_MTU)
case SOCKET_OPT_IPV6_MTU:
result = nsetopt_lvl_ipv6_mtu(env, descP, eVal);
@@ -5637,6 +5669,17 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
#endif
+#if defined(IPV6_AUTHHDR)
+static
+ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal)
+{
+ return nsetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR, eVal);
+}
+#endif
+
+
#if defined(IPV6_DROP_MEMBERSHIP)
static
ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
@@ -5660,6 +5703,17 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
#endif
+#if defined(IPV6_HOPOPTS)
+static
+ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal)
+{
+ return nsetopt_bool_opt(env, descP, SOL_IPV6, IPV6_HOPOPTS, eVal);
+}
+#endif
+
+
#if defined(IPV6_MTU)
static
ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
@@ -8097,12 +8151,24 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
"\r\n", eOpt) );
switch (eOpt) {
+#if defined(IPV6_AUTHHDR)
+ case SOCKET_OPT_IPV6_AUTHHDR:
+ result = ngetopt_lvl_ipv6_authhdr(env, descP);
+ break;
+#endif
+
#if defined(IPV6_HOPLIMIT)
case SOCKET_OPT_IPV6_HOPLIMIT:
result = ngetopt_lvl_ipv6_hoplimit(env, descP);
break;
#endif
+#if defined(IPV6_HOPOPTS)
+ case SOCKET_OPT_IPV6_HOPOPTS:
+ result = ngetopt_lvl_ipv6_hopopts(env, descP);
+ break;
+#endif
+
#if defined(IPV6_MTU)
case SOCKET_OPT_IPV6_MTU:
result = ngetopt_lvl_ipv6_mtu(env, descP);
@@ -8165,6 +8231,16 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
}
+#if defined(IPV6_AUTHHDR)
+static
+ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+ return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR);
+}
+#endif
+
+
#if defined(IPV6_HOPLIMIT)
static
ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
@@ -8175,6 +8251,16 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
#endif
+#if defined(IPV6_HOPOPTS)
+static
+ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+ return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_HOPOPTS);
+}
+#endif
+
+
#if defined(IPV6_MTU)
static
ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
@@ -8707,6 +8793,13 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
SOCKOPTLEN_T valSz = sizeof(val);
int res;
+ /*
+ SSDBG( descP, ("SOCKET", "ngetopt_bool_opt -> entry with"
+ "\r\n: level: %d"
+ "\r\n: opt: %d"
+ "\r\n", level, opt) );
+ */
+
res = sock_getopt(descP->sock, level, opt, &val, &valSz);
if (res != 0) {
@@ -8717,6 +8810,13 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
result = esock_make_ok2(env, bval);
}
+ /*
+ SSDBG( descP, ("SOCKET", "ngetopt_bool_opt -> done when"
+ "\r\n: res: %d"
+ "\r\n: result: %T"
+ "\r\n", res, result) );
+ */
+
return result;
}
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index 1873289486..da825abb98 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index d2267192e5..3c0dc6e95b 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -632,7 +632,7 @@
%% -define(SOCKET_OPT_IPV6_ADDFORM, 1).
-define(SOCKET_OPT_IPV6_ADD_MEMBERSHIP, 2).
-%% -define(SOCKET_OPT_IPV6_AUTHHDR, 3).
+-define(SOCKET_OPT_IPV6_AUTHHDR, 3). % Obsolete?
%% -define(SOCKET_OPT_IPV6_AUTH_LEVEL, 4).
%% -define(SOCKET_OPT_IPV6_CHECKSUM, 5).
-define(SOCKET_OPT_IPV6_DROP_MEMBERSHIP, 6).
@@ -642,7 +642,7 @@
%% -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_HOPOPTS, 13).
%% -define(SOCKET_OPT_IPV6_IPCOMP_LEVEL, 14).
%% -define(SOCKET_OPT_IPV6_JOIN_GROUP, 15).
%% -define(SOCKET_OPT_IPV6_LEAVE_GROUP, 16).
@@ -2249,6 +2249,12 @@ enc_setopt_value(ipv6, add_membership, #{multiaddr := MA,
when ((is_tuple(MA) andalso (size(MA) =:= 8)) andalso
(is_integer(IF) andalso (IF >= 0))) ->
V;
+%% Is this obsolete? When get, the result is enoprotoopt and in the
+%% header file it says 'obsolete'...
+%% But there might be (old?) versions of linux where it still works...
+enc_setopt_value(ipv6, authhdr, 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
@@ -2257,6 +2263,9 @@ 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, hopopts, V, _D, T, _P)
+ when is_boolean(V) andalso ((T =:= dgram) orelse (T =:= raw)) ->
+ V;
enc_setopt_value(ipv6, mtu, V, _D, _T, _P) when is_integer(V) ->
V;
enc_setopt_value(ipv6, mtu_discover, V, _D, _T, _P)
@@ -2282,8 +2291,8 @@ enc_setopt_value(ipv6, Opt, V, _D, _T, _P)
when ((Opt =:= recvpktinfo) orelse (Opt =:= pktinfo)) andalso
is_boolean(V) ->
V;
-enc_setopt_value(ipv6, rthdr, V, _D, _T, _P)
- when is_boolean(V) ->
+enc_setopt_value(ipv6, rthdr, 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;
@@ -2674,9 +2683,9 @@ enc_sockopt_key(ipv6 = L, addrform = Opt, set = _Dir, _D, _T, _P) ->
not_supported({L, Opt});
enc_sockopt_key(ipv6, add_membership = _Opt, set = _Dir, _D, _T, _P) ->
?SOCKET_OPT_IPV6_ADD_MEMBERSHIP;
-enc_sockopt_key(ipv6 = L, authhdr = Opt, set = _Dir, _D, T, _P)
+enc_sockopt_key(ipv6 = _L, authhdr = _Opt, _Dir, _D, T, _P)
when ((T =:= dgram) orelse (T =:= raw)) ->
- not_supported({L, Opt});
+ ?SOCKET_OPT_IPV6_AUTHHDR;
enc_sockopt_key(ipv6 = L, auth_level = Opt, _Dir, _D, _T, _P) ->
not_supported({L, Opt});
enc_sockopt_key(ipv6 = L, checksum = Opt, _Dir, _D, _T, _P) ->
@@ -2693,12 +2702,12 @@ enc_sockopt_key(ipv6 = L, esp_network_level = Opt, _Dir, _D, _T, _P) ->
enc_sockopt_key(ipv6 = L, flowinfo = Opt, set = _Dir, _D, T, _P)
when (T =:= dgram) orelse (T =:= raw) ->
not_supported({L, Opt});
-enc_sockopt_key(ipv6, hoplimit = _Opt, _Dir, set = _D, T, _P)
+enc_sockopt_key(ipv6, hoplimit = _Opt, _Dir, _D, T, _P)
when (T =:= dgram) orelse (T =:= raw) ->
?SOCKET_OPT_IPV6_HOPLIMIT;
-enc_sockopt_key(ipv6 = L, hopopts = Opt, set = _Dir, _D, T, _P)
+enc_sockopt_key(ipv6 = _L, hopopts = _Opt, _Dir, _D, T, _P)
when ((T =:= dgram) orelse (T =:= raw)) ->
- not_supported({L, Opt});
+ ?SOCKET_OPT_IPV6_HOPOPTS;
enc_sockopt_key(ipv6 = L, ipcomp_level = Opt, _Dir, _D, _T, _P) ->
not_supported({L, Opt});
enc_sockopt_key(ipv6 = L, join_group = Opt, _Dir, _D, _T, _P) ->
diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl
index 75cede75e5..1cd0ec1202 100644
--- a/lib/kernel/test/socket_server.erl
+++ b/lib/kernel/test/socket_server.erl
@@ -634,6 +634,8 @@ handler_init(Manager, ID, Peek, Sock) ->
MLoop6 = GIP6(multicast_loop),
RecvPktInfo = GIP6(recvpktinfo),
RtHdr = GIP6(rthdr),
+ AuthHdr = GIP6(authhdr),
+ HopOpts = GIP6(hopopts),
i("got continue when: "
"~n (socket) Domain: ~p"
"~n (socket) Type: ~p"
@@ -666,14 +668,17 @@ handler_init(Manager, ID, Peek, Sock) ->
"~n (ipv6) Multicast IF: ~s"
"~n (ipv6) Multicast Loop: ~s"
"~n (ipv6) Recv Pkt Info: ~s"
- "~n (ipv6) RT Hdr: ~s",
+ "~n (ipv6) RT Hdr: ~s"
+ "~n (ipv6) Auth Hdr: ~s"
+ "~n (ipv6) Hop Opts: ~s",
[Domain, Type, Proto,
RA, RP, B2D, OOBI,
RcvBuf, RcvLW, RcvTO, SndBuf, SndLW, SndTO,
Linger, Timestamp,
FreeBind, MTU, MTUDisc, MALL, MIF4, MLoop4, MTTL,
NF, RecvIF, RecvOPTS, RecvTOS, RecvTTL,
- MHops, MIF6, MLoop6, RecvPktInfo, RtHdr]),
+ MHops, MIF6, MLoop6, RecvPktInfo,
+ RtHdr, AuthHdr, HopOpts]),
handler_loop(#handler{peek = Peek,
manager = Manager,