aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-10-04 10:06:16 +0200
committerMicael Karlberg <[email protected]>2018-10-04 10:06:16 +0200
commit4b1e1e148a5cc9c19127b61aaa3e15eeeaea6cb2 (patch)
tree26621f8cca51051dda15027260c836783e916f7f /erts
parent1c412c62ba3be17b7a818f264049a7ee7942351e (diff)
downloadotp-4b1e1e148a5cc9c19127b61aaa3e15eeeaea6cb2.tar.gz
otp-4b1e1e148a5cc9c19127b61aaa3e15eeeaea6cb2.tar.bz2
otp-4b1e1e148a5cc9c19127b61aaa3e15eeeaea6cb2.zip
[socket-nif] Socket option 'SO_DOMAIN' not avalable on all platforms
Internally in the socket module we accessed domain, type and protocol for an open socket. But as it turns out, domain (family) is not actually available as a socket option on all platforms. FreeBSD in this case. So, since we store these values in the socket descriptor anyway, we switch to use these values for our internal use instead. OTP-14831
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/socket_usage.xml2
-rw-r--r--erts/emulator/nifs/common/socket_nif.c146
-rw-r--r--erts/preloaded/ebin/socket.beambin66584 -> 66596 bytes
-rw-r--r--erts/preloaded/src/socket.erl13
4 files changed, 152 insertions, 9 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml
index 23d0f319f1..1ea29097c3 100644
--- a/erts/doc/src/socket_usage.xml
+++ b/erts/doc/src/socket_usage.xml
@@ -146,7 +146,7 @@
<cell>domain()</cell>
<cell>no</cell>
<cell>yes</cell>
- <cell>none</cell>
+ <cell><em>Not</em> on FreeBSD (for instance)</cell>
</row>
<row>
<cell>dontroute</cell>
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 876bed3135..b821fd6575 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -319,8 +319,8 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
/* Debug stuff... */
-#define SOCKET_NIF_DEBUG_DEFAULT FALSE
-#define SOCKET_DEBUG_DEFAULT FALSE
+#define SOCKET_GLOBAL_DEBUG_DEFAULT FALSE
+#define SOCKET_DEBUG_DEFAULT FALSE
/* Counters and stuff (Don't know where to sent this stuff anyway) */
#define SOCKET_NIF_IOW_DEFAULT FALSE
@@ -504,6 +504,9 @@ typedef union {
#define SOCKET_OPT_OTP_RCVBUF 4
#define SOCKET_OPT_OTP_RCVCTRLBUF 6
#define SOCKET_OPT_OTP_SNDCTRLBUF 7
+#define SOCKET_OPT_OTP_DOMAIN 0xFF01 // INTERNAL AND ONLY GET
+#define SOCKET_OPT_OTP_TYPE 0xFF02 // INTERNAL AND ONLY GET
+#define SOCKET_OPT_OTP_PROTOCOL 0xFF03 // INTERNAL AND ONLY GET
#define SOCKET_OPT_SOCK_ACCEPTCONN 1
#define SOCKET_OPT_SOCK_BINDTODEVICE 3
@@ -1510,6 +1513,12 @@ static ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
SocketDescriptor* descP);
static ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
+ SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
+ SocketDescriptor* descP);
+static ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
+ SocketDescriptor* descP);
static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
SocketDescriptor* descP,
int level,
@@ -8279,6 +8288,19 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
result = ngetopt_otp_sndctrlbuf(env, descP);
break;
+ /* *** INTERNAL *** */
+ case SOCKET_OPT_OTP_DOMAIN:
+ result = ngetopt_otp_domain(env, descP);
+ break;
+
+ case SOCKET_OPT_OTP_TYPE:
+ result = ngetopt_otp_type(env, descP);
+ break;
+
+ case SOCKET_OPT_OTP_PROTOCOL:
+ result = ngetopt_otp_protocol(env, descP);
+ break;
+
default:
result = esock_make_error(env, esock_atom_einval);
break;
@@ -8366,6 +8388,124 @@ ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
}
+/* ngetopt_otp_domain - Handle the OTP (level) domain options.
+ */
+static
+ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+ ERL_NIF_TERM result;
+ int val = descP->domain;
+
+ switch (val) {
+ case AF_INET:
+ result = esock_make_ok2(env, esock_atom_inet);
+ break;
+
+#if defined(HAVE_IN6) && defined(AF_INET6)
+ case AF_INET6:
+ result = esock_make_ok2(env, esock_atom_inet6);
+ break;
+#endif
+
+#if defined(HAVE_SYS_UN_H)
+ case AF_UNIX:
+ result = esock_make_ok2(env, esock_atom_local);
+ break;
+#endif
+
+ default:
+ result = esock_make_error(env,
+ MKT2(env,
+ esock_atom_unknown,
+ MKI(env, val)));
+ break;
+ }
+
+ return result;
+}
+
+
+/* ngetopt_otp_type - Handle the OTP (level) type options.
+ */
+static
+ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+ ERL_NIF_TERM result;
+ int val = descP->type;
+
+ switch (val) {
+ case SOCK_STREAM:
+ result = esock_make_ok2(env, esock_atom_stream);
+ break;
+
+ case SOCK_DGRAM:
+ result = esock_make_ok2(env, esock_atom_dgram);
+ break;
+
+#ifdef HAVE_SCTP
+ case SOCK_SEQPACKET:
+ result = esock_make_ok2(env, esock_atom_seqpacket);
+ break;
+#endif
+ case SOCK_RAW:
+ result = esock_make_ok2(env, esock_atom_raw);
+ break;
+
+ case SOCK_RDM:
+ result = esock_make_ok2(env, esock_atom_rdm);
+ break;
+
+ default:
+ result = esock_make_error(env,
+ MKT2(env, esock_atom_unknown, MKI(env, val)));
+ break;
+ }
+
+ return result;
+}
+
+
+/* ngetopt_otp_protocol - Handle the OTP (level) protocol options.
+ */
+static
+ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+ ERL_NIF_TERM result;
+ int val = descP->protocol;
+
+ switch (val) {
+ case IPPROTO_IP:
+ result = esock_make_ok2(env, esock_atom_ip);
+ break;
+
+ case IPPROTO_TCP:
+ result = esock_make_ok2(env, esock_atom_tcp);
+ break;
+
+ case IPPROTO_UDP:
+ result = esock_make_ok2(env, esock_atom_udp);
+ break;
+
+#if defined(HAVE_SCTP)
+ case IPPROTO_SCTP:
+ result = esock_make_ok2(env, esock_atom_sctp);
+ break;
+#endif
+
+ default:
+ result = esock_make_error(env,
+ MKT2(env, esock_atom_unknown, MKI(env, val)));
+ break;
+ }
+
+ return result;
+}
+
+
+
/* The option has *not* been encoded. Instead it has been provided
* in "native mode" (option is provided as is). In this case it will have the
* format: {NativeOpt :: integer(), ValueSize :: non_neg_integer()}
@@ -15279,7 +15419,7 @@ BOOLEAN_T extract_debug(ErlNifEnv* env,
*/
ERL_NIF_TERM debug = MKA(env, "debug");
- return esock_extract_bool_from_map(env, map, debug, SOCKET_NIF_DEBUG_DEFAULT);
+ return esock_extract_bool_from_map(env, map, debug, SOCKET_GLOBAL_DEBUG_DEFAULT);
}
static
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index a0550990e3..9c7bcf89b5 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 8093bad885..c388fc2849 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -652,6 +652,9 @@
%%-define(SOCKET_OPT_OTP_SNDBUF, 5).
-define(SOCKET_OPT_OTP_RCVCTRLBUF, 6).
-define(SOCKET_OPT_OTP_SNDCTRLBUF, 7).
+-define(SOCKET_OPT_OTP_DOMAIN, 16#FF01). % INTERNAL
+-define(SOCKET_OPT_OTP_TYPE, 16#FF02). % INTERNAL
+-define(SOCKET_OPT_OTP_PROTOCOL, 16#FF03). % INTERNAL
%% *** SOCKET (socket) options
-define(SOCKET_OPT_SOCK_ACCEPTCONN, 1).
@@ -2159,7 +2162,7 @@ getopt(#socket{ref = SockRef}, Level, Key) ->
which_domain(SockRef) ->
case nif_getopt(SockRef, true,
- ?SOCKET_OPT_LEVEL_SOCKET, ?SOCKET_OPT_SOCK_DOMAIN) of
+ ?SOCKET_OPT_LEVEL_OTP, ?SOCKET_OPT_OTP_DOMAIN) of
{ok, Domain} ->
Domain;
{error, _} = ERROR ->
@@ -2173,7 +2176,7 @@ which_domain(SockRef) ->
which_type(SockRef) ->
case nif_getopt(SockRef, true,
- ?SOCKET_OPT_LEVEL_SOCKET, ?SOCKET_OPT_SOCK_TYPE) of
+ ?SOCKET_OPT_LEVEL_OTP, ?SOCKET_OPT_OTP_TYPE) of
{ok, Type} ->
Type;
{error, _} = ERROR ->
@@ -2186,9 +2189,9 @@ which_type(SockRef) ->
which_protocol(SockRef) ->
case nif_getopt(SockRef, true,
- ?SOCKET_OPT_LEVEL_SOCKET, ?SOCKET_OPT_SOCK_PROTOCOL) of
- {ok, Type} ->
- Type;
+ ?SOCKET_OPT_LEVEL_OTP, ?SOCKET_OPT_OTP_PROTOCOL) of
+ {ok, Proto} ->
+ Proto;
{error, _} = ERROR ->
throw(ERROR)
end.