From ee2eadd1c61d4237ee4044260665c82edf559228 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 3 Aug 2018 18:55:30 +0200 Subject: [socket-nif] Add support for (recvmsg) control message ipv6_pktinfo Added support for (recvmsg) control message ipv6_pktinfo, for level = ipv6 and type = pktinfo. This is enabled by setting the socket option: recvpktinfo for level ipv6. Not yet tested! OTP-14831 --- erts/doc/src/socket_usage.xml | 18 +++--- erts/emulator/nifs/common/socket_nif.c | 99 +++++++++++++++++++++++++++++---- erts/preloaded/ebin/socket.beam | Bin 64540 -> 64588 bytes erts/preloaded/src/socket.erl | 7 +++ 4 files changed, 103 insertions(+), 21 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index b7459e97fa..9785830637 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -51,7 +51,7 @@ Value Type Set Get - Other + Other Requirements and comments assoc_id @@ -90,7 +90,7 @@ Value Type Set Get - Other + Other Requirements and comments acceptcon @@ -118,7 +118,7 @@ integer() yes yes - require admin capability + requires admin capability domain @@ -255,7 +255,7 @@ Value Type Set Get - Other + Other Requirements and comments add_membership @@ -451,7 +451,7 @@ boolean() yes yes - require admin capability + requires admin capability ttl @@ -476,7 +476,7 @@ Value Type Set Get - Other + Other Requirements and comments addrform @@ -621,7 +621,7 @@ Value Type Set Get - Other + Other Requirements and comments congestion @@ -653,7 +653,7 @@ Value Type Set Get - Other + Other Requirements and comments cork @@ -671,7 +671,7 @@ Value Type Set Get - Other + Other Requirements and comments associnfo diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 90b727eff7..f7e59678bb 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -1960,6 +1960,15 @@ static char* encode_cmsghdr_data_ip(ErlNifEnv* env, size_t dataPos, size_t dataLen, ERL_NIF_TERM* eCMsgHdrData); +#if defined(SOL_IPV6) +static char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, + ERL_NIF_TERM ctrlBuf, + int type, + unsigned char* dataP, + size_t dataPos, + size_t dataLen, + ERL_NIF_TERM* eCMsgHdrData); +#endif extern char* encode_msghdr_flags(ErlNifEnv* env, SocketDescriptor* descP, int msgFlags, @@ -11419,19 +11428,19 @@ char* encode_cmsghdr_type(ErlNifEnv* env, *eType = esock_atom_tos; break; #endif - + #if defined(IP_TTL) case IP_TTL: *eType = esock_atom_ttl; break; #endif - + #if defined(IP_PKTINFO) case IP_PKTINFO: *eType = esock_atom_pktinfo; break; #endif - + #if defined(IP_ORIGDSTADDR) case IP_ORIGDSTADDR: *eType = esock_atom_origdstaddr; @@ -11443,17 +11452,23 @@ char* encode_cmsghdr_type(ErlNifEnv* env, break; } break; - + #if defined(SOL_IPV6) case SOL_IPV6: switch (type) { +#if defined(IPV6_PKTINFO) + case IPV6_PKTINFO: + *eType = esock_atom_pktinfo; + break; +#endif + default: xres = ESOCK_STR_EINVAL; break; } break; #endif - + case IPPROTO_TCP: switch (type) { default: @@ -11634,13 +11649,13 @@ char* encode_cmsghdr_data(ErlNifEnv* env, eCMsgHdrData); break; - /* - #if defined(SOL_IPV6) - case SOL_IPV6: - xres = encode_cmsghdr_data_ipv6(env, type, dataP, eCMsgHdrData); - break; - #endif - */ +#if defined(SOL_IPV6) + case SOL_IPV6: + xres = encode_cmsghdr_data_ipv6(env, ctrlBuf, type, + dataP, dataPos, dataLen, + eCMsgHdrData); + break; +#endif /* case IPPROTO_TCP: @@ -11827,6 +11842,66 @@ char* encode_cmsghdr_data_ip(ErlNifEnv* env, +/* +++ encode_cmsghdr_data_ipv6 +++ + * + * Encode the data part when protocol = IPv6 of the cmsghdr(). + * + */ +#if defined(SOL_IPV6) +static +char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, + ERL_NIF_TERM ctrlBuf, + int type, + unsigned char* dataP, + size_t dataPos, + size_t dataLen, + ERL_NIF_TERM* eCMsgHdrData) +{ + char* xres; + + switch (type) { +#if defined(IPV6_PKTINFO) + case IPV6_PKTINFO: + { + struct in6_pktinfo* pktInfoP = (struct in6_pktinfo*) dataP; + ERL_NIF_TERM ifIndex = MKI(env, pktInfoP->ipi6_ifindex); + ERL_NIF_TERM addr; + + if ((xres = esock_encode_ip6_address(env, + &pktInfoP->ipi6_addr, + &addr)) != NULL) { + *eCMsgHdrData = esock_atom_undefined; + return xres; + } + + { + ERL_NIF_TERM keys[] = {esock_atom_addr, esock_atom_ifindex}; + ERL_NIF_TERM vals[] = {addr, ifIndex}; + unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM); + unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM); + + ESOCK_ASSERT( (numKeys == numVals) ); + + if (!MKMA(env, keys, vals, numKeys, eCMsgHdrData)) { + *eCMsgHdrData = esock_atom_undefined; + return ESOCK_STR_EINVAL; + } + } + } + break; +#endif + + default: + *eCMsgHdrData = MKSBIN(env, ctrlBuf, dataPos, dataLen); + break; + } + + return NULL; +} +#endif + + + /* +++ encode_msghdr_flags +++ * * Encode a list of msghdr_flag(). diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 125191c1d0..5b14af3ad8 100644 Binary files a/erts/preloaded/ebin/socket.beam and b/erts/preloaded/ebin/socket.beam differ diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 3d65f52a2b..8af052e149 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -228,6 +228,12 @@ -type ipv6_pmtudisc() :: ip_pmtudisc(). +-type ipv6_pktinfo() :: #{ + addr := ip6_address(), + ifindex := integer() + }. + + -type sctp_assoc_id() :: int32(). -type sctp_sndrcvinfo() :: #{ stream := uint16(), @@ -560,6 +566,7 @@ integer(). -type cmsghdr_data() :: timeval() | % if level = socket and type = timstamp ip_pktinfo() | % if level = ip and type = pktinfo + ipv6_pktinfo() | % if level = ipv6 and type = pktinfo ip_tos() | % if level = ip and type = tos integer() | % if level = ip and type = ttl sockaddr_in4() | % if level = ip and type = origdstaddr -- cgit v1.2.3