summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2014-06-03 14:55:13 +0200
committerMichael Adam <obnox@samba.org>2014-06-05 23:57:09 +0200
commit56d5bf9af86dfac5431ec9c12096a4a28d337c05 (patch)
treee5aa6bb877804e12e8d6dd8a16fcab56bbd25210 /lib
parented3c219ec5cfd2c491296c753202275d46e488d4 (diff)
downloadsamba-56d5bf9af86dfac5431ec9c12096a4a28d337c05.tar.gz
swrap: Add swrap_msghdr_add_cmsghdr().
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Pair-Programmed-With: Michael Adam <obnox@samba.org> Signed-off-by: Andreas Schneider <asn@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org> Signed-off-by: Michael Adam <obnox@samba.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/socket_wrapper/socket_wrapper.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index e1b69fa94b1..d3824597810 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/socket_wrapper.c
@@ -2964,6 +2964,77 @@ int ioctl(int s, unsigned long int r, ...)
return rc;
}
+/*****************
+ * CMSG
+ *****************/
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+/**
+ * @brief Add a cmsghdr to a msghdr.
+ *
+ * This is an function to add any type of cmsghdr. It will operate on the
+ * msg->msg_control and msg->msg_controllen you pass in by adapting them to
+ * the buffer position after the added cmsg element. Hence, this function is
+ * intended to be used with an intermediate msghdr and not on the original
+ * one handed in by the client.
+ *
+ * @param[in] msg The msghdr to which to add the cmsg.
+ *
+ * @param[in] level The cmsg level to set.
+ *
+ * @param[in] type The cmsg type to set.
+ *
+ * @param[in] data The cmsg data to set.
+ *
+ * @param[in] len the length of the data to set.
+ */
+static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
+ int level,
+ int type,
+ const void *data,
+ size_t len)
+{
+ size_t cmlen = CMSG_LEN(len);
+ size_t cmspace = CMSG_SPACE(len);
+ uint8_t cmbuf[cmspace];
+ struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
+ uint8_t *p;
+
+ memset(cmbuf, 0, cmspace);
+
+ if (msg->msg_controllen < cmlen) {
+ cmlen = msg->msg_controllen;
+ msg->msg_flags |= MSG_CTRUNC;
+ }
+
+ if (msg->msg_controllen < cmspace) {
+ cmspace = msg->msg_controllen;
+ }
+
+ /*
+ * We copy the full input data into an intermediate cmsghdr first
+ * in order to more easily cope with truncation.
+ */
+ cm->cmsg_len = cmlen;
+ cm->cmsg_level = level;
+ cm->cmsg_type = type;
+ memcpy(CMSG_DATA(cm), data, len);
+
+ /*
+ * We now copy the possibly truncated buffer.
+ * We copy cmlen bytes, but consume cmspace bytes,
+ * leaving the possible padding uninitialiazed.
+ */
+ p = (uint8_t *)msg->msg_control;
+ memcpy(p, cm, cmlen);
+ p += cmspace;
+ msg->msg_control = p;
+ msg->msg_controllen -= cmspace;
+
+ return;
+}
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+
static ssize_t swrap_sendmsg_before(int fd,
struct socket_info *si,
struct msghdr *msg,