From 64853dc28ce838583e35d5fefb0604933b6e98f9 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 6 Jul 2018 12:55:10 +0200
Subject: Implement socket option recvtos and friends
Implement socket options recvtclass, recvtos, recvttl and pktoptions.
Document the implemented socket options, new types and message formats.
The options recvtclass, recvtos and recvttl are boolean options that
when activated (true) for a socket will cause ancillary data to be
received through recvmsg(). That is for packet oriented sockets
(UDP and SCTP).
The required options for this feature were recvtclass and recvtos,
and recvttl was only added to test that the ancillary data parsing
handled multiple data items in one message correctly.
These options does not work on Windows since ancillary data
is not handled by the Winsock2 API.
For stream sockets (TCP) there is no clear connection between
a received packet and what is returned when reading data from
the socket, so recvmsg() is not useful. It is possible to get
the same ancillary data through a getsockopt() call with
the IPv6 socket option IPV6_PKTOPTIONS, on Linux named
IPV6_2292PKTOPTIONS after the now obsoleted RFC where it originated.
(unfortunately RFC 3542 that obsoletes it explicitly undefines
this way to get packet ancillary data from a stream socket)
Linux also has got a way to get packet ancillary data for IPv4
TCP sockets through a getsockopt() call with IP_PKTOPTIONS,
which appears to be Linux specific.
This implementation uses a flag field in the inet_drv.c socket
internal data that records if any setsockopt() call with recvtclass,
recvtos or recvttl (IPV6_RECVTCLASS, IP_RECVTOS or IP_RECVTTL)
has been activated. If so recvmsg() is used instead of recvfrom().
Ancillary data is delivered to the application by a new return
tuple format from gen_udp:recv/2,3 containing a list of
ancillary data tuples [{tclass,TCLASS} | {tos,TOS} | {ttl,TTL}],
as returned by recvmsg(). For a socket in active mode a new
message format, containing the ancillary data list, delivers
the data in the same way.
For gen_sctp the ancillary data is delivered in the same way,
except that the gen_sctp return tuple format already contained
an ancillary data list so there are just more possible elements
when using these socket options. Note that the active mode
message format has got an extra tuple level for the ancillary
data compared to what is now implemented gen_udp.
The gen_sctp active mode format was considered to be the odd one
- now all tuples containing ancillary data are flat,
except for gen_sctp active mode.
Note that testing has not shown that Linux SCTP sockets deliver
any ancillary data for these socket options, so it is probably
not implemented yet. Remains to be seen what FreeBSD does...
For gen_tcp inet:getopts([pktoptions]) will deliver the latest
received ancillary data for any activated socket option recvtclass,
recvtos or recvttl, on platforms where IP_PKTOPTIONS is defined
for an IPv4 socket, or where IPV6_PKTOPTIONS or IPV6_2292PKTOPTIONS
is defined for an IPv6 socket. It will be delivered as a
list of ancillary data items in the same way as for gen_udp
(and gen_sctp).
On some platforms, e.g the BSD:s, when you activate IP_RECVTOS
you get ancillary data tagged IP_RECVTOS with the TOS value,
but on Linux you get ancillary data tagged IP_TOS with the
TOS value. Linux follows the style of RFC 2292, and the BSD:s
use an older notion. For RFC 2292 that defines the IP_PKTOPTIONS
socket option it is more logical to tag the items with the
tag that is the item's, than with the tag that defines that you
want the item. Therefore this implementation translates all
BSD style ancillary data tags to the corresponding Linux style
data tags, so the application will only see the tags 'tclass',
'tos' and 'ttl' on all platforms.
---
lib/kernel/doc/src/gen_sctp.xml | 69 ++++++++++++++++++++--
lib/kernel/doc/src/gen_tcp.xml | 16 +++++-
lib/kernel/doc/src/gen_udp.xml | 35 ++++++++++--
lib/kernel/doc/src/inet.xml | 123 +++++++++++++++++++++++++++++++++++++++-
4 files changed, 230 insertions(+), 13 deletions(-)
(limited to 'lib/kernel/doc/src')
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 737800c6b1..1e08b25f66 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -4,7 +4,7 @@
- 20072016
+ 20072018
Ericsson AB. All Rights Reserved.
@@ -331,6 +331,37 @@ connect(Socket, Ip, Port>,
with SockType seqpacket, and with reasonably large
kernel and driver
buffers.
+
+ If the socket is in
+ passive
+ mode data can be received through the
+ recv/1,2
+ calls.
+
+
+ If the socket is in
+ active
+ mode data received data is delivered to the controlling process
+ as messages:
+
+
+{sctp, Socket, FromIP, FromPort, {AncData, Data}}
+
+
+ See
+ recv/1,2
+ for a description of the message fields.
+
+
+
+ This message format unfortunately differs slightly from the
+ gen_udp
+ message format with ancillary data,
+ and from the
+ recv/1,2
+ return tuple format.
+
+
@@ -380,6 +411,19 @@ connect(Socket, Ip, Port>,
socket option
sctp_get_peer_addr_info,
but this does still not produce the stream number).
+
+ AncData may also contain
+
+ ancillary data
+
+ from the socket
+ options
+ recvtos,
+ recvtclass
+ or
+ recvttl,
+ if that is supported by the platform for the socket.
+
The Data received can be a binary()
or a list() of bytes (integers in the range 0 through 255)
depending on the socket mode, or an SCTP event.
@@ -544,12 +588,25 @@ connect(Socket, Ip, Port>,
recv call
to retrieve the available data from the socket.
+ -
+
+ If true|once|N (active modes)
+ received data or events are sent to the owning process.
+ See open/0..2
+ for the message format.
+
+
-
-
If true (full active mode), the pending data or events are
- sent to the owning process.
- Notice that this can cause the message queue to overflow,
- as there is no way to throttle the sender in this case
- (no flow control).
+
+ If true (full active mode) there is no flow control.
+
+
+
+ Note that this can cause the message queue to overflow
+ causing for example the virtual machine
+ to run out of memory and crash.
+
+
-
If once, only one message is automatically placed
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index e6104b0c76..cf649991d0 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -4,7 +4,7 @@
- 19972017
+ 19972018
Ericsson AB. All Rights Reserved.
@@ -69,6 +69,20 @@ do_recv(Sock, Bs) ->
+
+
+
+
+ If the platform implements the IPv4 option
+ IP_PKTOPTIONS (probably Linux specific), or the IPv6 option
+ IPV6_PKTOPTIONS or IPV6_2292PKTOPTIONS for the socket
+ this value is returned from
+ inet:getopts/2
+ when called with the option name
+ pktoptions.
+
+
+
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index f79566ef71..840ca3c188 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -4,7 +4,7 @@
- 19972016
+ 19972018
Ericsson AB. All Rights Reserved.
@@ -147,7 +147,21 @@
at the opened port, if the socket is in an active mode, the packets
are delivered as messages to the controlling process:
-{udp, Socket, IP, InPortNo, Packet}
+{udp, Socket, IP, InPortNo, Packet} % Without ancillary data
+{udp, Socket, IP, InPortNo, AncData, Packet} % With ancillary data
+
+
+ The message contains an AncData field
+ if any of the socket
+ options
+ recvtos,
+ recvtclass
+ or
+ recvttl
+ are active, otherwise it does not.
+
+
+
If the socket is not in an active mode, data can be
retrieved through the
recv/2,3 calls.
@@ -179,9 +193,22 @@
Receive a packet from a passive socket.
- Receives a packet from a socket in passive mode. Optional parameter
+
+ Receives a packet from a socket in passive mode. Optional parameter
Timeout specifies a time-out in milliseconds.
- Defaults to infinity.
+ Defaults to infinity.
+
+
+ If any of the socket
+ options
+ recvtos,
+ recvtclass
+ or
+ recvttl
+ are active, the RecvData tuple contains an
+ AncData field,
+ otherwise it does not.
+
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index f281d61459..ed775d67eb 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -176,6 +176,27 @@ fe80::204:acff:fe17:bf38
+
+
+
+
+ Ancillary data received with the data packet
+ or read with the socket option
+
+ pktoptions
+
+ from a TCP socket.
+
+
+ The value(s) correspond to the currently active socket
+ options
+ recvtos,
+ recvtclass
+ and
+ recvttl.
+
+
+
@@ -344,7 +365,11 @@ fe80::204:acff:fe17:bf38
Gets one or more options for a socket. For a list of available
options, see
- setopts/2.
+ setopts/2.
+ See also the description for the type
+
+ gen_tcp:pktoptions_value()
+ .
The number of elements in the returned
OptionValues
list does not necessarily correspond to the number of options
@@ -360,7 +385,7 @@ fe80::204:acff:fe17:bf38
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non-portable, but
allows the Erlang programmer to take advantage of unusual features
- present on the current platform.
+ present on a particular platform.
RawOptReq consists of tag raw followed
by the protocol level, the option number, and either a binary
or the size, in bytes, of the
@@ -1115,6 +1140,100 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp
the socket. You are encouraged to use
getopts/2
to retrieve the size set by your operating system.
+
+
+ {recvtclass, Boolean}
+ -
+
+ If set to true activates returning the received
+ TCLASS value on platforms that implements
+ the protocol IPPROTO_IPV6
+ option IPV6_RECVTCLASS or IPV6_2292RECVTCLASS
+ for the socket.
+ The value is returned as a {tclass,TCLASS} tuple
+ regardless of if the platform returns an IPV6_TCLASS
+ or an IPV6_RECVTCLASS CMSG value.
+
+
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (gen_udp and gen_sctp),
+ the TCLASS value is returned
+ in an extended return tuple contained in an
+
+ ancillary data
+
+ list.
+ For stream oriented sockets (gen_tcp)
+ the only way to get the TCLASS
+ value is if the platform supports the
+
+ pktoptions
+
+ option.
+
+
+
+ {recvtos, Boolean}
+ -
+
+ If set to true activates returning the received
+ TOS value on platforms that implements
+ the protocol IPPROTO_IP option IP_RECVTOS
+ for the socket.
+ The value is returned as a {tos,TOS} tuple
+ regardless of if the platform returns an IP_TOS
+ or an IP_RECVTOS CMSG value.
+
+
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (gen_udp and gen_sctp),
+ the TOS value is returned
+ in an extended return tuple contained in an
+
+ ancillary data
+
+ list.
+ For stream oriented sockets (gen_tcp)
+ the only way to get the TOS
+ value is if the platform supports the
+
+ pktoptions
+
+ option.
+
+
+
+ {recvttl, Boolean}
+ -
+
+ If set to true activates returning the received
+ TTL value on platforms that implements
+ the protocol IPPROTO_IP option IP_RECVTTL
+ for the socket.
+ The value is returned as a {ttl,TTL} tuple
+ regardless of if the platform returns an IP_TTL
+ or an IP_RECVTTL CMSG value.
+
+
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (gen_udp and gen_sctp),
+ the TTL value is returned
+ in an extended return tuple contained in an
+
+ ancillary data
+
+ list.
+ For stream oriented sockets (gen_tcp)
+ the only way to get the TTL
+ value is if the platform supports the
+
+ pktoptions
+
+ option.
+
{reuseaddr, Boolean}
-
--
cgit v1.2.3