WIP: unix_msg: add fds array to unix_msg_send()/unix_dmg_msg_send() for fd-passing master-smb2
authorMichael Adam <obnox@samba.org>
Sat, 10 May 2014 15:57:10 +0000 (17:57 +0200)
committerMichael Adam <obnox@samba.org>
Sat, 10 May 2014 15:57:10 +0000 (17:57 +0200)
Signed-off-by: Michael Adam <obnox@samba.org>
source3/lib/messages_dgm.c
source3/lib/unix_msg/test_source.c
source3/lib/unix_msg/tests.c
source3/lib/unix_msg/unix_msg.c
source3/lib/unix_msg/unix_msg.h

index 55a6fcfac21a7e53cb860e1f7da144394a5da541..1b4b29229e365653efa4671dff8492da6546aa2a 100644 (file)
@@ -324,7 +324,8 @@ static NTSTATUS messaging_dgm_send(struct messaging_context *msg_ctx,
        iov[1].iov_len = data->length;
 
        become_root();
-       ret = unix_msg_send(ctx->dgm_ctx, dst_sock, iov, ARRAY_SIZE(iov));
+       ret = unix_msg_send(ctx->dgm_ctx, dst_sock, iov, ARRAY_SIZE(iov),
+                           NULL, 0);
        unbecome_root();
 
        TALLOC_FREE(to_free);
index 94984d88523ba31bc9679fac85eb6d248ac76282..cba6850094c7058825a087bcdfd84eaf89bcf124 100644 (file)
@@ -61,7 +61,7 @@ int main(int argc, const char *argv[])
                unsigned j;
 
                for (j=0; j<100000; j++) {
-                       ret = unix_msg_send(ctxs[i], argv[1], &iov, 1);
+                       ret = unix_msg_send(ctxs[i], argv[1], &iov, 1, NULL, 0);
                        if (ret != 0) {
                                fprintf(stderr, "unix_msg_send failed: %s\n",
                                        strerror(ret));
index 29d5dcb374596a572245cb984c31b08b9a2ece44..e4774e00a1819884d321483f9580b5a6d5b7d5e6 100644 (file)
@@ -98,7 +98,7 @@ int main(void)
        state.buf = NULL;
        state.buflen = 0;
 
-       ret = unix_msg_send(ctx1, sock2, NULL, 0);
+       ret = unix_msg_send(ctx1, sock2, NULL, 0, NULL, 0);
        if (ret != 0) {
                fprintf(stderr, "unix_msg_send failed: %s\n",
                        strerror(ret));
@@ -115,7 +115,7 @@ int main(void)
        state.buf = &msg;
        state.buflen = sizeof(msg);
 
-       ret = unix_msg_send(ctx1, sock2, &iov, 1);
+       ret = unix_msg_send(ctx1, sock2, &iov, 1, NULL, 0);
        if (ret != 0) {
                fprintf(stderr, "unix_msg_send failed: %s\n",
                        strerror(ret));
@@ -136,13 +136,13 @@ int main(void)
        state.buflen = sizeof(buf);
 
        for (i=0; i<3; i++) {
-               ret = unix_msg_send(ctx1, sock2, &iov, 1);
+               ret = unix_msg_send(ctx1, sock2, &iov, 1, NULL, 0);
                if (ret != 0) {
                        fprintf(stderr, "unix_msg_send failed: %s\n",
                                strerror(ret));
                        return 1;
                }
-               ret = unix_msg_send(ctx2, sock2, &iov, 1);
+               ret = unix_msg_send(ctx2, sock2, &iov, 1, NULL, 0);
                if (ret != 0) {
                        fprintf(stderr, "unix_msg_send failed: %s\n",
                                strerror(ret));
@@ -181,7 +181,7 @@ int main(void)
                        j++;
                }
 
-               ret = unix_msg_send(ctx1, sock1, iovs, j);
+               ret = unix_msg_send(ctx1, sock1, iovs, j, NULL, 0);
                if (ret != 0) {
                        fprintf(stderr, "unix_msg_send failed: %s\n",
                                strerror(ret));
@@ -194,13 +194,13 @@ int main(void)
        printf("Filling send queues before freeing\n");
 
        for (i=0; i<5; i++) {
-               ret = unix_msg_send(ctx1, sock2, &iov, 1);
+               ret = unix_msg_send(ctx1, sock2, &iov, 1, NULL, 0);
                if (ret != 0) {
                        fprintf(stderr, "unix_msg_send failed: %s\n",
                                strerror(ret));
                        return 1;
                }
-               ret = unix_msg_send(ctx1, sock1, &iov, 1);
+               ret = unix_msg_send(ctx1, sock1, &iov, 1, NULL, 0);
                if (ret != 0) {
                        fprintf(stderr, "unix_msg_send failed: %s\n",
                                strerror(ret));
index ae8ee505513d1408b2a9028994a40d05335906c1..31fb3f80a0bffebc8fdcd3ec599c91bf7fd2880f 100644 (file)
@@ -461,15 +461,24 @@ static void unix_dgram_job_finished(struct poll_watch *w, int fd, short events,
        unix_dgram_send_queue_free(q);
 }
 
+#define MAX_FDS 256
+
 static int unix_dgram_send(struct unix_dgram_ctx *ctx, const char *dst_sock,
-                          const struct iovec *iov, int iovlen)
+                          const struct iovec *iov, int iovlen,
+                          int *fds, size_t num_fds)
 {
        struct unix_dgram_send_queue *q;
        struct sockaddr_un addr = { 0, };
        struct msghdr msg;
+       struct cmsghdr *cmsg;
+       char buf[CMSG_SPACE(sizeof(int)*MAX_FDS)]; // TODO: talloc?
        size_t dst_len;
        int ret;
 
+       if (num_fds > MAX_FDS) {
+               return EINVAL;
+       }
+
        dst_len = strlen(dst_sock);
        if (dst_len >= sizeof(addr.sun_path)) {
                return ENAMETOOLONG;
@@ -498,6 +507,18 @@ static int unix_dgram_send(struct unix_dgram_ctx *ctx, const char *dst_sock,
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
        msg.msg_flags = 0;
+       if (num_fds > 0) {
+               int *fdptr;
+               msg.msg_control = buf;
+               msg.msg_controllen = sizeof(int) * num_fds;
+               cmsg = CMSG_FIRSTHDR(&msg);
+               cmsg->cmsg_level = SOL_SOCKET;
+               cmsg->cmsg_type = SCM_RIGHTS;
+               cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
+               fdptr = (int *)CMSG_DATA(cmsg);
+               memcpy(fdptr,  *fds, sizeof(int) * num_fds);
+               msg.msg_controllen = cmsg->cmsg_len;
+       }
 
        ret = sendmsg(ctx->sock, &msg, 0);
        if (ret >= 0) {
@@ -640,7 +661,8 @@ int unix_msg_init(const char *path, const struct poll_funcs *ev_funcs,
 }
 
 int unix_msg_send(struct unix_msg_ctx *ctx, const char *dst_sock,
-                 const struct iovec *iov, int iovlen)
+                 const struct iovec *iov, int iovlen,
+                 int *fds, size_t num_fds)
 {
        ssize_t msglen;
        size_t sent;
@@ -671,7 +693,7 @@ int unix_msg_send(struct unix_msg_ctx *ctx, const char *dst_sock,
                }
 
                return unix_dgram_send(ctx->dgram, dst_sock, tmp_iov,
-                                      iovlen+1);
+                                      iovlen+1, fds, num_fds);
        }
 
        hdr.msglen = msglen;
@@ -730,7 +752,8 @@ int unix_msg_send(struct unix_msg_ctx *ctx, const char *dst_sock,
                sent += (fragment_len - sizeof(ctx->cookie) - sizeof(hdr));
 
                ret = unix_dgram_send(ctx->dgram, dst_sock,
-                                     iov_copy, iov_index);
+                                     iov_copy, iov_index,
+                                     fds, num_fds);
                if (ret != 0) {
                        break;
                }
index fc636d8b702b8adc2c7001ddd264462da9059adc..f24cacc09f7be79a7092556a142bf373d64b8e01 100644 (file)
@@ -94,7 +94,8 @@ int unix_msg_init(const char *path, const struct poll_funcs *ev_funcs,
  */
 
 int unix_msg_send(struct unix_msg_ctx *ctx, const char *dst_sock,
-                 const struct iovec *iov, int iovlen);
+                 const struct iovec *iov, int iovlen,
+                 int *fds, size_t num_fds);
 
 /**
  * @brief Free a unix_msg_ctx