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