1*36da5199SPawel Jakub Dawidek /*- 2*36da5199SPawel Jakub Dawidek * Copyright (c) 2013 The FreeBSD Foundation 3*36da5199SPawel Jakub Dawidek * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org> 4*36da5199SPawel Jakub Dawidek * All rights reserved. 5*36da5199SPawel Jakub Dawidek * 6*36da5199SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 7*36da5199SPawel Jakub Dawidek * the FreeBSD Foundation. 8*36da5199SPawel Jakub Dawidek * 9*36da5199SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 10*36da5199SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 11*36da5199SPawel Jakub Dawidek * are met: 12*36da5199SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 13*36da5199SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 14*36da5199SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 15*36da5199SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 16*36da5199SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 17*36da5199SPawel Jakub Dawidek * 18*36da5199SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19*36da5199SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*36da5199SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*36da5199SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22*36da5199SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*36da5199SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*36da5199SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*36da5199SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26*36da5199SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*36da5199SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*36da5199SPawel Jakub Dawidek * SUCH DAMAGE. 29*36da5199SPawel Jakub Dawidek */ 30*36da5199SPawel Jakub Dawidek 31*36da5199SPawel Jakub Dawidek #include <sys/cdefs.h> 32*36da5199SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 33*36da5199SPawel Jakub Dawidek 34*36da5199SPawel Jakub Dawidek #include <sys/types.h> 35*36da5199SPawel Jakub Dawidek #include <sys/socket.h> 36*36da5199SPawel Jakub Dawidek 37*36da5199SPawel Jakub Dawidek #include <errno.h> 38*36da5199SPawel Jakub Dawidek #include <fcntl.h> 39*36da5199SPawel Jakub Dawidek #include <stdbool.h> 40*36da5199SPawel Jakub Dawidek #include <stdint.h> 41*36da5199SPawel Jakub Dawidek #include <stdlib.h> 42*36da5199SPawel Jakub Dawidek #include <string.h> 43*36da5199SPawel Jakub Dawidek #include <unistd.h> 44*36da5199SPawel Jakub Dawidek 45*36da5199SPawel Jakub Dawidek #ifdef HAVE_PJDLOG 46*36da5199SPawel Jakub Dawidek #include <pjdlog.h> 47*36da5199SPawel Jakub Dawidek #endif 48*36da5199SPawel Jakub Dawidek 49*36da5199SPawel Jakub Dawidek #include "common_impl.h" 50*36da5199SPawel Jakub Dawidek #include "msgio.h" 51*36da5199SPawel Jakub Dawidek 52*36da5199SPawel Jakub Dawidek #ifndef HAVE_PJDLOG 53*36da5199SPawel Jakub Dawidek #include <assert.h> 54*36da5199SPawel Jakub Dawidek #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 55*36da5199SPawel Jakub Dawidek #define PJDLOG_RASSERT(expr, ...) assert(expr) 56*36da5199SPawel Jakub Dawidek #define PJDLOG_ABORT(...) abort() 57*36da5199SPawel Jakub Dawidek #endif 58*36da5199SPawel Jakub Dawidek 59*36da5199SPawel Jakub Dawidek static int 60*36da5199SPawel Jakub Dawidek msghdr_add_fd(struct cmsghdr *cmsg, int fd) 61*36da5199SPawel Jakub Dawidek { 62*36da5199SPawel Jakub Dawidek 63*36da5199SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 64*36da5199SPawel Jakub Dawidek 65*36da5199SPawel Jakub Dawidek if (!fd_is_valid(fd)) { 66*36da5199SPawel Jakub Dawidek errno = EBADF; 67*36da5199SPawel Jakub Dawidek return (-1); 68*36da5199SPawel Jakub Dawidek } 69*36da5199SPawel Jakub Dawidek 70*36da5199SPawel Jakub Dawidek cmsg->cmsg_level = SOL_SOCKET; 71*36da5199SPawel Jakub Dawidek cmsg->cmsg_type = SCM_RIGHTS; 72*36da5199SPawel Jakub Dawidek cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); 73*36da5199SPawel Jakub Dawidek bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); 74*36da5199SPawel Jakub Dawidek 75*36da5199SPawel Jakub Dawidek return (0); 76*36da5199SPawel Jakub Dawidek } 77*36da5199SPawel Jakub Dawidek 78*36da5199SPawel Jakub Dawidek static int 79*36da5199SPawel Jakub Dawidek msghdr_get_fd(struct cmsghdr *cmsg) 80*36da5199SPawel Jakub Dawidek { 81*36da5199SPawel Jakub Dawidek int fd; 82*36da5199SPawel Jakub Dawidek 83*36da5199SPawel Jakub Dawidek if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || 84*36da5199SPawel Jakub Dawidek cmsg->cmsg_type != SCM_RIGHTS || 85*36da5199SPawel Jakub Dawidek cmsg->cmsg_len != CMSG_LEN(sizeof(fd))) { 86*36da5199SPawel Jakub Dawidek errno = EINVAL; 87*36da5199SPawel Jakub Dawidek return (-1); 88*36da5199SPawel Jakub Dawidek } 89*36da5199SPawel Jakub Dawidek 90*36da5199SPawel Jakub Dawidek bcopy(CMSG_DATA(cmsg), &fd, sizeof(fd)); 91*36da5199SPawel Jakub Dawidek #ifndef MSG_CMSG_CLOEXEC 92*36da5199SPawel Jakub Dawidek /* 93*36da5199SPawel Jakub Dawidek * If the MSG_CMSG_CLOEXEC flag is not available we cannot set the 94*36da5199SPawel Jakub Dawidek * close-on-exec flag atomically, but we still want to set it for 95*36da5199SPawel Jakub Dawidek * consistency. 96*36da5199SPawel Jakub Dawidek */ 97*36da5199SPawel Jakub Dawidek (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 98*36da5199SPawel Jakub Dawidek #endif 99*36da5199SPawel Jakub Dawidek 100*36da5199SPawel Jakub Dawidek return (fd); 101*36da5199SPawel Jakub Dawidek } 102*36da5199SPawel Jakub Dawidek 103*36da5199SPawel Jakub Dawidek static void 104*36da5199SPawel Jakub Dawidek fd_wait(int fd, bool doread) 105*36da5199SPawel Jakub Dawidek { 106*36da5199SPawel Jakub Dawidek fd_set fds; 107*36da5199SPawel Jakub Dawidek 108*36da5199SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 109*36da5199SPawel Jakub Dawidek 110*36da5199SPawel Jakub Dawidek FD_ZERO(&fds); 111*36da5199SPawel Jakub Dawidek FD_SET(fd, &fds); 112*36da5199SPawel Jakub Dawidek (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds, 113*36da5199SPawel Jakub Dawidek NULL, NULL); 114*36da5199SPawel Jakub Dawidek } 115*36da5199SPawel Jakub Dawidek 116*36da5199SPawel Jakub Dawidek int 117*36da5199SPawel Jakub Dawidek msg_peek(int sock, void *buf, size_t size) 118*36da5199SPawel Jakub Dawidek { 119*36da5199SPawel Jakub Dawidek ssize_t done; 120*36da5199SPawel Jakub Dawidek 121*36da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 122*36da5199SPawel Jakub Dawidek PJDLOG_ASSERT(size > 0); 123*36da5199SPawel Jakub Dawidek 124*36da5199SPawel Jakub Dawidek do { 125*36da5199SPawel Jakub Dawidek fd_wait(sock, true); 126*36da5199SPawel Jakub Dawidek done = recv(sock, buf, size, MSG_PEEK | MSG_WAITALL); 127*36da5199SPawel Jakub Dawidek if (done == -1) { 128*36da5199SPawel Jakub Dawidek if (errno == EAGAIN || errno == EINTR) 129*36da5199SPawel Jakub Dawidek continue; 130*36da5199SPawel Jakub Dawidek return (-1); 131*36da5199SPawel Jakub Dawidek } else if (done == 0) { 132*36da5199SPawel Jakub Dawidek errno = ENOTCONN; 133*36da5199SPawel Jakub Dawidek return (-1); 134*36da5199SPawel Jakub Dawidek } 135*36da5199SPawel Jakub Dawidek } while (done != (ssize_t)size); 136*36da5199SPawel Jakub Dawidek 137*36da5199SPawel Jakub Dawidek return (0); 138*36da5199SPawel Jakub Dawidek } 139*36da5199SPawel Jakub Dawidek 140*36da5199SPawel Jakub Dawidek static int 141*36da5199SPawel Jakub Dawidek msg_recv(int sock, struct msghdr *msg) 142*36da5199SPawel Jakub Dawidek { 143*36da5199SPawel Jakub Dawidek int flags; 144*36da5199SPawel Jakub Dawidek 145*36da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 146*36da5199SPawel Jakub Dawidek 147*36da5199SPawel Jakub Dawidek #ifdef MSG_CMSG_CLOEXEC 148*36da5199SPawel Jakub Dawidek flags = MSG_CMSG_CLOEXEC; 149*36da5199SPawel Jakub Dawidek #else 150*36da5199SPawel Jakub Dawidek flags = 0; 151*36da5199SPawel Jakub Dawidek #endif 152*36da5199SPawel Jakub Dawidek 153*36da5199SPawel Jakub Dawidek for (;;) { 154*36da5199SPawel Jakub Dawidek fd_wait(sock, true); 155*36da5199SPawel Jakub Dawidek if (recvmsg(sock, msg, flags) == -1) { 156*36da5199SPawel Jakub Dawidek if (errno == EINTR) 157*36da5199SPawel Jakub Dawidek continue; 158*36da5199SPawel Jakub Dawidek return (-1); 159*36da5199SPawel Jakub Dawidek } 160*36da5199SPawel Jakub Dawidek break; 161*36da5199SPawel Jakub Dawidek } 162*36da5199SPawel Jakub Dawidek 163*36da5199SPawel Jakub Dawidek return (0); 164*36da5199SPawel Jakub Dawidek } 165*36da5199SPawel Jakub Dawidek 166*36da5199SPawel Jakub Dawidek static int 167*36da5199SPawel Jakub Dawidek msg_send(int sock, const struct msghdr *msg) 168*36da5199SPawel Jakub Dawidek { 169*36da5199SPawel Jakub Dawidek 170*36da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 171*36da5199SPawel Jakub Dawidek 172*36da5199SPawel Jakub Dawidek for (;;) { 173*36da5199SPawel Jakub Dawidek fd_wait(sock, false); 174*36da5199SPawel Jakub Dawidek if (sendmsg(sock, msg, 0) == -1) { 175*36da5199SPawel Jakub Dawidek if (errno == EINTR) 176*36da5199SPawel Jakub Dawidek continue; 177*36da5199SPawel Jakub Dawidek return (-1); 178*36da5199SPawel Jakub Dawidek } 179*36da5199SPawel Jakub Dawidek break; 180*36da5199SPawel Jakub Dawidek } 181*36da5199SPawel Jakub Dawidek 182*36da5199SPawel Jakub Dawidek return (0); 183*36da5199SPawel Jakub Dawidek } 184*36da5199SPawel Jakub Dawidek 185*36da5199SPawel Jakub Dawidek int 186*36da5199SPawel Jakub Dawidek cred_send(int sock) 187*36da5199SPawel Jakub Dawidek { 188*36da5199SPawel Jakub Dawidek unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))]; 189*36da5199SPawel Jakub Dawidek struct msghdr msg; 190*36da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 191*36da5199SPawel Jakub Dawidek struct iovec iov; 192*36da5199SPawel Jakub Dawidek uint8_t dummy; 193*36da5199SPawel Jakub Dawidek 194*36da5199SPawel Jakub Dawidek bzero(credbuf, sizeof(credbuf)); 195*36da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 196*36da5199SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 197*36da5199SPawel Jakub Dawidek 198*36da5199SPawel Jakub Dawidek /* 199*36da5199SPawel Jakub Dawidek * XXX: We send one byte along with the control message, because 200*36da5199SPawel Jakub Dawidek * setting msg_iov to NULL only works if this is the first 201*36da5199SPawel Jakub Dawidek * packet send over the socket. Once we send some data we 202*36da5199SPawel Jakub Dawidek * won't be able to send credentials anymore. This is most 203*36da5199SPawel Jakub Dawidek * likely a kernel bug. 204*36da5199SPawel Jakub Dawidek */ 205*36da5199SPawel Jakub Dawidek dummy = 0; 206*36da5199SPawel Jakub Dawidek iov.iov_base = &dummy; 207*36da5199SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 208*36da5199SPawel Jakub Dawidek 209*36da5199SPawel Jakub Dawidek msg.msg_iov = &iov; 210*36da5199SPawel Jakub Dawidek msg.msg_iovlen = 1; 211*36da5199SPawel Jakub Dawidek msg.msg_control = credbuf; 212*36da5199SPawel Jakub Dawidek msg.msg_controllen = sizeof(credbuf); 213*36da5199SPawel Jakub Dawidek 214*36da5199SPawel Jakub Dawidek cmsg = CMSG_FIRSTHDR(&msg); 215*36da5199SPawel Jakub Dawidek cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred)); 216*36da5199SPawel Jakub Dawidek cmsg->cmsg_level = SOL_SOCKET; 217*36da5199SPawel Jakub Dawidek cmsg->cmsg_type = SCM_CREDS; 218*36da5199SPawel Jakub Dawidek 219*36da5199SPawel Jakub Dawidek if (msg_send(sock, &msg) == -1) 220*36da5199SPawel Jakub Dawidek return (-1); 221*36da5199SPawel Jakub Dawidek 222*36da5199SPawel Jakub Dawidek return (0); 223*36da5199SPawel Jakub Dawidek } 224*36da5199SPawel Jakub Dawidek 225*36da5199SPawel Jakub Dawidek int 226*36da5199SPawel Jakub Dawidek cred_recv(int sock, struct cmsgcred *cred) 227*36da5199SPawel Jakub Dawidek { 228*36da5199SPawel Jakub Dawidek unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))]; 229*36da5199SPawel Jakub Dawidek struct msghdr msg; 230*36da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 231*36da5199SPawel Jakub Dawidek struct iovec iov; 232*36da5199SPawel Jakub Dawidek uint8_t dummy; 233*36da5199SPawel Jakub Dawidek 234*36da5199SPawel Jakub Dawidek bzero(credbuf, sizeof(credbuf)); 235*36da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 236*36da5199SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 237*36da5199SPawel Jakub Dawidek 238*36da5199SPawel Jakub Dawidek iov.iov_base = &dummy; 239*36da5199SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 240*36da5199SPawel Jakub Dawidek 241*36da5199SPawel Jakub Dawidek msg.msg_iov = &iov; 242*36da5199SPawel Jakub Dawidek msg.msg_iovlen = 1; 243*36da5199SPawel Jakub Dawidek msg.msg_control = credbuf; 244*36da5199SPawel Jakub Dawidek msg.msg_controllen = sizeof(credbuf); 245*36da5199SPawel Jakub Dawidek 246*36da5199SPawel Jakub Dawidek if (msg_recv(sock, &msg) == -1) 247*36da5199SPawel Jakub Dawidek return (-1); 248*36da5199SPawel Jakub Dawidek 249*36da5199SPawel Jakub Dawidek cmsg = CMSG_FIRSTHDR(&msg); 250*36da5199SPawel Jakub Dawidek if (cmsg == NULL || 251*36da5199SPawel Jakub Dawidek cmsg->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred)) || 252*36da5199SPawel Jakub Dawidek cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDS) { 253*36da5199SPawel Jakub Dawidek errno = EINVAL; 254*36da5199SPawel Jakub Dawidek return (-1); 255*36da5199SPawel Jakub Dawidek } 256*36da5199SPawel Jakub Dawidek bcopy(CMSG_DATA(cmsg), cred, sizeof(*cred)); 257*36da5199SPawel Jakub Dawidek 258*36da5199SPawel Jakub Dawidek return (0); 259*36da5199SPawel Jakub Dawidek } 260*36da5199SPawel Jakub Dawidek 261*36da5199SPawel Jakub Dawidek int 262*36da5199SPawel Jakub Dawidek fd_send(int sock, const int *fds, size_t nfds) 263*36da5199SPawel Jakub Dawidek { 264*36da5199SPawel Jakub Dawidek struct msghdr msg; 265*36da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 266*36da5199SPawel Jakub Dawidek unsigned int i; 267*36da5199SPawel Jakub Dawidek int serrno, ret; 268*36da5199SPawel Jakub Dawidek 269*36da5199SPawel Jakub Dawidek if (nfds == 0 || fds == NULL) { 270*36da5199SPawel Jakub Dawidek errno = EINVAL; 271*36da5199SPawel Jakub Dawidek return (-1); 272*36da5199SPawel Jakub Dawidek } 273*36da5199SPawel Jakub Dawidek 274*36da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 275*36da5199SPawel Jakub Dawidek msg.msg_iov = NULL; 276*36da5199SPawel Jakub Dawidek msg.msg_iovlen = 0; 277*36da5199SPawel Jakub Dawidek msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int)); 278*36da5199SPawel Jakub Dawidek msg.msg_control = calloc(1, msg.msg_controllen); 279*36da5199SPawel Jakub Dawidek if (msg.msg_control == NULL) 280*36da5199SPawel Jakub Dawidek return (-1); 281*36da5199SPawel Jakub Dawidek 282*36da5199SPawel Jakub Dawidek ret = -1; 283*36da5199SPawel Jakub Dawidek 284*36da5199SPawel Jakub Dawidek for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL; 285*36da5199SPawel Jakub Dawidek i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) { 286*36da5199SPawel Jakub Dawidek if (msghdr_add_fd(cmsg, fds[i]) == -1) 287*36da5199SPawel Jakub Dawidek goto end; 288*36da5199SPawel Jakub Dawidek } 289*36da5199SPawel Jakub Dawidek 290*36da5199SPawel Jakub Dawidek if (msg_send(sock, &msg) == -1) 291*36da5199SPawel Jakub Dawidek goto end; 292*36da5199SPawel Jakub Dawidek 293*36da5199SPawel Jakub Dawidek ret = 0; 294*36da5199SPawel Jakub Dawidek end: 295*36da5199SPawel Jakub Dawidek serrno = errno; 296*36da5199SPawel Jakub Dawidek free(msg.msg_control); 297*36da5199SPawel Jakub Dawidek errno = serrno; 298*36da5199SPawel Jakub Dawidek return (ret); 299*36da5199SPawel Jakub Dawidek } 300*36da5199SPawel Jakub Dawidek 301*36da5199SPawel Jakub Dawidek int 302*36da5199SPawel Jakub Dawidek fd_recv(int sock, int *fds, size_t nfds) 303*36da5199SPawel Jakub Dawidek { 304*36da5199SPawel Jakub Dawidek struct msghdr msg; 305*36da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 306*36da5199SPawel Jakub Dawidek unsigned int i; 307*36da5199SPawel Jakub Dawidek int serrno, ret; 308*36da5199SPawel Jakub Dawidek 309*36da5199SPawel Jakub Dawidek if (nfds == 0 || fds == NULL) { 310*36da5199SPawel Jakub Dawidek errno = EINVAL; 311*36da5199SPawel Jakub Dawidek return (-1); 312*36da5199SPawel Jakub Dawidek } 313*36da5199SPawel Jakub Dawidek 314*36da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 315*36da5199SPawel Jakub Dawidek msg.msg_iov = NULL; 316*36da5199SPawel Jakub Dawidek msg.msg_iovlen = 0; 317*36da5199SPawel Jakub Dawidek msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int)); 318*36da5199SPawel Jakub Dawidek msg.msg_control = calloc(1, msg.msg_controllen); 319*36da5199SPawel Jakub Dawidek if (msg.msg_control == NULL) 320*36da5199SPawel Jakub Dawidek return (-1); 321*36da5199SPawel Jakub Dawidek 322*36da5199SPawel Jakub Dawidek ret = -1; 323*36da5199SPawel Jakub Dawidek 324*36da5199SPawel Jakub Dawidek if (msg_recv(sock, &msg) == -1) 325*36da5199SPawel Jakub Dawidek goto end; 326*36da5199SPawel Jakub Dawidek 327*36da5199SPawel Jakub Dawidek for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL; 328*36da5199SPawel Jakub Dawidek i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) { 329*36da5199SPawel Jakub Dawidek fds[i] = msghdr_get_fd(cmsg); 330*36da5199SPawel Jakub Dawidek if (fds[i] < 0) 331*36da5199SPawel Jakub Dawidek break; 332*36da5199SPawel Jakub Dawidek } 333*36da5199SPawel Jakub Dawidek 334*36da5199SPawel Jakub Dawidek if (cmsg != NULL || i < nfds) { 335*36da5199SPawel Jakub Dawidek int fd; 336*36da5199SPawel Jakub Dawidek 337*36da5199SPawel Jakub Dawidek /* 338*36da5199SPawel Jakub Dawidek * We need to close all received descriptors, even if we have 339*36da5199SPawel Jakub Dawidek * different control message (eg. SCM_CREDS) in between. 340*36da5199SPawel Jakub Dawidek */ 341*36da5199SPawel Jakub Dawidek for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 342*36da5199SPawel Jakub Dawidek cmsg = CMSG_NXTHDR(&msg, cmsg)) { 343*36da5199SPawel Jakub Dawidek fd = msghdr_get_fd(cmsg); 344*36da5199SPawel Jakub Dawidek if (fd >= 0) 345*36da5199SPawel Jakub Dawidek close(fd); 346*36da5199SPawel Jakub Dawidek } 347*36da5199SPawel Jakub Dawidek errno = EINVAL; 348*36da5199SPawel Jakub Dawidek goto end; 349*36da5199SPawel Jakub Dawidek } 350*36da5199SPawel Jakub Dawidek 351*36da5199SPawel Jakub Dawidek ret = 0; 352*36da5199SPawel Jakub Dawidek end: 353*36da5199SPawel Jakub Dawidek serrno = errno; 354*36da5199SPawel Jakub Dawidek free(msg.msg_control); 355*36da5199SPawel Jakub Dawidek errno = serrno; 356*36da5199SPawel Jakub Dawidek return (ret); 357*36da5199SPawel Jakub Dawidek } 358*36da5199SPawel Jakub Dawidek 359*36da5199SPawel Jakub Dawidek int 360*36da5199SPawel Jakub Dawidek buf_send(int sock, void *buf, size_t size) 361*36da5199SPawel Jakub Dawidek { 362*36da5199SPawel Jakub Dawidek ssize_t done; 363*36da5199SPawel Jakub Dawidek unsigned char *ptr; 364*36da5199SPawel Jakub Dawidek 365*36da5199SPawel Jakub Dawidek ptr = buf; 366*36da5199SPawel Jakub Dawidek do { 367*36da5199SPawel Jakub Dawidek fd_wait(sock, false); 368*36da5199SPawel Jakub Dawidek done = send(sock, ptr, size, 0); 369*36da5199SPawel Jakub Dawidek if (done == -1) { 370*36da5199SPawel Jakub Dawidek if (errno == EINTR) 371*36da5199SPawel Jakub Dawidek continue; 372*36da5199SPawel Jakub Dawidek return (-1); 373*36da5199SPawel Jakub Dawidek } else if (done == 0) { 374*36da5199SPawel Jakub Dawidek errno = ENOTCONN; 375*36da5199SPawel Jakub Dawidek return (-1); 376*36da5199SPawel Jakub Dawidek } 377*36da5199SPawel Jakub Dawidek size -= done; 378*36da5199SPawel Jakub Dawidek ptr += done; 379*36da5199SPawel Jakub Dawidek } while (size > 0); 380*36da5199SPawel Jakub Dawidek 381*36da5199SPawel Jakub Dawidek return (0); 382*36da5199SPawel Jakub Dawidek } 383*36da5199SPawel Jakub Dawidek 384*36da5199SPawel Jakub Dawidek int 385*36da5199SPawel Jakub Dawidek buf_recv(int sock, void *buf, size_t size) 386*36da5199SPawel Jakub Dawidek { 387*36da5199SPawel Jakub Dawidek ssize_t done; 388*36da5199SPawel Jakub Dawidek unsigned char *ptr; 389*36da5199SPawel Jakub Dawidek 390*36da5199SPawel Jakub Dawidek ptr = buf; 391*36da5199SPawel Jakub Dawidek do { 392*36da5199SPawel Jakub Dawidek fd_wait(sock, true); 393*36da5199SPawel Jakub Dawidek done = recv(sock, ptr, size, 0); 394*36da5199SPawel Jakub Dawidek if (done == -1) { 395*36da5199SPawel Jakub Dawidek if (errno == EINTR) 396*36da5199SPawel Jakub Dawidek continue; 397*36da5199SPawel Jakub Dawidek return (-1); 398*36da5199SPawel Jakub Dawidek } else if (done == 0) { 399*36da5199SPawel Jakub Dawidek errno = ENOTCONN; 400*36da5199SPawel Jakub Dawidek return (-1); 401*36da5199SPawel Jakub Dawidek } 402*36da5199SPawel Jakub Dawidek size -= done; 403*36da5199SPawel Jakub Dawidek ptr += done; 404*36da5199SPawel Jakub Dawidek } while (size > 0); 405*36da5199SPawel Jakub Dawidek 406*36da5199SPawel Jakub Dawidek return (0); 407*36da5199SPawel Jakub Dawidek } 408