aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/socket_usage.xml11
-rw-r--r--erts/emulator/nifs/common/socket_nif.c59
-rw-r--r--erts/preloaded/ebin/socket.beambin59660 -> 59768 bytes
-rw-r--r--erts/preloaded/src/socket.erl9
-rw-r--r--lib/kernel/test/socket_server.erl12
5 files changed, 84 insertions, 7 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml
index f69aa75820..933341bd35 100644
--- a/erts/doc/src/socket_usage.xml
+++ b/erts/doc/src/socket_usage.xml
@@ -35,6 +35,10 @@
<p>The socket interface (module) is basically an "thin" layer on top of
the OS socket interface. It is assumed that, unless you have special needs,
gen_[tcp|udp|sctp] should be sufficent. </p>
+ <p>Note that just because we have a documented and described option,
+ it does <em>not</em> mean that the OS supports it. So its recommended
+ that the user reads the platform specific documentation for the
+ option used. </p>
</section>
<section>
@@ -429,6 +433,13 @@
<cell>type = raw</cell>
</row>
<row>
+ <cell>sendsrcaddr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
<cell>tos</cell>
<cell>ip_tos()</cell>
<cell>yes</cell>
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 4ba94f4f60..13250349db 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -540,6 +540,7 @@ typedef union {
#define SOCKET_OPT_IP_RECVTTL 26
#define SOCKET_OPT_IP_RETOPTS 27
#define SOCKET_OPT_IP_ROUTER_ALERT 28
+#define SOCKET_OPT_IP_SENDSRCADDR 29 // Same as IP_RECVDSTADDR?
#define SOCKET_OPT_IP_TOS 30
#define SOCKET_OPT_IP_TRANSPARENT 31
#define SOCKET_OPT_IP_TTL 32
@@ -1218,6 +1219,11 @@ static ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
SocketDescriptor* descP,
ERL_NIF_TERM eVal);
#endif
+#if defined(IP_SENDSRCADDR)
+static ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal);
+#endif
#if defined(IP_TOS)
static ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
SocketDescriptor* descP,
@@ -1640,6 +1646,10 @@ static ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
static ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
SocketDescriptor* descP);
#endif
+#if defined(IP_SENDSRCADDR)
+static ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ SocketDescriptor* descP);
+#endif
#if defined(IP_TOS)
static ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
SocketDescriptor* descP);
@@ -5125,6 +5135,12 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
break;
#endif
+#if defined(IP_SENDSRCADDR)
+ case SOCKET_OPT_IP_SENDSRCADDR:
+ result = nsetopt_lvl_ip_sendsrcaddr(env, descP, eVal);
+ break;
+#endif
+
#if defined(IP_TOS)
case SOCKET_OPT_IP_TOS:
result = nsetopt_lvl_ip_tos(env, descP, eVal);
@@ -5808,6 +5824,25 @@ ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
#endif
+/* nsetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option
+ */
+#if defined(IP_SENDSRCADDR)
+static
+ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ SocketDescriptor* descP,
+ ERL_NIF_TERM eVal)
+{
+#if defined(SOL_IP)
+ int level = SOL_IP;
+#else
+ int level = IPPROTO_IP;
+#endif
+
+ return nsetopt_bool_opt(env, descP, level, IP_SENDSRCADDR, eVal);
+}
+#endif
+
+
/* nsetopt_lvl_ip_tos - Level IP TOS option
*/
#if defined(IP_TOS)
@@ -8418,6 +8453,12 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
break;
#endif
+#if defined(IP_SENDSRCADDR)
+ case SOCKET_OPT_IP_SENDSRCADDR:
+ result = ngetopt_lvl_ip_sendsrcaddr(env, descP);
+ break;
+#endif
+
#if defined(IP_TOS)
case SOCKET_OPT_IP_TOS:
result = ngetopt_lvl_ip_tos(env, descP);
@@ -8846,6 +8887,24 @@ ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
#endif
+/* ngetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option
+ */
+#if defined(IP_SENDSRCADDR)
+static
+ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ SocketDescriptor* descP)
+{
+#if defined(SOL_IP)
+ int level = SOL_IP;
+#else
+ int level = IPPROTO_IP;
+#endif
+
+ return ngetopt_bool_opt(env, descP, level, IP_SENDSRCADDR);
+}
+#endif
+
+
/* ngetopt_lvl_ip_tos - Level IP TOS option
*/
#if defined(IP_TOS)
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index 90cb657178..b2bd8f2728 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 68b7d3f4b0..1983c993a5 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -638,11 +638,11 @@
-define(SOCKET_OPT_IP_RECVTTL, 26).
-define(SOCKET_OPT_IP_RETOPTS, 27).
-define(SOCKET_OPT_IP_ROUTER_ALERT, 28).
-%% -define(SOCKET_OPT_IP_SNDSRCADDR, 29).
+-define(SOCKET_OPT_IP_SENDSRCADDR, 29). % FreeBSD
-define(SOCKET_OPT_IP_TOS, 30).
-define(SOCKET_OPT_IP_TRANSPARENT, 31).
-define(SOCKET_OPT_IP_TTL, 32).
--define(SOCKET_OPT_IP_UNBLOCK_SOURCE, 33).
+-define(SOCKET_OPT_IP_UNBLOCK_SOURCE, 33).
-define(SOCKET_OPT_IPV6_ADDRFORM, 1).
-define(SOCKET_OPT_IPV6_ADD_MEMBERSHIP, 2).
@@ -2316,6 +2316,9 @@ enc_setopt_value(ip, retopts, V, _D, _T, _P)
enc_setopt_value(ip, router_alert, V, _D, _T, _P)
when is_integer(V) ->
V;
+enc_setopt_value(ip, sendsrcaddr, V, _D, _T, _P)
+ when is_boolean(V) ->
+ V;
enc_setopt_value(ip, tos, V, _D, _T, _P)
when (V =:= lowdelay) orelse
(V =:= throughput) orelse
@@ -2776,6 +2779,8 @@ enc_sockopt_key(ip = _L, retopts = _Opt, _Dir, _D, T, _P) when (T =/= stream) ->
?SOCKET_OPT_IP_RETOPTS;
enc_sockopt_key(ip, router_alert = _Opt, _Dir, _D, raw = _T, _P) ->
?SOCKET_OPT_IP_ROUTER_ALERT;
+enc_sockopt_key(ip, sendsrcaddr = _Opt, _Dir, _D, _T, _P) ->
+ ?SOCKET_OPT_IP_SENDSRCADDR;
%% On FreeBSD it specifies that this option is only valid
%% for stream, dgram and "some" raw sockets...
%% No such condition on linux (in the man page)...
diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl
index 3dad94b751..88b63ecf2d 100644
--- a/lib/kernel/test/socket_server.erl
+++ b/lib/kernel/test/socket_server.erl
@@ -644,6 +644,7 @@ handler_init(Manager, ID, Peek, Sock) ->
RecvTOS = GIP4(recvtos),
RecvTTL = GIP4(recvttl), % not stream
RetOpts = GIP4(retopts), % not stream
+ SendSrcAddr = GIP4(sendsrcaddr),
TOS = GIP4(tos),
Transparent = GIP4(transparent),
TTL = GIP4(ttl),
@@ -691,6 +692,7 @@ handler_init(Manager, ID, Peek, Sock) ->
"~n (ip) Recv TOS: ~s"
"~n (ip) Recv TTL: ~s"
"~n (ip) Ret Opts: ~s"
+ "~n (ip) Send Src Addr: ~s"
"~n (ip) TOS: ~s"
"~n (ip) Transparent: ~s"
"~n (ip) TTL: ~s"
@@ -713,7 +715,7 @@ handler_init(Manager, ID, Peek, Sock) ->
FreeBind, MTU, MTUDisc, MALL, MIF4, MLoop4, MTTL,
NF, PktInfo,RecvErr4,
RecvIF, RecvOPTS, RecvOrigDstAddr, RecvTOS, RecvTTL, RetOpts,
- TOS, Transparent, TTL,
+ SendSrcAddr, TOS, Transparent, TTL,
MHops, MIF6, MLoop6, RecvErr6, RecvPktInfo,
RtHdr, AuthHdr, HopLimit, HopOpts, DstOpts, FlowInfo,
UHops]),
@@ -724,14 +726,14 @@ handler_init(Manager, ID, Peek, Sock) ->
socket = Sock})
end.
-so(Sock, Lvl, Opt, Val) ->
- ok = socket:setopt(Sock, Lvl, Opt, Val).
+%% so(Sock, Lvl, Opt, Val) ->
+%% ok = socket:setopt(Sock, Lvl, Opt, Val).
%% soso(Sock, Opt, Val) ->
%% so(Sock, socket, Opt, Val).
-soip(Sock, Opt, Val) ->
- so(Sock, ip, Opt, Val).
+%% soip(Sock, Opt, Val) ->
+%% so(Sock, ip, Opt, Val).
%% soipv6(Sock, Opt, Val) ->
%% so(Sock, ipv6, Opt, Val).