136da5199SPawel Jakub Dawidek /*- 25e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 35e53a4f9SPedro F. Giffuni * 436da5199SPawel Jakub Dawidek * Copyright (c) 2013 The FreeBSD Foundation 536da5199SPawel Jakub Dawidek * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org> 636da5199SPawel Jakub Dawidek * All rights reserved. 736da5199SPawel Jakub Dawidek * 836da5199SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 936da5199SPawel Jakub Dawidek * the FreeBSD Foundation. 1036da5199SPawel Jakub Dawidek * 1136da5199SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 1236da5199SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 1336da5199SPawel Jakub Dawidek * are met: 1436da5199SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 1536da5199SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 1636da5199SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 1736da5199SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 1836da5199SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 1936da5199SPawel Jakub Dawidek * 2036da5199SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 2136da5199SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2236da5199SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2336da5199SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2436da5199SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2536da5199SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2636da5199SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2736da5199SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2836da5199SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2936da5199SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3036da5199SPawel Jakub Dawidek * SUCH DAMAGE. 3136da5199SPawel Jakub Dawidek */ 3236da5199SPawel Jakub Dawidek 3336da5199SPawel Jakub Dawidek #include <sys/cdefs.h> 3436da5199SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 3536da5199SPawel Jakub Dawidek 36586c5854SPawel Jakub Dawidek #include <sys/param.h> 3736da5199SPawel Jakub Dawidek #include <sys/socket.h> 38*3810ba1bSMariusz Zaborski #include <sys/select.h> 3936da5199SPawel Jakub Dawidek 4036da5199SPawel Jakub Dawidek #include <errno.h> 4136da5199SPawel Jakub Dawidek #include <fcntl.h> 4236da5199SPawel Jakub Dawidek #include <stdbool.h> 4336da5199SPawel Jakub Dawidek #include <stdint.h> 4436da5199SPawel Jakub Dawidek #include <stdlib.h> 4536da5199SPawel Jakub Dawidek #include <string.h> 4636da5199SPawel Jakub Dawidek #include <unistd.h> 4736da5199SPawel Jakub Dawidek 4836da5199SPawel Jakub Dawidek #ifdef HAVE_PJDLOG 4936da5199SPawel Jakub Dawidek #include <pjdlog.h> 5036da5199SPawel Jakub Dawidek #endif 5136da5199SPawel Jakub Dawidek 5236da5199SPawel Jakub Dawidek #include "common_impl.h" 5336da5199SPawel Jakub Dawidek #include "msgio.h" 5436da5199SPawel Jakub Dawidek 5536da5199SPawel Jakub Dawidek #ifndef HAVE_PJDLOG 5636da5199SPawel Jakub Dawidek #include <assert.h> 5736da5199SPawel Jakub Dawidek #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 5836da5199SPawel Jakub Dawidek #define PJDLOG_RASSERT(expr, ...) assert(expr) 5936da5199SPawel Jakub Dawidek #define PJDLOG_ABORT(...) abort() 6036da5199SPawel Jakub Dawidek #endif 6136da5199SPawel Jakub Dawidek 62*3810ba1bSMariusz Zaborski #ifdef __linux__ 63*3810ba1bSMariusz Zaborski /* Linux: arbitrary size, but must be lower than SCM_MAX_FD. */ 64*3810ba1bSMariusz Zaborski #define PKG_MAX_SIZE ((64U - 1) * CMSG_SPACE(sizeof(int))) 65*3810ba1bSMariusz Zaborski #else 66586c5854SPawel Jakub Dawidek #define PKG_MAX_SIZE (MCLBYTES / CMSG_SPACE(sizeof(int)) - 1) 67*3810ba1bSMariusz Zaborski #endif 68586c5854SPawel Jakub Dawidek 6936da5199SPawel Jakub Dawidek static int 7036da5199SPawel Jakub Dawidek msghdr_add_fd(struct cmsghdr *cmsg, int fd) 7136da5199SPawel Jakub Dawidek { 7236da5199SPawel Jakub Dawidek 7336da5199SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 7436da5199SPawel Jakub Dawidek 7536da5199SPawel Jakub Dawidek cmsg->cmsg_level = SOL_SOCKET; 7636da5199SPawel Jakub Dawidek cmsg->cmsg_type = SCM_RIGHTS; 7736da5199SPawel Jakub Dawidek cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); 7836da5199SPawel Jakub Dawidek bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); 7936da5199SPawel Jakub Dawidek 8036da5199SPawel Jakub Dawidek return (0); 8136da5199SPawel Jakub Dawidek } 8236da5199SPawel Jakub Dawidek 8336da5199SPawel Jakub Dawidek static void 8436da5199SPawel Jakub Dawidek fd_wait(int fd, bool doread) 8536da5199SPawel Jakub Dawidek { 8636da5199SPawel Jakub Dawidek fd_set fds; 8736da5199SPawel Jakub Dawidek 8836da5199SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 8936da5199SPawel Jakub Dawidek 9036da5199SPawel Jakub Dawidek FD_ZERO(&fds); 9136da5199SPawel Jakub Dawidek FD_SET(fd, &fds); 9236da5199SPawel Jakub Dawidek (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds, 9336da5199SPawel Jakub Dawidek NULL, NULL); 9436da5199SPawel Jakub Dawidek } 9536da5199SPawel Jakub Dawidek 9636da5199SPawel Jakub Dawidek static int 9736da5199SPawel Jakub Dawidek msg_recv(int sock, struct msghdr *msg) 9836da5199SPawel Jakub Dawidek { 9936da5199SPawel Jakub Dawidek int flags; 10036da5199SPawel Jakub Dawidek 10136da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 10236da5199SPawel Jakub Dawidek 10336da5199SPawel Jakub Dawidek #ifdef MSG_CMSG_CLOEXEC 10436da5199SPawel Jakub Dawidek flags = MSG_CMSG_CLOEXEC; 10536da5199SPawel Jakub Dawidek #else 10636da5199SPawel Jakub Dawidek flags = 0; 10736da5199SPawel Jakub Dawidek #endif 10836da5199SPawel Jakub Dawidek 10936da5199SPawel Jakub Dawidek for (;;) { 11036da5199SPawel Jakub Dawidek fd_wait(sock, true); 11136da5199SPawel Jakub Dawidek if (recvmsg(sock, msg, flags) == -1) { 11236da5199SPawel Jakub Dawidek if (errno == EINTR) 11336da5199SPawel Jakub Dawidek continue; 11436da5199SPawel Jakub Dawidek return (-1); 11536da5199SPawel Jakub Dawidek } 11636da5199SPawel Jakub Dawidek break; 11736da5199SPawel Jakub Dawidek } 11836da5199SPawel Jakub Dawidek 11936da5199SPawel Jakub Dawidek return (0); 12036da5199SPawel Jakub Dawidek } 12136da5199SPawel Jakub Dawidek 12236da5199SPawel Jakub Dawidek static int 12336da5199SPawel Jakub Dawidek msg_send(int sock, const struct msghdr *msg) 12436da5199SPawel Jakub Dawidek { 12536da5199SPawel Jakub Dawidek 12636da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 12736da5199SPawel Jakub Dawidek 12836da5199SPawel Jakub Dawidek for (;;) { 12936da5199SPawel Jakub Dawidek fd_wait(sock, false); 13036da5199SPawel Jakub Dawidek if (sendmsg(sock, msg, 0) == -1) { 13136da5199SPawel Jakub Dawidek if (errno == EINTR) 13236da5199SPawel Jakub Dawidek continue; 13336da5199SPawel Jakub Dawidek return (-1); 13436da5199SPawel Jakub Dawidek } 13536da5199SPawel Jakub Dawidek break; 13636da5199SPawel Jakub Dawidek } 13736da5199SPawel Jakub Dawidek 13836da5199SPawel Jakub Dawidek return (0); 13936da5199SPawel Jakub Dawidek } 14036da5199SPawel Jakub Dawidek 141*3810ba1bSMariusz Zaborski #ifdef __FreeBSD__ 14236da5199SPawel Jakub Dawidek int 14336da5199SPawel Jakub Dawidek cred_send(int sock) 14436da5199SPawel Jakub Dawidek { 14536da5199SPawel Jakub Dawidek unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))]; 14636da5199SPawel Jakub Dawidek struct msghdr msg; 14736da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 14836da5199SPawel Jakub Dawidek struct iovec iov; 14936da5199SPawel Jakub Dawidek uint8_t dummy; 15036da5199SPawel Jakub Dawidek 15136da5199SPawel Jakub Dawidek bzero(credbuf, sizeof(credbuf)); 15236da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 15336da5199SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 15436da5199SPawel Jakub Dawidek 15536da5199SPawel Jakub Dawidek /* 15636da5199SPawel Jakub Dawidek * XXX: We send one byte along with the control message, because 15736da5199SPawel Jakub Dawidek * setting msg_iov to NULL only works if this is the first 15836da5199SPawel Jakub Dawidek * packet send over the socket. Once we send some data we 15936da5199SPawel Jakub Dawidek * won't be able to send credentials anymore. This is most 16036da5199SPawel Jakub Dawidek * likely a kernel bug. 16136da5199SPawel Jakub Dawidek */ 16236da5199SPawel Jakub Dawidek dummy = 0; 16336da5199SPawel Jakub Dawidek iov.iov_base = &dummy; 16436da5199SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 16536da5199SPawel Jakub Dawidek 16636da5199SPawel Jakub Dawidek msg.msg_iov = &iov; 16736da5199SPawel Jakub Dawidek msg.msg_iovlen = 1; 16836da5199SPawel Jakub Dawidek msg.msg_control = credbuf; 16936da5199SPawel Jakub Dawidek msg.msg_controllen = sizeof(credbuf); 17036da5199SPawel Jakub Dawidek 17136da5199SPawel Jakub Dawidek cmsg = CMSG_FIRSTHDR(&msg); 17236da5199SPawel Jakub Dawidek cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred)); 17336da5199SPawel Jakub Dawidek cmsg->cmsg_level = SOL_SOCKET; 17436da5199SPawel Jakub Dawidek cmsg->cmsg_type = SCM_CREDS; 17536da5199SPawel Jakub Dawidek 17636da5199SPawel Jakub Dawidek if (msg_send(sock, &msg) == -1) 17736da5199SPawel Jakub Dawidek return (-1); 17836da5199SPawel Jakub Dawidek 17936da5199SPawel Jakub Dawidek return (0); 18036da5199SPawel Jakub Dawidek } 18136da5199SPawel Jakub Dawidek 18236da5199SPawel Jakub Dawidek int 18336da5199SPawel Jakub Dawidek cred_recv(int sock, struct cmsgcred *cred) 18436da5199SPawel Jakub Dawidek { 18536da5199SPawel Jakub Dawidek unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))]; 18636da5199SPawel Jakub Dawidek struct msghdr msg; 18736da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 18836da5199SPawel Jakub Dawidek struct iovec iov; 18936da5199SPawel Jakub Dawidek uint8_t dummy; 19036da5199SPawel Jakub Dawidek 19136da5199SPawel Jakub Dawidek bzero(credbuf, sizeof(credbuf)); 19236da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 19336da5199SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 19436da5199SPawel Jakub Dawidek 19536da5199SPawel Jakub Dawidek iov.iov_base = &dummy; 19636da5199SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 19736da5199SPawel Jakub Dawidek 19836da5199SPawel Jakub Dawidek msg.msg_iov = &iov; 19936da5199SPawel Jakub Dawidek msg.msg_iovlen = 1; 20036da5199SPawel Jakub Dawidek msg.msg_control = credbuf; 20136da5199SPawel Jakub Dawidek msg.msg_controllen = sizeof(credbuf); 20236da5199SPawel Jakub Dawidek 20336da5199SPawel Jakub Dawidek if (msg_recv(sock, &msg) == -1) 20436da5199SPawel Jakub Dawidek return (-1); 20536da5199SPawel Jakub Dawidek 20636da5199SPawel Jakub Dawidek cmsg = CMSG_FIRSTHDR(&msg); 20736da5199SPawel Jakub Dawidek if (cmsg == NULL || 20836da5199SPawel Jakub Dawidek cmsg->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred)) || 20936da5199SPawel Jakub Dawidek cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDS) { 21036da5199SPawel Jakub Dawidek errno = EINVAL; 21136da5199SPawel Jakub Dawidek return (-1); 21236da5199SPawel Jakub Dawidek } 21336da5199SPawel Jakub Dawidek bcopy(CMSG_DATA(cmsg), cred, sizeof(*cred)); 21436da5199SPawel Jakub Dawidek 21536da5199SPawel Jakub Dawidek return (0); 21636da5199SPawel Jakub Dawidek } 217032f0fbbSAlex Richardson #endif 21836da5199SPawel Jakub Dawidek 219586c5854SPawel Jakub Dawidek static int 220586c5854SPawel Jakub Dawidek fd_package_send(int sock, const int *fds, size_t nfds) 22136da5199SPawel Jakub Dawidek { 22236da5199SPawel Jakub Dawidek struct msghdr msg; 22336da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 224586c5854SPawel Jakub Dawidek struct iovec iov; 22536da5199SPawel Jakub Dawidek unsigned int i; 22636da5199SPawel Jakub Dawidek int serrno, ret; 227586c5854SPawel Jakub Dawidek uint8_t dummy; 22836da5199SPawel Jakub Dawidek 229586c5854SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 230586c5854SPawel Jakub Dawidek PJDLOG_ASSERT(fds != NULL); 231586c5854SPawel Jakub Dawidek PJDLOG_ASSERT(nfds > 0); 23236da5199SPawel Jakub Dawidek 23336da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 234586c5854SPawel Jakub Dawidek 235586c5854SPawel Jakub Dawidek /* 236586c5854SPawel Jakub Dawidek * XXX: Look into cred_send function for more details. 237586c5854SPawel Jakub Dawidek */ 238586c5854SPawel Jakub Dawidek dummy = 0; 239586c5854SPawel Jakub Dawidek iov.iov_base = &dummy; 240586c5854SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 241586c5854SPawel Jakub Dawidek 242586c5854SPawel Jakub Dawidek msg.msg_iov = &iov; 243586c5854SPawel Jakub Dawidek msg.msg_iovlen = 1; 24436da5199SPawel Jakub Dawidek msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int)); 24536da5199SPawel Jakub Dawidek msg.msg_control = calloc(1, msg.msg_controllen); 24636da5199SPawel Jakub Dawidek if (msg.msg_control == NULL) 24736da5199SPawel Jakub Dawidek return (-1); 24836da5199SPawel Jakub Dawidek 24936da5199SPawel Jakub Dawidek ret = -1; 25036da5199SPawel Jakub Dawidek 25136da5199SPawel Jakub Dawidek for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL; 25236da5199SPawel Jakub Dawidek i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) { 25336da5199SPawel Jakub Dawidek if (msghdr_add_fd(cmsg, fds[i]) == -1) 25436da5199SPawel Jakub Dawidek goto end; 25536da5199SPawel Jakub Dawidek } 25636da5199SPawel Jakub Dawidek 25736da5199SPawel Jakub Dawidek if (msg_send(sock, &msg) == -1) 25836da5199SPawel Jakub Dawidek goto end; 25936da5199SPawel Jakub Dawidek 26036da5199SPawel Jakub Dawidek ret = 0; 26136da5199SPawel Jakub Dawidek end: 26236da5199SPawel Jakub Dawidek serrno = errno; 26336da5199SPawel Jakub Dawidek free(msg.msg_control); 26436da5199SPawel Jakub Dawidek errno = serrno; 26536da5199SPawel Jakub Dawidek return (ret); 26636da5199SPawel Jakub Dawidek } 26736da5199SPawel Jakub Dawidek 268586c5854SPawel Jakub Dawidek static int 269586c5854SPawel Jakub Dawidek fd_package_recv(int sock, int *fds, size_t nfds) 27036da5199SPawel Jakub Dawidek { 27136da5199SPawel Jakub Dawidek struct msghdr msg; 27236da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 27336da5199SPawel Jakub Dawidek unsigned int i; 27436da5199SPawel Jakub Dawidek int serrno, ret; 275586c5854SPawel Jakub Dawidek struct iovec iov; 276586c5854SPawel Jakub Dawidek uint8_t dummy; 27736da5199SPawel Jakub Dawidek 278586c5854SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 279586c5854SPawel Jakub Dawidek PJDLOG_ASSERT(nfds > 0); 280586c5854SPawel Jakub Dawidek PJDLOG_ASSERT(fds != NULL); 28136da5199SPawel Jakub Dawidek 28236da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 283586c5854SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 284586c5854SPawel Jakub Dawidek 285586c5854SPawel Jakub Dawidek /* 286586c5854SPawel Jakub Dawidek * XXX: Look into cred_send function for more details. 287586c5854SPawel Jakub Dawidek */ 288586c5854SPawel Jakub Dawidek iov.iov_base = &dummy; 289586c5854SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 290586c5854SPawel Jakub Dawidek 291586c5854SPawel Jakub Dawidek msg.msg_iov = &iov; 292586c5854SPawel Jakub Dawidek msg.msg_iovlen = 1; 29336da5199SPawel Jakub Dawidek msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int)); 29436da5199SPawel Jakub Dawidek msg.msg_control = calloc(1, msg.msg_controllen); 29536da5199SPawel Jakub Dawidek if (msg.msg_control == NULL) 29636da5199SPawel Jakub Dawidek return (-1); 29736da5199SPawel Jakub Dawidek 29836da5199SPawel Jakub Dawidek ret = -1; 29936da5199SPawel Jakub Dawidek 30036da5199SPawel Jakub Dawidek if (msg_recv(sock, &msg) == -1) 30136da5199SPawel Jakub Dawidek goto end; 30236da5199SPawel Jakub Dawidek 303*3810ba1bSMariusz Zaborski i = 0; 304*3810ba1bSMariusz Zaborski cmsg = CMSG_FIRSTHDR(&msg); 305*3810ba1bSMariusz Zaborski while (cmsg && i < nfds) { 306*3810ba1bSMariusz Zaborski unsigned int n; 307*3810ba1bSMariusz Zaborski 308*3810ba1bSMariusz Zaborski if (cmsg->cmsg_level != SOL_SOCKET || 309*3810ba1bSMariusz Zaborski cmsg->cmsg_type != SCM_RIGHTS) { 310*3810ba1bSMariusz Zaborski errno = EINVAL; 31136da5199SPawel Jakub Dawidek break; 31236da5199SPawel Jakub Dawidek } 313*3810ba1bSMariusz Zaborski n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); 314*3810ba1bSMariusz Zaborski if (i + n > nfds) { 315*3810ba1bSMariusz Zaborski errno = EINVAL; 316*3810ba1bSMariusz Zaborski break; 317*3810ba1bSMariusz Zaborski } 318*3810ba1bSMariusz Zaborski bcopy(CMSG_DATA(cmsg), fds + i, sizeof(int) * n); 319*3810ba1bSMariusz Zaborski cmsg = CMSG_NXTHDR(&msg, cmsg); 320*3810ba1bSMariusz Zaborski i += n; 321*3810ba1bSMariusz Zaborski } 32236da5199SPawel Jakub Dawidek 32336da5199SPawel Jakub Dawidek if (cmsg != NULL || i < nfds) { 324*3810ba1bSMariusz Zaborski unsigned int last; 32536da5199SPawel Jakub Dawidek 32636da5199SPawel Jakub Dawidek /* 32736da5199SPawel Jakub Dawidek * We need to close all received descriptors, even if we have 32836da5199SPawel Jakub Dawidek * different control message (eg. SCM_CREDS) in between. 32936da5199SPawel Jakub Dawidek */ 330*3810ba1bSMariusz Zaborski last = i; 331*3810ba1bSMariusz Zaborski for (i = 0; i < last; i++) { 332*3810ba1bSMariusz Zaborski if (fds[i] >= 0) { 333*3810ba1bSMariusz Zaborski close(fds[i]); 334*3810ba1bSMariusz Zaborski } 33536da5199SPawel Jakub Dawidek } 33636da5199SPawel Jakub Dawidek errno = EINVAL; 33736da5199SPawel Jakub Dawidek goto end; 33836da5199SPawel Jakub Dawidek } 33936da5199SPawel Jakub Dawidek 340*3810ba1bSMariusz Zaborski #ifndef MSG_CMSG_CLOEXEC 341*3810ba1bSMariusz Zaborski /* 342*3810ba1bSMariusz Zaborski * If the MSG_CMSG_CLOEXEC flag is not available we cannot set the 343*3810ba1bSMariusz Zaborski * close-on-exec flag atomically, but we still want to set it for 344*3810ba1bSMariusz Zaborski * consistency. 345*3810ba1bSMariusz Zaborski */ 346*3810ba1bSMariusz Zaborski for (i = 0; i < nfds; i++) { 347*3810ba1bSMariusz Zaborski (void) fcntl(fds[i], F_SETFD, FD_CLOEXEC); 348*3810ba1bSMariusz Zaborski } 349*3810ba1bSMariusz Zaborski #endif 350*3810ba1bSMariusz Zaborski 35136da5199SPawel Jakub Dawidek ret = 0; 35236da5199SPawel Jakub Dawidek end: 35336da5199SPawel Jakub Dawidek serrno = errno; 35436da5199SPawel Jakub Dawidek free(msg.msg_control); 35536da5199SPawel Jakub Dawidek errno = serrno; 35636da5199SPawel Jakub Dawidek return (ret); 35736da5199SPawel Jakub Dawidek } 35836da5199SPawel Jakub Dawidek 35936da5199SPawel Jakub Dawidek int 360586c5854SPawel Jakub Dawidek fd_recv(int sock, int *fds, size_t nfds) 361586c5854SPawel Jakub Dawidek { 362586c5854SPawel Jakub Dawidek unsigned int i, step, j; 363586c5854SPawel Jakub Dawidek int ret, serrno; 364586c5854SPawel Jakub Dawidek 365586c5854SPawel Jakub Dawidek if (nfds == 0 || fds == NULL) { 366586c5854SPawel Jakub Dawidek errno = EINVAL; 367586c5854SPawel Jakub Dawidek return (-1); 368586c5854SPawel Jakub Dawidek } 369586c5854SPawel Jakub Dawidek 370586c5854SPawel Jakub Dawidek ret = i = step = 0; 371586c5854SPawel Jakub Dawidek while (i < nfds) { 372586c5854SPawel Jakub Dawidek if (PKG_MAX_SIZE < nfds - i) 373586c5854SPawel Jakub Dawidek step = PKG_MAX_SIZE; 374586c5854SPawel Jakub Dawidek else 375586c5854SPawel Jakub Dawidek step = nfds - i; 376586c5854SPawel Jakub Dawidek ret = fd_package_recv(sock, fds + i, step); 377586c5854SPawel Jakub Dawidek if (ret != 0) { 378586c5854SPawel Jakub Dawidek /* Close all received descriptors. */ 379586c5854SPawel Jakub Dawidek serrno = errno; 380586c5854SPawel Jakub Dawidek for (j = 0; j < i; j++) 381586c5854SPawel Jakub Dawidek close(fds[j]); 382586c5854SPawel Jakub Dawidek errno = serrno; 383586c5854SPawel Jakub Dawidek break; 384586c5854SPawel Jakub Dawidek } 385586c5854SPawel Jakub Dawidek i += step; 386586c5854SPawel Jakub Dawidek } 387586c5854SPawel Jakub Dawidek 388586c5854SPawel Jakub Dawidek return (ret); 389586c5854SPawel Jakub Dawidek } 390586c5854SPawel Jakub Dawidek 391586c5854SPawel Jakub Dawidek int 392586c5854SPawel Jakub Dawidek fd_send(int sock, const int *fds, size_t nfds) 393586c5854SPawel Jakub Dawidek { 394586c5854SPawel Jakub Dawidek unsigned int i, step; 395586c5854SPawel Jakub Dawidek int ret; 396586c5854SPawel Jakub Dawidek 397586c5854SPawel Jakub Dawidek if (nfds == 0 || fds == NULL) { 398586c5854SPawel Jakub Dawidek errno = EINVAL; 399586c5854SPawel Jakub Dawidek return (-1); 400586c5854SPawel Jakub Dawidek } 401586c5854SPawel Jakub Dawidek 402586c5854SPawel Jakub Dawidek ret = i = step = 0; 403586c5854SPawel Jakub Dawidek while (i < nfds) { 404586c5854SPawel Jakub Dawidek if (PKG_MAX_SIZE < nfds - i) 405586c5854SPawel Jakub Dawidek step = PKG_MAX_SIZE; 406586c5854SPawel Jakub Dawidek else 407586c5854SPawel Jakub Dawidek step = nfds - i; 408586c5854SPawel Jakub Dawidek ret = fd_package_send(sock, fds + i, step); 409586c5854SPawel Jakub Dawidek if (ret != 0) 410586c5854SPawel Jakub Dawidek break; 411586c5854SPawel Jakub Dawidek i += step; 412586c5854SPawel Jakub Dawidek } 413586c5854SPawel Jakub Dawidek 414586c5854SPawel Jakub Dawidek return (ret); 415586c5854SPawel Jakub Dawidek } 416586c5854SPawel Jakub Dawidek 417586c5854SPawel Jakub Dawidek int 41836da5199SPawel Jakub Dawidek buf_send(int sock, void *buf, size_t size) 41936da5199SPawel Jakub Dawidek { 42036da5199SPawel Jakub Dawidek ssize_t done; 42136da5199SPawel Jakub Dawidek unsigned char *ptr; 42236da5199SPawel Jakub Dawidek 4233d34eceaSPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 4243d34eceaSPawel Jakub Dawidek PJDLOG_ASSERT(size > 0); 4253d34eceaSPawel Jakub Dawidek PJDLOG_ASSERT(buf != NULL); 4263d34eceaSPawel Jakub Dawidek 42736da5199SPawel Jakub Dawidek ptr = buf; 42836da5199SPawel Jakub Dawidek do { 42936da5199SPawel Jakub Dawidek fd_wait(sock, false); 43036da5199SPawel Jakub Dawidek done = send(sock, ptr, size, 0); 43136da5199SPawel Jakub Dawidek if (done == -1) { 43236da5199SPawel Jakub Dawidek if (errno == EINTR) 43336da5199SPawel Jakub Dawidek continue; 43436da5199SPawel Jakub Dawidek return (-1); 43536da5199SPawel Jakub Dawidek } else if (done == 0) { 43636da5199SPawel Jakub Dawidek errno = ENOTCONN; 43736da5199SPawel Jakub Dawidek return (-1); 43836da5199SPawel Jakub Dawidek } 43936da5199SPawel Jakub Dawidek size -= done; 44036da5199SPawel Jakub Dawidek ptr += done; 44136da5199SPawel Jakub Dawidek } while (size > 0); 44236da5199SPawel Jakub Dawidek 44336da5199SPawel Jakub Dawidek return (0); 44436da5199SPawel Jakub Dawidek } 44536da5199SPawel Jakub Dawidek 44636da5199SPawel Jakub Dawidek int 44736da5199SPawel Jakub Dawidek buf_recv(int sock, void *buf, size_t size) 44836da5199SPawel Jakub Dawidek { 44936da5199SPawel Jakub Dawidek ssize_t done; 45036da5199SPawel Jakub Dawidek unsigned char *ptr; 45136da5199SPawel Jakub Dawidek 4523d34eceaSPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 4533d34eceaSPawel Jakub Dawidek PJDLOG_ASSERT(buf != NULL); 4543d34eceaSPawel Jakub Dawidek 45536da5199SPawel Jakub Dawidek ptr = buf; 4567f7fe890SPawel Jakub Dawidek while (size > 0) { 45736da5199SPawel Jakub Dawidek fd_wait(sock, true); 45836da5199SPawel Jakub Dawidek done = recv(sock, ptr, size, 0); 45936da5199SPawel Jakub Dawidek if (done == -1) { 46036da5199SPawel Jakub Dawidek if (errno == EINTR) 46136da5199SPawel Jakub Dawidek continue; 46236da5199SPawel Jakub Dawidek return (-1); 46336da5199SPawel Jakub Dawidek } else if (done == 0) { 46436da5199SPawel Jakub Dawidek errno = ENOTCONN; 46536da5199SPawel Jakub Dawidek return (-1); 46636da5199SPawel Jakub Dawidek } 46736da5199SPawel Jakub Dawidek size -= done; 46836da5199SPawel Jakub Dawidek ptr += done; 4697f7fe890SPawel Jakub Dawidek } 47036da5199SPawel Jakub Dawidek 47136da5199SPawel Jakub Dawidek return (0); 47236da5199SPawel Jakub Dawidek } 473