136da5199SPawel Jakub Dawidek /*- 236da5199SPawel Jakub Dawidek * Copyright (c) 2013 The FreeBSD Foundation 336da5199SPawel Jakub Dawidek * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org> 436da5199SPawel Jakub Dawidek * All rights reserved. 536da5199SPawel Jakub Dawidek * 636da5199SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 736da5199SPawel Jakub Dawidek * the FreeBSD Foundation. 836da5199SPawel Jakub Dawidek * 936da5199SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 1036da5199SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 1136da5199SPawel Jakub Dawidek * are met: 1236da5199SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 1336da5199SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 1436da5199SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 1536da5199SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 1636da5199SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 1736da5199SPawel Jakub Dawidek * 1836da5199SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1936da5199SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2036da5199SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2136da5199SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2236da5199SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2336da5199SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2436da5199SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2536da5199SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2636da5199SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2736da5199SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2836da5199SPawel Jakub Dawidek * SUCH DAMAGE. 2936da5199SPawel Jakub Dawidek */ 3036da5199SPawel Jakub Dawidek 3136da5199SPawel Jakub Dawidek #include <sys/cdefs.h> 3236da5199SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 3336da5199SPawel Jakub Dawidek 3436da5199SPawel Jakub Dawidek #include <sys/types.h> 3536da5199SPawel Jakub Dawidek #include <sys/socket.h> 3636da5199SPawel Jakub Dawidek 3736da5199SPawel Jakub Dawidek #include <errno.h> 3836da5199SPawel Jakub Dawidek #include <fcntl.h> 3936da5199SPawel Jakub Dawidek #include <stdbool.h> 4036da5199SPawel Jakub Dawidek #include <stdint.h> 4136da5199SPawel Jakub Dawidek #include <stdlib.h> 4236da5199SPawel Jakub Dawidek #include <string.h> 4336da5199SPawel Jakub Dawidek #include <unistd.h> 4436da5199SPawel Jakub Dawidek 4536da5199SPawel Jakub Dawidek #ifdef HAVE_PJDLOG 4636da5199SPawel Jakub Dawidek #include <pjdlog.h> 4736da5199SPawel Jakub Dawidek #endif 4836da5199SPawel Jakub Dawidek 4936da5199SPawel Jakub Dawidek #include "common_impl.h" 5036da5199SPawel Jakub Dawidek #include "msgio.h" 5136da5199SPawel Jakub Dawidek 5236da5199SPawel Jakub Dawidek #ifndef HAVE_PJDLOG 5336da5199SPawel Jakub Dawidek #include <assert.h> 5436da5199SPawel Jakub Dawidek #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 5536da5199SPawel Jakub Dawidek #define PJDLOG_RASSERT(expr, ...) assert(expr) 5636da5199SPawel Jakub Dawidek #define PJDLOG_ABORT(...) abort() 5736da5199SPawel Jakub Dawidek #endif 5836da5199SPawel Jakub Dawidek 5936da5199SPawel Jakub Dawidek static int 6036da5199SPawel Jakub Dawidek msghdr_add_fd(struct cmsghdr *cmsg, int fd) 6136da5199SPawel Jakub Dawidek { 6236da5199SPawel Jakub Dawidek 6336da5199SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 6436da5199SPawel Jakub Dawidek 6536da5199SPawel Jakub Dawidek if (!fd_is_valid(fd)) { 6636da5199SPawel Jakub Dawidek errno = EBADF; 6736da5199SPawel Jakub Dawidek return (-1); 6836da5199SPawel Jakub Dawidek } 6936da5199SPawel Jakub Dawidek 7036da5199SPawel Jakub Dawidek cmsg->cmsg_level = SOL_SOCKET; 7136da5199SPawel Jakub Dawidek cmsg->cmsg_type = SCM_RIGHTS; 7236da5199SPawel Jakub Dawidek cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); 7336da5199SPawel Jakub Dawidek bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); 7436da5199SPawel Jakub Dawidek 7536da5199SPawel Jakub Dawidek return (0); 7636da5199SPawel Jakub Dawidek } 7736da5199SPawel Jakub Dawidek 7836da5199SPawel Jakub Dawidek static int 7936da5199SPawel Jakub Dawidek msghdr_get_fd(struct cmsghdr *cmsg) 8036da5199SPawel Jakub Dawidek { 8136da5199SPawel Jakub Dawidek int fd; 8236da5199SPawel Jakub Dawidek 8336da5199SPawel Jakub Dawidek if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || 8436da5199SPawel Jakub Dawidek cmsg->cmsg_type != SCM_RIGHTS || 8536da5199SPawel Jakub Dawidek cmsg->cmsg_len != CMSG_LEN(sizeof(fd))) { 8636da5199SPawel Jakub Dawidek errno = EINVAL; 8736da5199SPawel Jakub Dawidek return (-1); 8836da5199SPawel Jakub Dawidek } 8936da5199SPawel Jakub Dawidek 9036da5199SPawel Jakub Dawidek bcopy(CMSG_DATA(cmsg), &fd, sizeof(fd)); 9136da5199SPawel Jakub Dawidek #ifndef MSG_CMSG_CLOEXEC 9236da5199SPawel Jakub Dawidek /* 9336da5199SPawel Jakub Dawidek * If the MSG_CMSG_CLOEXEC flag is not available we cannot set the 9436da5199SPawel Jakub Dawidek * close-on-exec flag atomically, but we still want to set it for 9536da5199SPawel Jakub Dawidek * consistency. 9636da5199SPawel Jakub Dawidek */ 9736da5199SPawel Jakub Dawidek (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 9836da5199SPawel Jakub Dawidek #endif 9936da5199SPawel Jakub Dawidek 10036da5199SPawel Jakub Dawidek return (fd); 10136da5199SPawel Jakub Dawidek } 10236da5199SPawel Jakub Dawidek 10336da5199SPawel Jakub Dawidek static void 10436da5199SPawel Jakub Dawidek fd_wait(int fd, bool doread) 10536da5199SPawel Jakub Dawidek { 10636da5199SPawel Jakub Dawidek fd_set fds; 10736da5199SPawel Jakub Dawidek 10836da5199SPawel Jakub Dawidek PJDLOG_ASSERT(fd >= 0); 10936da5199SPawel Jakub Dawidek 11036da5199SPawel Jakub Dawidek FD_ZERO(&fds); 11136da5199SPawel Jakub Dawidek FD_SET(fd, &fds); 11236da5199SPawel Jakub Dawidek (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds, 11336da5199SPawel Jakub Dawidek NULL, NULL); 11436da5199SPawel Jakub Dawidek } 11536da5199SPawel Jakub Dawidek 11636da5199SPawel Jakub Dawidek static int 11736da5199SPawel Jakub Dawidek msg_recv(int sock, struct msghdr *msg) 11836da5199SPawel Jakub Dawidek { 11936da5199SPawel Jakub Dawidek int flags; 12036da5199SPawel Jakub Dawidek 12136da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 12236da5199SPawel Jakub Dawidek 12336da5199SPawel Jakub Dawidek #ifdef MSG_CMSG_CLOEXEC 12436da5199SPawel Jakub Dawidek flags = MSG_CMSG_CLOEXEC; 12536da5199SPawel Jakub Dawidek #else 12636da5199SPawel Jakub Dawidek flags = 0; 12736da5199SPawel Jakub Dawidek #endif 12836da5199SPawel Jakub Dawidek 12936da5199SPawel Jakub Dawidek for (;;) { 13036da5199SPawel Jakub Dawidek fd_wait(sock, true); 13136da5199SPawel Jakub Dawidek if (recvmsg(sock, msg, flags) == -1) { 13236da5199SPawel Jakub Dawidek if (errno == EINTR) 13336da5199SPawel Jakub Dawidek continue; 13436da5199SPawel Jakub Dawidek return (-1); 13536da5199SPawel Jakub Dawidek } 13636da5199SPawel Jakub Dawidek break; 13736da5199SPawel Jakub Dawidek } 13836da5199SPawel Jakub Dawidek 13936da5199SPawel Jakub Dawidek return (0); 14036da5199SPawel Jakub Dawidek } 14136da5199SPawel Jakub Dawidek 14236da5199SPawel Jakub Dawidek static int 14336da5199SPawel Jakub Dawidek msg_send(int sock, const struct msghdr *msg) 14436da5199SPawel Jakub Dawidek { 14536da5199SPawel Jakub Dawidek 14636da5199SPawel Jakub Dawidek PJDLOG_ASSERT(sock >= 0); 14736da5199SPawel Jakub Dawidek 14836da5199SPawel Jakub Dawidek for (;;) { 14936da5199SPawel Jakub Dawidek fd_wait(sock, false); 15036da5199SPawel Jakub Dawidek if (sendmsg(sock, msg, 0) == -1) { 15136da5199SPawel Jakub Dawidek if (errno == EINTR) 15236da5199SPawel Jakub Dawidek continue; 15336da5199SPawel Jakub Dawidek return (-1); 15436da5199SPawel Jakub Dawidek } 15536da5199SPawel Jakub Dawidek break; 15636da5199SPawel Jakub Dawidek } 15736da5199SPawel Jakub Dawidek 15836da5199SPawel Jakub Dawidek return (0); 15936da5199SPawel Jakub Dawidek } 16036da5199SPawel Jakub Dawidek 16136da5199SPawel Jakub Dawidek int 16236da5199SPawel Jakub Dawidek cred_send(int sock) 16336da5199SPawel Jakub Dawidek { 16436da5199SPawel Jakub Dawidek unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))]; 16536da5199SPawel Jakub Dawidek struct msghdr msg; 16636da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 16736da5199SPawel Jakub Dawidek struct iovec iov; 16836da5199SPawel Jakub Dawidek uint8_t dummy; 16936da5199SPawel Jakub Dawidek 17036da5199SPawel Jakub Dawidek bzero(credbuf, sizeof(credbuf)); 17136da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 17236da5199SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 17336da5199SPawel Jakub Dawidek 17436da5199SPawel Jakub Dawidek /* 17536da5199SPawel Jakub Dawidek * XXX: We send one byte along with the control message, because 17636da5199SPawel Jakub Dawidek * setting msg_iov to NULL only works if this is the first 17736da5199SPawel Jakub Dawidek * packet send over the socket. Once we send some data we 17836da5199SPawel Jakub Dawidek * won't be able to send credentials anymore. This is most 17936da5199SPawel Jakub Dawidek * likely a kernel bug. 18036da5199SPawel Jakub Dawidek */ 18136da5199SPawel Jakub Dawidek dummy = 0; 18236da5199SPawel Jakub Dawidek iov.iov_base = &dummy; 18336da5199SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 18436da5199SPawel Jakub Dawidek 18536da5199SPawel Jakub Dawidek msg.msg_iov = &iov; 18636da5199SPawel Jakub Dawidek msg.msg_iovlen = 1; 18736da5199SPawel Jakub Dawidek msg.msg_control = credbuf; 18836da5199SPawel Jakub Dawidek msg.msg_controllen = sizeof(credbuf); 18936da5199SPawel Jakub Dawidek 19036da5199SPawel Jakub Dawidek cmsg = CMSG_FIRSTHDR(&msg); 19136da5199SPawel Jakub Dawidek cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred)); 19236da5199SPawel Jakub Dawidek cmsg->cmsg_level = SOL_SOCKET; 19336da5199SPawel Jakub Dawidek cmsg->cmsg_type = SCM_CREDS; 19436da5199SPawel Jakub Dawidek 19536da5199SPawel Jakub Dawidek if (msg_send(sock, &msg) == -1) 19636da5199SPawel Jakub Dawidek return (-1); 19736da5199SPawel Jakub Dawidek 19836da5199SPawel Jakub Dawidek return (0); 19936da5199SPawel Jakub Dawidek } 20036da5199SPawel Jakub Dawidek 20136da5199SPawel Jakub Dawidek int 20236da5199SPawel Jakub Dawidek cred_recv(int sock, struct cmsgcred *cred) 20336da5199SPawel Jakub Dawidek { 20436da5199SPawel Jakub Dawidek unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))]; 20536da5199SPawel Jakub Dawidek struct msghdr msg; 20636da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 20736da5199SPawel Jakub Dawidek struct iovec iov; 20836da5199SPawel Jakub Dawidek uint8_t dummy; 20936da5199SPawel Jakub Dawidek 21036da5199SPawel Jakub Dawidek bzero(credbuf, sizeof(credbuf)); 21136da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 21236da5199SPawel Jakub Dawidek bzero(&iov, sizeof(iov)); 21336da5199SPawel Jakub Dawidek 21436da5199SPawel Jakub Dawidek iov.iov_base = &dummy; 21536da5199SPawel Jakub Dawidek iov.iov_len = sizeof(dummy); 21636da5199SPawel Jakub Dawidek 21736da5199SPawel Jakub Dawidek msg.msg_iov = &iov; 21836da5199SPawel Jakub Dawidek msg.msg_iovlen = 1; 21936da5199SPawel Jakub Dawidek msg.msg_control = credbuf; 22036da5199SPawel Jakub Dawidek msg.msg_controllen = sizeof(credbuf); 22136da5199SPawel Jakub Dawidek 22236da5199SPawel Jakub Dawidek if (msg_recv(sock, &msg) == -1) 22336da5199SPawel Jakub Dawidek return (-1); 22436da5199SPawel Jakub Dawidek 22536da5199SPawel Jakub Dawidek cmsg = CMSG_FIRSTHDR(&msg); 22636da5199SPawel Jakub Dawidek if (cmsg == NULL || 22736da5199SPawel Jakub Dawidek cmsg->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred)) || 22836da5199SPawel Jakub Dawidek cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDS) { 22936da5199SPawel Jakub Dawidek errno = EINVAL; 23036da5199SPawel Jakub Dawidek return (-1); 23136da5199SPawel Jakub Dawidek } 23236da5199SPawel Jakub Dawidek bcopy(CMSG_DATA(cmsg), cred, sizeof(*cred)); 23336da5199SPawel Jakub Dawidek 23436da5199SPawel Jakub Dawidek return (0); 23536da5199SPawel Jakub Dawidek } 23636da5199SPawel Jakub Dawidek 23736da5199SPawel Jakub Dawidek int 23836da5199SPawel Jakub Dawidek fd_send(int sock, const int *fds, size_t nfds) 23936da5199SPawel Jakub Dawidek { 24036da5199SPawel Jakub Dawidek struct msghdr msg; 24136da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 24236da5199SPawel Jakub Dawidek unsigned int i; 24336da5199SPawel Jakub Dawidek int serrno, ret; 24436da5199SPawel Jakub Dawidek 24536da5199SPawel Jakub Dawidek if (nfds == 0 || fds == NULL) { 24636da5199SPawel Jakub Dawidek errno = EINVAL; 24736da5199SPawel Jakub Dawidek return (-1); 24836da5199SPawel Jakub Dawidek } 24936da5199SPawel Jakub Dawidek 25036da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 25136da5199SPawel Jakub Dawidek msg.msg_iov = NULL; 25236da5199SPawel Jakub Dawidek msg.msg_iovlen = 0; 25336da5199SPawel Jakub Dawidek msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int)); 25436da5199SPawel Jakub Dawidek msg.msg_control = calloc(1, msg.msg_controllen); 25536da5199SPawel Jakub Dawidek if (msg.msg_control == NULL) 25636da5199SPawel Jakub Dawidek return (-1); 25736da5199SPawel Jakub Dawidek 25836da5199SPawel Jakub Dawidek ret = -1; 25936da5199SPawel Jakub Dawidek 26036da5199SPawel Jakub Dawidek for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL; 26136da5199SPawel Jakub Dawidek i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) { 26236da5199SPawel Jakub Dawidek if (msghdr_add_fd(cmsg, fds[i]) == -1) 26336da5199SPawel Jakub Dawidek goto end; 26436da5199SPawel Jakub Dawidek } 26536da5199SPawel Jakub Dawidek 26636da5199SPawel Jakub Dawidek if (msg_send(sock, &msg) == -1) 26736da5199SPawel Jakub Dawidek goto end; 26836da5199SPawel Jakub Dawidek 26936da5199SPawel Jakub Dawidek ret = 0; 27036da5199SPawel Jakub Dawidek end: 27136da5199SPawel Jakub Dawidek serrno = errno; 27236da5199SPawel Jakub Dawidek free(msg.msg_control); 27336da5199SPawel Jakub Dawidek errno = serrno; 27436da5199SPawel Jakub Dawidek return (ret); 27536da5199SPawel Jakub Dawidek } 27636da5199SPawel Jakub Dawidek 27736da5199SPawel Jakub Dawidek int 27836da5199SPawel Jakub Dawidek fd_recv(int sock, int *fds, size_t nfds) 27936da5199SPawel Jakub Dawidek { 28036da5199SPawel Jakub Dawidek struct msghdr msg; 28136da5199SPawel Jakub Dawidek struct cmsghdr *cmsg; 28236da5199SPawel Jakub Dawidek unsigned int i; 28336da5199SPawel Jakub Dawidek int serrno, ret; 28436da5199SPawel Jakub Dawidek 28536da5199SPawel Jakub Dawidek if (nfds == 0 || fds == NULL) { 28636da5199SPawel Jakub Dawidek errno = EINVAL; 28736da5199SPawel Jakub Dawidek return (-1); 28836da5199SPawel Jakub Dawidek } 28936da5199SPawel Jakub Dawidek 29036da5199SPawel Jakub Dawidek bzero(&msg, sizeof(msg)); 29136da5199SPawel Jakub Dawidek msg.msg_iov = NULL; 29236da5199SPawel Jakub Dawidek msg.msg_iovlen = 0; 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 30336da5199SPawel Jakub Dawidek for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL; 30436da5199SPawel Jakub Dawidek i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) { 30536da5199SPawel Jakub Dawidek fds[i] = msghdr_get_fd(cmsg); 30636da5199SPawel Jakub Dawidek if (fds[i] < 0) 30736da5199SPawel Jakub Dawidek break; 30836da5199SPawel Jakub Dawidek } 30936da5199SPawel Jakub Dawidek 31036da5199SPawel Jakub Dawidek if (cmsg != NULL || i < nfds) { 31136da5199SPawel Jakub Dawidek int fd; 31236da5199SPawel Jakub Dawidek 31336da5199SPawel Jakub Dawidek /* 31436da5199SPawel Jakub Dawidek * We need to close all received descriptors, even if we have 31536da5199SPawel Jakub Dawidek * different control message (eg. SCM_CREDS) in between. 31636da5199SPawel Jakub Dawidek */ 31736da5199SPawel Jakub Dawidek for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 31836da5199SPawel Jakub Dawidek cmsg = CMSG_NXTHDR(&msg, cmsg)) { 31936da5199SPawel Jakub Dawidek fd = msghdr_get_fd(cmsg); 32036da5199SPawel Jakub Dawidek if (fd >= 0) 32136da5199SPawel Jakub Dawidek close(fd); 32236da5199SPawel Jakub Dawidek } 32336da5199SPawel Jakub Dawidek errno = EINVAL; 32436da5199SPawel Jakub Dawidek goto end; 32536da5199SPawel Jakub Dawidek } 32636da5199SPawel Jakub Dawidek 32736da5199SPawel Jakub Dawidek ret = 0; 32836da5199SPawel Jakub Dawidek end: 32936da5199SPawel Jakub Dawidek serrno = errno; 33036da5199SPawel Jakub Dawidek free(msg.msg_control); 33136da5199SPawel Jakub Dawidek errno = serrno; 33236da5199SPawel Jakub Dawidek return (ret); 33336da5199SPawel Jakub Dawidek } 33436da5199SPawel Jakub Dawidek 33536da5199SPawel Jakub Dawidek int 33636da5199SPawel Jakub Dawidek buf_send(int sock, void *buf, size_t size) 33736da5199SPawel Jakub Dawidek { 33836da5199SPawel Jakub Dawidek ssize_t done; 33936da5199SPawel Jakub Dawidek unsigned char *ptr; 34036da5199SPawel Jakub Dawidek 34136da5199SPawel Jakub Dawidek ptr = buf; 34236da5199SPawel Jakub Dawidek do { 34336da5199SPawel Jakub Dawidek fd_wait(sock, false); 34436da5199SPawel Jakub Dawidek done = send(sock, ptr, size, 0); 34536da5199SPawel Jakub Dawidek if (done == -1) { 34636da5199SPawel Jakub Dawidek if (errno == EINTR) 34736da5199SPawel Jakub Dawidek continue; 34836da5199SPawel Jakub Dawidek return (-1); 34936da5199SPawel Jakub Dawidek } else if (done == 0) { 35036da5199SPawel Jakub Dawidek errno = ENOTCONN; 35136da5199SPawel Jakub Dawidek return (-1); 35236da5199SPawel Jakub Dawidek } 35336da5199SPawel Jakub Dawidek size -= done; 35436da5199SPawel Jakub Dawidek ptr += done; 35536da5199SPawel Jakub Dawidek } while (size > 0); 35636da5199SPawel Jakub Dawidek 35736da5199SPawel Jakub Dawidek return (0); 35836da5199SPawel Jakub Dawidek } 35936da5199SPawel Jakub Dawidek 36036da5199SPawel Jakub Dawidek int 36136da5199SPawel Jakub Dawidek buf_recv(int sock, void *buf, size_t size) 36236da5199SPawel Jakub Dawidek { 36336da5199SPawel Jakub Dawidek ssize_t done; 36436da5199SPawel Jakub Dawidek unsigned char *ptr; 36536da5199SPawel Jakub Dawidek 36636da5199SPawel Jakub Dawidek ptr = buf; 367*7f7fe890SPawel Jakub Dawidek while (size > 0) { 36836da5199SPawel Jakub Dawidek fd_wait(sock, true); 36936da5199SPawel Jakub Dawidek done = recv(sock, ptr, size, 0); 37036da5199SPawel Jakub Dawidek if (done == -1) { 37136da5199SPawel Jakub Dawidek if (errno == EINTR) 37236da5199SPawel Jakub Dawidek continue; 37336da5199SPawel Jakub Dawidek return (-1); 37436da5199SPawel Jakub Dawidek } else if (done == 0) { 37536da5199SPawel Jakub Dawidek errno = ENOTCONN; 37636da5199SPawel Jakub Dawidek return (-1); 37736da5199SPawel Jakub Dawidek } 37836da5199SPawel Jakub Dawidek size -= done; 37936da5199SPawel Jakub Dawidek ptr += done; 380*7f7fe890SPawel Jakub Dawidek } 38136da5199SPawel Jakub Dawidek 38236da5199SPawel Jakub Dawidek return (0); 38336da5199SPawel Jakub Dawidek } 384