aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/nifs/common/socket_util.c
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-07-31 18:01:55 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commit25c38eff5c1e8d4dc6325afa62031874e23262dc (patch)
tree699fb4b7d0bb2615398ee3f674e005a835066fd4 /erts/emulator/nifs/common/socket_util.c
parentd4c6b555aea77198d662822c7f5a134a16cff8af (diff)
downloadotp-25c38eff5c1e8d4dc6325afa62031874e23262dc.tar.gz
otp-25c38eff5c1e8d4dc6325afa62031874e23262dc.tar.bz2
otp-25c38eff5c1e8d4dc6325afa62031874e23262dc.zip
[socket-nif] Add more control message decoding
Added decoding of the "known" control message options: pktinfo, recvtos, recvttl and recvorigdstaddr). OTP-14831
Diffstat (limited to 'erts/emulator/nifs/common/socket_util.c')
-rw-r--r--erts/emulator/nifs/common/socket_util.c259
1 files changed, 3 insertions, 256 deletions
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 50cc94c263..232e8200df 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -31,7 +31,6 @@
#include <stddef.h>
#include "socket_int.h"
-#include "socket_tarray.h"
#include "socket_util.h"
#include "socket_dbg.h"
#include "sys.h"
@@ -40,7 +39,7 @@
* should use the compile debug flag, whatever that is...
*/
-#define COMPILE_DEBUG_FLAG_WE_NEED_TO_CHECK 1
+// #define COMPILE_DEBUG_FLAG_WE_NEED_TO_CHECK 1
#if defined(COMPILE_DEBUG_FLAG_WE_NEED_TO_CHECK)
#define UTIL_DEBUG TRUE
#else
@@ -70,96 +69,6 @@ static char* make_sockaddr_un(ErlNifEnv* env,
ERL_NIF_TERM* sa);
-/* +++ esock_encode_msghdr +++
- *
- * Encode a msghdr (recvmsg). In erlang its represented as
- * a map, which has a specific set of attributes:
- *
- * addr (source address) - sockaddr()
- * iov - [binary()]
- * ctrl - [cmsghdr()]
- * flags - msghdr_flags()
- */
-
-extern
-char* esock_encode_msghdr(ErlNifEnv* env,
- int read,
- struct msghdr* msgHdrP,
- ErlNifBinary* dataBufP,
- ErlNifBinary* ctrlBufP,
- ERL_NIF_TERM* eSockAddr)
-{
- char* xres;
- ERL_NIF_TERM addr, iov, ctrl, flags;
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> entry with"
- "\r\n read: %d"
- "\r\n", read) );
-
- if ((xres = esock_encode_sockaddr(env,
- (SocketAddress*) msgHdrP->msg_name,
- msgHdrP->msg_namelen,
- &addr)) != NULL)
- return xres;
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> try encode iov\r\n") );
- if ((xres = esock_encode_iov(env,
- read,
- msgHdrP->msg_iov,
- msgHdrP->msg_iovlen,
- dataBufP,
- &iov)) != NULL)
- return xres;
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> try encode cmsghdrs\r\n") );
- if ((xres = esock_encode_cmsghdrs(env,
- ctrlBufP,
- msgHdrP,
- &ctrl)) != NULL)
- return xres;
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> try encode flags\r\n") );
- if ((xres = esock_encode_mshghdr_flags(env,
- msgHdrP->msg_flags,
- &flags)) != NULL)
- return xres;
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> components encoded:"
- "\r\n addr: %T"
- "\r\n iov: %T"
- "\r\n ctrl: %T"
- "\r\n flags: %T"
- "\r\n", addr, iov, ctrl, flags) );
- {
- ERL_NIF_TERM keys[] = {esock_atom_addr,
- esock_atom_iov,
- esock_atom_ctrl,
- esock_atom_flags};
- ERL_NIF_TERM vals[] = {addr, iov, ctrl, flags};
- unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM);
- unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM);
- ERL_NIF_TERM tmp;
-
- ESOCK_ASSERT( (numKeys == numVals) );
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> create msghdr map\r\n") );
- if (!MKMA(env, keys, vals, numKeys, &tmp))
- return ESOCK_STR_EINVAL;
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> msghdr: "
- "\r\n %T"
- "\r\n", tmp) );
-
- *eSockAddr = tmp;
- }
-
- UDBG( ("SUTIL", "esock_encode_msghdr -> done\r\n") );
-
- return NULL;
-}
-
-
-
/* +++ esock_encode_iov +++
*
* Encode a IO Vector. In erlang we represented this as a list of binaries.
@@ -203,23 +112,20 @@ char* esock_encode_iov(ErlNifEnv* env,
/* We have the exact amount - we are done */
UDBG( ("SUTIL", "esock_encode_iov -> exact => done\r\n") );
a[i] = MKBIN(env, &data[i]);
- UDBG( ("SUTIL", "esock_encode_iov -> a[%d]: %T\r\n", i, a[i]) );
- rem = 0; // Besserwisser
+ rem = 0; // Besserwisser
done = TRUE;
} else if (iov[i].iov_len < rem) {
/* Filled another buffer - continue */
UDBG( ("SUTIL", "esock_encode_iov -> filled => continue\r\n") );
a[i] = MKBIN(env, &data[i]);
rem -= iov[i].iov_len;
- UDBG( ("SUTIL", "esock_encode_iov -> a[%d]: %T\r\n", i, a[i]) );
} else if (iov[i].iov_len > rem) {
/* Partly filled buffer (=> split) - we are done */
ERL_NIF_TERM tmp;
UDBG( ("SUTIL", "esock_encode_iov -> split => done\r\n") );
tmp = MKBIN(env, &data[i]);
a[i] = MKSBIN(env, tmp, 0, rem);
- UDBG( ("SUTIL", "esock_encode_iov -> a[%d]: %T\r\n", i, a[i]) );
- rem = 0; // Besserwisser
+ rem = 0; // Besserwisser
done = TRUE;
}
}
@@ -235,165 +141,6 @@ char* esock_encode_iov(ErlNifEnv* env,
-/* +++ esock_encode_cmsghdrs +++
- *
- * Encode a list of cmsghdr(). The X can 0 or more cmsghdr blocks.
- *
- * Our problem is that we have no idea how many control messages
- * we have.
- *
- * The cmsgHdrP arguments points to the start of the control data buffer,
- * an actual binary. Its the only way to create sub-binaries. So, what we
- * need to continue processing this is to tern that into an binary erlang
- * term (which can then in turn be turned into sub-binaries).
- *
- * We need the cmsgBufP (even though cmsgHdrP points to it) to be able
- * to create sub-binaries (one for each cmsg hdr).
- *
- * The TArray (term array) is created with the size of 128, which should
- * be enough. But if its not, then it will be automatically realloc'ed during
- * add. Once we are done adding hdr's to it, we convert the tarray to a list.
- */
-
-extern
-char* esock_encode_cmsghdrs(ErlNifEnv* env,
- ErlNifBinary* cmsgBinP,
- struct msghdr* msgHdrP,
- ERL_NIF_TERM* eCMsgHdr)
-{
- ERL_NIF_TERM ctrlBuf = MKBIN(env, cmsgBinP); // The *entire* binary
- SocketTArray cmsghdrs = TARRAY_CREATE(128);
- struct cmsghdr* firstP = CMSG_FIRSTHDR(msgHdrP);
- struct cmsghdr* currentP;
-
- UDBG( ("SUTIL", "esock_encode_cmsghdrs -> entry\r\n") );
-
- for (currentP = firstP;
- currentP != NULL;
- currentP = CMSG_NXTHDR(msgHdrP, currentP)) {
-
- UDBG( ("SUTIL", "esock_encode_cmsghdrs -> process cmsg header when"
- "\r\n TArray Size: %d"
- "\r\n", TARRAY_SZ(cmsghdrs)) );
-
- /* MUST check this since on Linux the returned "cmsg" may actually
- * go too far!
- */
- if (((CHARP(currentP) + currentP->cmsg_len) - CHARP(firstP)) >
- msgHdrP->msg_controllen) {
- /* Ouch, fatal error - give up
- * We assume we cannot trust any data if this is wrong.
- */
- TARRAY_DELETE(cmsghdrs);
- return ESOCK_STR_EINVAL;
- } else {
- ERL_NIF_TERM level;
- ERL_NIF_TERM type = MKI(env, currentP->cmsg_type);
- unsigned char* dataP = (unsigned char*) CMSG_DATA(currentP);
- size_t dataPos = dataP - cmsgBinP->data;
- size_t dataLen = currentP->cmsg_len - (CHARP(currentP)-CHARP(dataP));
- ERL_NIF_TERM dataBin = MKSBIN(env, ctrlBuf, dataPos, dataLen);
-
- /* We can't give up just because its an unknown protocol,
- * so if its a protocol we don't know, we return its integer
- * value and leave it to the user.
- */
- if (esock_encode_protocol(env, currentP->cmsg_level, &level) != NULL)
- level = MKI(env, currentP->cmsg_level);
-
- UDBG( ("SUTIL", "esock_encode_cmsghdrs -> "
- "\r\n level: %T"
- "\r\n type: %T"
- "\r\n", level, type) );
-
- /* And finally create the 'cmsghdr' map -
- * and if successfull add it to the tarray.
- */
- {
- ERL_NIF_TERM keys[] = {esock_atom_level,
- esock_atom_type,
- esock_atom_data};
- ERL_NIF_TERM vals[] = {level, type, dataBin};
- unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM);
- unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM);
- ERL_NIF_TERM cmsgHdr;
-
- /* Guard agains cut-and-paste errors */
- ESOCK_ASSERT( (numKeys == numVals) );
-
- if (!MKMA(env, keys, vals, numKeys, &cmsgHdr)) {
- TARRAY_DELETE(cmsghdrs);
- return ESOCK_STR_EINVAL;
- }
-
- /* And finally add it to the list... */
- TARRAY_ADD(cmsghdrs, cmsgHdr);
- }
- }
- }
-
- UDBG( ("SUTIL", "esock_encode_cmsghdrs -> cmsg headers processed when"
- "\r\n TArray Size: %d"
- "\r\n", TARRAY_SZ(cmsghdrs)) );
-
- /* The tarray is populated - convert it to a list */
- TARRAY_TOLIST(cmsghdrs, env, eCMsgHdr);
-
- return NULL;
-}
-
-
-
-/* +++ esock_encode_mshghdr_flags +++
- *
- * Encode a list of msghdr_flag().
- *
- * The following flags are handled: eor | trunc | ctrunc | oob | errqueue.
- */
-
-extern
-char* esock_encode_mshghdr_flags(ErlNifEnv* env,
- int msgFlags,
- ERL_NIF_TERM* flags)
-{
- UDBG( ("SUTIL", "esock_encode_cmsghdrs -> entry with"
- "\r\n msgFlags: %d (0x%lX)"
- "\r\n", msgFlags, msgFlags) );
-
- if (msgFlags == 0) {
- *flags = MKEL(env);
- return NULL;
- } else {
- SocketTArray ta = TARRAY_CREATE(10); // Just to be on the safe side
-
- if ((msgFlags & MSG_EOR) == MSG_EOR)
- TARRAY_ADD(ta, esock_atom_eor);
-
- if ((msgFlags & MSG_TRUNC) == MSG_TRUNC)
- TARRAY_ADD(ta, esock_atom_trunc);
-
- if ((msgFlags & MSG_CTRUNC) == MSG_CTRUNC)
- TARRAY_ADD(ta, esock_atom_ctrunc);
-
- if ((msgFlags & MSG_OOB) == MSG_OOB)
- TARRAY_ADD(ta, esock_atom_oob);
-
- if ((msgFlags & MSG_ERRQUEUE) == MSG_ERRQUEUE)
- TARRAY_ADD(ta, esock_atom_errqueue);
-
- UDBG( ("SUTIL", "esock_encode_cmsghdrs -> flags processed when"
- "\r\n TArray size: %d"
- "\r\n", TARRAY_SZ(ta)) );
-
- TARRAY_TOLIST(ta, env, flags);
-
- return NULL;
- }
-}
-
-
-
-
/* +++ esock_decode_sockaddr +++
*
* Decode a socket address - sockaddr. In erlang its represented as