X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Funix.c;h=9918db2e683e18f9e880e1025779057bb1289456;hb=3afa94aeca5a0daae40fd7b6cc96b7e4c150c7d8;hp=edca02abf4fa246ad3d33b399ddbd0be252060b8;hpb=3d8e5be7ac1d25649786f56a2bea1740b34aad98;p=lttng-tools.git diff --git a/src/common/unix.c b/src/common/unix.c index edca02abf..9918db2e6 100644 --- a/src/common/unix.c +++ b/src/common/unix.c @@ -1,23 +1,12 @@ /* - * Copyright (C) 2011 - David Goulet - * Mathieu Desnoyers + * Copyright (C) 2011 David Goulet + * Copyright (C) 2011 Mathieu Desnoyers * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2 only, - * as published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _LGPL_SOURCE -#include #include #include #include @@ -25,17 +14,17 @@ #include #include #include -#include #include +#include #include +#include #include "unix.h" /* * Connect to unix socket using the path name. */ -LTTNG_HIDDEN int lttcomm_connect_unix_sock(const char *pathname) { struct sockaddr_un s_un; @@ -85,7 +74,6 @@ error: * Do an accept(2) on the sock and return the new file descriptor. The socket * MUST be bind(2) before. */ -LTTNG_HIDDEN int lttcomm_accept_unix_sock(int sock) { int new_fd; @@ -101,7 +89,6 @@ int lttcomm_accept_unix_sock(int sock) return new_fd; } -LTTNG_HIDDEN int lttcomm_create_anon_unix_socketpair(int *fds) { if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds) < 0) { @@ -115,7 +102,6 @@ int lttcomm_create_anon_unix_socketpair(int *fds) * Creates a AF_UNIX local socket using pathname bind the socket upon creation * and return the fd. */ -LTTNG_HIDDEN int lttcomm_create_unix_sock(const char *pathname) { struct sockaddr_un s_un; @@ -163,7 +149,6 @@ error: /* * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN. */ -LTTNG_HIDDEN int lttcomm_listen_unix_sock(int sock) { int ret; @@ -182,7 +167,6 @@ int lttcomm_listen_unix_sock(int sock) * * Return the size of received data. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) { struct msghdr msg; @@ -190,6 +174,10 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) ssize_t ret = -1; size_t len_last; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = buf; @@ -203,7 +191,7 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) if (ret > 0) { iov[0].iov_base += ret; iov[0].iov_len -= ret; - assert(ret <= len_last); + LTTNG_ASSERT(ret <= len_last); } } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR)); if (ret < 0) { @@ -220,15 +208,21 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) * Receive data of size len in put that data into the buf param. Using recvmsg * API. Only use with sockets set in non-blocking mode. * + * NOTE: EPIPE errors are NOT reported. This call expects the socket to be in a + * poll set. The poll loop will handle the EPIPE original cause. + * * Return the size of received data. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = buf; @@ -243,17 +237,24 @@ retry: goto retry; } else { /* - * Only warn about EPIPE when quiet mode is - * deactivated. - * We consider EPIPE as expected. + * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected. */ - if (errno != EPIPE || !lttng_opt_quiet) { - PERROR("recvmsg"); + if (errno == EAGAIN || errno == EWOULDBLOCK || + errno == EPIPE) { + /* + * Nothing was recv. + */ + ret = 0; + goto end; } + + /* Unexpected error */ + PERROR("recvmsg"); + ret = -1; goto end; } } - ret = len; + end: return ret; } @@ -263,13 +264,16 @@ end: * * Return the size of sent data. */ -LTTNG_HIDDEN ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = (void *) buf; @@ -308,15 +312,21 @@ end: * of the function is that this one does not retry to send on partial sends, * except if the interruption was caused by a signal (EINTR). * + * NOTE: EPIPE errors are NOT reported. This call expects the socket to be in a + * poll set. The poll loop will handle the EPIPE original cause. + * * Return the size of sent data. */ -LTTNG_HIDDEN ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = (void *) buf; @@ -331,17 +341,24 @@ retry: goto retry; } else { /* - * Only warn about EPIPE when quiet mode is - * deactivated. - * We consider EPIPE as expected. + * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected. */ - if (errno != EPIPE || !lttng_opt_quiet) { - PERROR("sendmsg"); + if (errno == EAGAIN || errno == EWOULDBLOCK || + errno == EPIPE) { + /* + * This can happen in non blocking mode. + * Nothing was sent. + */ + ret = 0; + goto end; } + + /* Unexpected error */ + PERROR("sendmsg"); + ret = -1; goto end; } } - ret = len; end: return ret; } @@ -349,7 +366,6 @@ end: /* * Shutdown cleanly a unix socket. */ -LTTNG_HIDDEN int lttcomm_close_unix_sock(int sock) { int ret, closeret; @@ -373,7 +389,6 @@ int lttcomm_close_unix_sock(int sock) * * Returns the size of data sent, or negative error value. */ -LTTNG_HIDDEN ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) { struct msghdr msg; @@ -384,6 +399,10 @@ ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) char tmp[CMSG_SPACE(sizeof_fds)]; char dummy = 0; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); memset(tmp, 0, sizeof(tmp)); @@ -425,6 +444,158 @@ ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) return ret; } +/* + * Send the fd(s) of a payload view over a unix socket. + * + * Returns the size of data sent, or negative error value. + */ +static +ssize_t _lttcomm_send_payload_view_fds_unix_sock(int sock, + struct lttng_payload_view *view, + bool blocking) +{ + int i; + ssize_t ret; + struct lttng_dynamic_array raw_fds; + const int fd_count = lttng_payload_view_get_fd_handle_count(view); + + lttng_dynamic_array_init(&raw_fds, sizeof(int), NULL); + + if (fd_count < 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + /* + * Prepare a contiguous array of file descriptors to send them. + * + * Note that the reference to each fd is released during the iteration; + * we're just getting the numerical value of the fds to conform to the + * syscall's interface. We rely on the fact that "view" must remain + * valid for the duration of the call and that the underlying payload + * owns a reference to the fd_handles. + */ + for (i = 0; i < fd_count; i++) { + struct fd_handle *handle = + lttng_payload_view_pop_fd_handle(view); + const int raw_fd = fd_handle_get_fd(handle); + const int add_ret = lttng_dynamic_array_add_element( + &raw_fds, &raw_fd); + + fd_handle_put(handle); + if (add_ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + } + + if (blocking) { + ret = lttcomm_send_fds_unix_sock(sock, + (const int *) raw_fds.buffer.data, fd_count); + } else { + ret = lttcomm_send_fds_unix_sock_non_block(sock, + (const int *) raw_fds.buffer.data, fd_count); + } + +end: + lttng_dynamic_array_reset(&raw_fds); + return ret; +} + +ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock, + struct lttng_payload_view *view) +{ + return _lttcomm_send_payload_view_fds_unix_sock(sock, view, true); +} + +ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock, + struct lttng_payload_view *view) +{ + return _lttcomm_send_payload_view_fds_unix_sock(sock, view, false); +} + +/* + * Send a message accompanied by fd(s) over a unix socket. + * Only use for non blocking socket. + * + * Returns the size of data sent, or negative error value. + */ +ssize_t lttcomm_send_fds_unix_sock_non_block(int sock, const int *fds, size_t nb_fd) +{ + struct msghdr msg; + struct cmsghdr *cmptr; + struct iovec iov[1]; + ssize_t ret = -1; + unsigned int sizeof_fds = nb_fd * sizeof(int); + char tmp[CMSG_SPACE(sizeof_fds)]; + char dummy = 0; + + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + + memset(&msg, 0, sizeof(msg)); + memset(tmp, 0, sizeof(tmp)); + + if (nb_fd > LTTCOMM_MAX_SEND_FDS) + return -EINVAL; + + msg.msg_control = (caddr_t)tmp; + msg.msg_controllen = CMSG_LEN(sizeof_fds); + + cmptr = CMSG_FIRSTHDR(&msg); + if (!cmptr) { + return -1; + } + + cmptr->cmsg_level = SOL_SOCKET; + cmptr->cmsg_type = SCM_RIGHTS; + cmptr->cmsg_len = CMSG_LEN(sizeof_fds); + memcpy(CMSG_DATA(cmptr), fds, sizeof_fds); + /* Sum of the length of all control messages in the buffer: */ + msg.msg_controllen = cmptr->cmsg_len; + + iov[0].iov_base = &dummy; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + +retry: + ret = sendmsg(sock, &msg, 0); + if (ret < 0) { + if (errno == EINTR) { + goto retry; + } else { + /* + * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected. + */ + if (errno == EAGAIN || errno == EWOULDBLOCK) { + /* + * This can happen in non blocking mode. + * Nothing was sent. + */ + ret = 0; + goto end; + } + + if (errno == EPIPE) { + /* Expected error, pass error to caller */ + DBG3("EPIPE on sendmsg"); + ret = -1; + goto end; + } + + /* Unexpected error */ + PERROR("sendmsg"); + ret = -1; + goto end; + } + } + +end: + return ret; +} + /* * Recv a message accompanied by fd(s) from a unix socket. * @@ -433,7 +604,6 @@ ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) * Expect at most "nb_fd" file descriptors. Returns the number of fd * actually received in nb_fd. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) { struct iovec iov[1]; @@ -441,11 +611,21 @@ ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) struct cmsghdr *cmsg; size_t sizeof_fds = nb_fd * sizeof(int); - /* Account for the struct ucred cmsg in the buffer size */ - char recv_buf[CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred))]; +#ifdef __linux__ +/* Account for the struct ucred cmsg in the buffer size */ +#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred)) +#else +#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) +#endif /* __linux__ */ + + char recv_buf[LTTNG_SOCK_RECV_FDS_BUF_SIZE]; struct msghdr msg; char dummy; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); /* Prepare to receive the structures */ @@ -463,14 +643,269 @@ ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) msg.msg_controllen = CMSG_LEN(sizeof(recv_buf)); msg.msg_flags = 0; - do { - ret = recvmsg(sock, &msg, 0); - } while (ret < 0 && errno == EINTR); +retry: + ret = lttng_recvmsg_nosigpipe(sock, &msg); if (ret < 0) { - PERROR("recvmsg fds"); + if (errno == EINTR) { + goto retry; + } else { + /* We consider EPIPE and EAGAIN as expected. */ + if (!lttng_opt_quiet && + (errno != EPIPE && errno != EAGAIN)) { + PERROR("recvmsg"); + } + goto end; + } + } + + if (ret != 1) { + fprintf(stderr, "Error: Received %zd bytes, expected %d\n", + ret, 1); + goto end; + } + + if (msg.msg_flags & MSG_CTRUNC) { + fprintf(stderr, "Error: Control message truncated.\n"); + ret = -1; + goto end; + } + + /* + * If the socket was configured with SO_PASSCRED, the kernel will add a + * control message (cmsg) to the ancillary data of the unix socket. We + * need to expect a cmsg of the SCM_CREDENTIALS as the first control + * message. + */ + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET) { + fprintf(stderr, "Error: The socket needs to be of type SOL_SOCKET\n"); + ret = -1; + goto end; + } + if (cmsg->cmsg_type == SCM_RIGHTS) { + /* + * We found the controle message for file descriptors, + * now copy the fds to the fds ptr and return success. + */ + if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) { + fprintf(stderr, "Error: Received %zu bytes of" + "ancillary data for FDs, expected %zu\n", + (size_t) cmsg->cmsg_len, + (size_t) CMSG_LEN(sizeof_fds)); + ret = -1; + goto end; + } + memcpy(fds, CMSG_DATA(cmsg), sizeof_fds); + ret = sizeof_fds; + goto end; + } +#ifdef __linux__ + if (cmsg->cmsg_type == SCM_CREDENTIALS) { + /* + * Expect credentials to be sent when expecting fds even + * if no credential were include in the send(). The + * kernel adds them... + */ + ret = -1; + } +#endif /* __linux__ */ + } +end: + return ret; +} + +static +void close_raw_fd(void *ptr) +{ + const int raw_fd = *((const int *) ptr); + + if (raw_fd >= 0) { + const int ret = close(raw_fd); + + if (ret) { + PERROR("Failed to close file descriptor %d", raw_fd); + } + } +} + +static +enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds, + struct lttng_payload *payload) +{ + int i; + enum lttng_error_code ret_code = LTTNG_OK; + const int fd_count = lttng_dynamic_array_get_count(raw_fds); + + for (i = 0; i < fd_count; i++) { + int ret; + struct fd_handle *handle; + int *raw_fd = (int *) lttng_dynamic_array_get_element( + raw_fds, i); + + LTTNG_ASSERT(*raw_fd != -1); + + handle = fd_handle_create(*raw_fd); + if (!handle) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + /* FD ownership transferred to the handle. */ + *raw_fd = -1; + + ret = lttng_payload_push_fd_handle(payload, handle); + fd_handle_put(handle); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + } + +end: + return ret_code; +} + +static +ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd, + struct lttng_payload *payload, bool blocking) +{ + int i = 0; + enum lttng_error_code add_ret; + ssize_t ret; + int default_value = -1; + struct lttng_dynamic_array raw_fds; + + LTTNG_ASSERT(sock); + LTTNG_ASSERT(payload); + LTTNG_ASSERT(nb_fd > 0); + + lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd); + + for (i = 0; i < nb_fd; i++) { + if (lttng_dynamic_array_add_element(&raw_fds, &default_value)) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + } + + if (blocking) { + ret = lttcomm_recv_fds_unix_sock( + sock, (int *) raw_fds.buffer.data, nb_fd); + } else { + ret = lttcomm_recv_fds_unix_sock_non_block( + sock, (int *) raw_fds.buffer.data, nb_fd); + } + + if (ret <= 0) { goto end; } + add_ret = add_fds_to_payload(&raw_fds, payload); + if (add_ret != LTTNG_OK) { + ret = - (int) add_ret; + goto end; + } + +end: + lttng_dynamic_array_reset(&raw_fds); + return ret; +} + +ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd, + struct lttng_payload *payload) +{ + return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true); +} + +ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd, + struct lttng_payload *payload) +{ + return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false); +} + +/* + * Recv a message accompanied by fd(s) from a non-blocking unix socket. + * Only use with non-blocking sockets. + * + * Returns the size of received data, or negative error value. + * + * Expect at most "nb_fd" file descriptors. + * + * Note that based on our comprehension, partial reception of fds is not + * possible since the FDs are actually in the control message. It is all or + * nothing, still the sender side can send the wrong number of fds. + */ +ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd) +{ + struct iovec iov[1]; + ssize_t ret = 0; + struct cmsghdr *cmsg; + size_t sizeof_fds = nb_fd * sizeof(int); + + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + +#ifdef __linux__ +/* Account for the struct ucred cmsg in the buffer size */ +#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred)) +#else +#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) +#endif /* __linux__ */ + + char recv_buf[LTTNG_SOCK_RECV_FDS_BUF_SIZE]; + struct msghdr msg; + char dummy; + + memset(&msg, 0, sizeof(msg)); + + /* Prepare to receive the structures */ + iov[0].iov_base = &dummy; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + cmsg = (struct cmsghdr *) recv_buf; + cmsg->cmsg_len = CMSG_LEN(sizeof_fds); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_LEN(sizeof(recv_buf)); + msg.msg_flags = 0; + +retry: + ret = lttng_recvmsg_nosigpipe(sock, &msg); + if (ret < 0) { + if (errno == EINTR) { + goto retry; + } else { + /* + * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected. + */ + if (errno == EAGAIN || errno == EWOULDBLOCK) { + /* + * This can happen in non blocking mode. + * Nothing was recv. + */ + ret = 0; + goto end; + } + + if (errno == EPIPE) { + /* Expected error, pass error to caller */ + DBG3("EPIPE on recvmsg"); + ret = -1; + goto end; + } + + /* Unexpected error */ + PERROR("recvmsg"); + ret = -1; + goto end; + } + } + if (ret != 1) { fprintf(stderr, "Error: Received %zd bytes, expected %d\n", ret, 1); @@ -512,6 +947,7 @@ ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) ret = sizeof_fds; goto end; } +#ifdef __linux__ if (cmsg->cmsg_type == SCM_CREDENTIALS) { /* * Expect credentials to be sent when expecting fds even @@ -520,6 +956,7 @@ ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) */ ret = -1; } +#endif /* __linux__ */ } end: return ret; @@ -530,29 +967,32 @@ end: * * Returns the size of data sent, or negative error value. */ -LTTNG_HIDDEN -ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) +ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret = -1; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) struct cmsghdr *cmptr; size_t sizeof_cred = sizeof(lttng_sock_cred); char anc_buf[CMSG_SPACE(sizeof_cred)]; lttng_sock_cred *creds; memset(anc_buf, 0, CMSG_SPACE(sizeof_cred) * sizeof(char)); -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ memset(&msg, 0, sizeof(msg)); - iov[0].iov_base = buf; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + + iov[0].iov_base = (void *) buf; iov[0].iov_len = len; msg.msg_iov = iov; msg.msg_iovlen = 1; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) msg.msg_control = (caddr_t) anc_buf; msg.msg_controllen = CMSG_LEN(sizeof_cred); @@ -569,7 +1009,7 @@ ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) LTTNG_SOCK_SET_UID_CRED(creds, geteuid()); LTTNG_SOCK_SET_GID_CRED(creds, getegid()); LTTNG_SOCK_SET_PID_CRED(creds, getpid()); -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ do { ret = sendmsg(sock, &msg, 0); @@ -591,7 +1031,6 @@ ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) * * Returns the size of received data, or negative error value. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, lttng_sock_cred *creds) { @@ -599,19 +1038,18 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, struct iovec iov[1]; ssize_t ret; size_t len_last; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) struct cmsghdr *cmptr; size_t sizeof_cred = sizeof(lttng_sock_cred); char anc_buf[CMSG_SPACE(sizeof_cred)]; -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ - memset(&msg, 0, sizeof(msg)); + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + LTTNG_ASSERT(creds); - /* Not allowed */ - if (creds == NULL) { - ret = -1; - goto end; - } + memset(&msg, 0, sizeof(msg)); /* Prepare to receive the structures */ iov[0].iov_base = buf; @@ -619,10 +1057,10 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, msg.msg_iov = iov; msg.msg_iovlen = 1; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) msg.msg_control = anc_buf; msg.msg_controllen = sizeof(anc_buf); -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ do { len_last = iov[0].iov_len; @@ -630,7 +1068,7 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, if (ret > 0) { iov[0].iov_base += ret; iov[0].iov_len -= ret; - assert(ret <= len_last); + LTTNG_ASSERT(ret <= len_last); } } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR)); if (ret < 0) { @@ -641,7 +1079,7 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, } /* Else ret = 0 meaning an orderly shutdown. */ -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) if (msg.msg_flags & MSG_CTRUNC) { fprintf(stderr, "Error: Control message truncated.\n"); ret = -1; @@ -670,18 +1108,15 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, } memcpy(creds, CMSG_DATA(cmptr), sizeof_cred); -#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__)) - { - int peer_ret; - - peer_ret = getpeereid(sock, &creds->uid, &creds->gid); - if (peer_ret != 0) { - return peer_ret; - } +#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__)) + if (lttng_get_unix_socket_peer_creds(sock, creds)) { + fprintf(stderr, "ARG\n"); + ret = -1; + goto end; } #else #error "Please implement credential support for your OS." -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ end: return ret; @@ -690,8 +1125,7 @@ end: /* * Set socket option to use credentials passing. */ -#ifdef __linux__ -LTTNG_HIDDEN +#if defined(__linux__) || defined(__CYGWIN__) int lttcomm_setsockopt_creds_unix_sock(int sock) { int ret, on = 1; @@ -703,8 +1137,7 @@ int lttcomm_setsockopt_creds_unix_sock(int sock) } return ret; } -#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__)) -LTTNG_HIDDEN +#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__)) int lttcomm_setsockopt_creds_unix_sock(int sock) { return 0;