From 2a8652701d0ce7185c60cc05e407950e87a6c150 Mon Sep 17 00:00:00 2001 From: Dave Wallace Date: Wed, 7 Feb 2018 21:00:42 -0500 Subject: LD_PRELOAD: Refactor nomenclature (vcom -> ldp). Change-Id: Id3891fe2873b631f8f69c1ca2905968130678561 Signed-off-by: Dave Wallace --- src/vcl/ldp_socket_wrapper.c | 909 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 909 insertions(+) create mode 100644 src/vcl/ldp_socket_wrapper.c (limited to 'src/vcl/ldp_socket_wrapper.c') diff --git a/src/vcl/ldp_socket_wrapper.c b/src/vcl/ldp_socket_wrapper.c new file mode 100644 index 00000000000..981125850ff --- /dev/null +++ b/src/vcl/ldp_socket_wrapper.c @@ -0,0 +1,909 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Copyright (c) 2005-2008 Jelmer Vernooij + * Copyright (C) 2006-2014 Stefan Metzmacher + * Copyright (C) 2013-2014 Andreas Schneider + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + Socket wrapper library. Passes all socket communication over + unix domain sockets if the environment variable SOCKET_WRAPPER_DIR + is set. +*/ + +#include +#include + +#include +#include +#include +#include + +#include + + +enum swrap_dbglvl_e +{ + SWRAP_LOG_ERROR = 0, + SWRAP_LOG_WARN, + SWRAP_LOG_DEBUG, + SWRAP_LOG_TRACE +}; + + +/* Macros for accessing mutexes */ +#define SWRAP_LOCK(m) do { \ + pthread_mutex_lock(&(m ## _mutex)); \ +} while(0) + +#define SWRAP_UNLOCK(m) do { \ + pthread_mutex_unlock(&(m ## _mutex)); \ +} while(0) + +/* Add new global locks here please */ +#define SWRAP_LOCK_ALL \ + SWRAP_LOCK(libc_symbol_binding); \ + +#define SWRAP_UNLOCK_ALL \ + SWRAP_UNLOCK(libc_symbol_binding); \ + + + +/* The mutex for accessing the global libc.symbols */ +static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Function prototypes */ + +#ifdef NDEBUG +#define SWRAP_LOG(...) +#else +static unsigned int swrap_log_lvl = SWRAP_LOG_WARN; + +static void +swrap_log (enum swrap_dbglvl_e dbglvl, const char *func, + const char *format, ...) +PRINTF_ATTRIBUTE (3, 4); +#define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__) + + static void + swrap_log (enum swrap_dbglvl_e dbglvl, + const char *func, const char *format, ...) +{ + char buffer[1024]; + va_list va; + + va_start (va, format); + vsnprintf (buffer, sizeof (buffer), format, va); + va_end (va); + + if (dbglvl <= swrap_log_lvl) + { + switch (dbglvl) + { + case SWRAP_LOG_ERROR: + fprintf (stderr, + "SWRAP_ERROR(%d) - %s: %s\n", + (int) getpid (), func, buffer); + break; + case SWRAP_LOG_WARN: + fprintf (stderr, + "SWRAP_WARN(%d) - %s: %s\n", + (int) getpid (), func, buffer); + break; + case SWRAP_LOG_DEBUG: + fprintf (stderr, + "SWRAP_DEBUG(%d) - %s: %s\n", + (int) getpid (), func, buffer); + break; + case SWRAP_LOG_TRACE: + fprintf (stderr, + "SWRAP_TRACE(%d) - %s: %s\n", + (int) getpid (), func, buffer); + break; + } + } +} +#endif + + +/********************************************************* + * SWRAP LOADING LIBC FUNCTIONS + *********************************************************/ + +typedef int (*__libc_accept4) (int sockfd, + struct sockaddr * addr, + socklen_t * addrlen, int flags); +typedef int (*__libc_accept) (int sockfd, + struct sockaddr * addr, socklen_t * addrlen); +typedef int (*__libc_bind) (int sockfd, + const struct sockaddr * addr, socklen_t addrlen); +typedef int (*__libc_close) (int fd); +typedef int (*__libc_connect) (int sockfd, + const struct sockaddr * addr, + socklen_t addrlen); + +#if 0 +/* TBD: dup and dup2 to be implemented later */ +typedef int (*__libc_dup) (int fd); +typedef int (*__libc_dup2) (int oldfd, int newfd); +#endif + +typedef int (*__libc_fcntl) (int fd, int cmd, ...); +typedef FILE *(*__libc_fopen) (const char *name, const char *mode); +#ifdef HAVE_FOPEN64 +typedef FILE *(*__libc_fopen64) (const char *name, const char *mode); +#endif +#ifdef HAVE_EVENTFD +typedef int (*__libc_eventfd) (int count, int flags); +#endif +typedef int (*__libc_getpeername) (int sockfd, + struct sockaddr * addr, + socklen_t * addrlen); +typedef int (*__libc_getsockname) (int sockfd, + struct sockaddr * addr, + socklen_t * addrlen); +typedef int (*__libc_getsockopt) (int sockfd, + int level, + int optname, + void *optval, socklen_t * optlen); +typedef int (*__libc_ioctl) (int d, unsigned long int request, ...); +typedef int (*__libc_listen) (int sockfd, int backlog); +typedef int (*__libc_open) (const char *pathname, int flags, mode_t mode); +#ifdef HAVE_OPEN64 +typedef int (*__libc_open64) (const char *pathname, int flags, mode_t mode); +#endif /* HAVE_OPEN64 */ +typedef int (*__libc_openat) (int dirfd, const char *path, int flags, ...); +typedef int (*__libc_pipe) (int pipefd[2]); +typedef int (*__libc_read) (int fd, void *buf, size_t count); +typedef ssize_t (*__libc_readv) (int fd, const struct iovec * iov, + int iovcnt); +typedef int (*__libc_recv) (int sockfd, void *buf, size_t len, int flags); +typedef int (*__libc_recvfrom) (int sockfd, + void *buf, + size_t len, + int flags, + struct sockaddr * src_addr, + socklen_t * addrlen); +typedef int (*__libc_recvmsg) (int sockfd, const struct msghdr * msg, + int flags); +typedef int (*__libc_send) (int sockfd, const void *buf, size_t len, + int flags); +typedef ssize_t (*__libc_sendfile) (int out_fd, int in_fd, off_t * offset, + size_t len); +typedef int (*__libc_sendmsg) (int sockfd, const struct msghdr * msg, + int flags); +typedef int (*__libc_sendto) (int sockfd, const void *buf, size_t len, + int flags, const struct sockaddr * dst_addr, + socklen_t addrlen); +typedef int (*__libc_setsockopt) (int sockfd, int level, int optname, + const void *optval, socklen_t optlen); +#ifdef HAVE_SIGNALFD +typedef int (*__libc_signalfd) (int fd, const sigset_t * mask, int flags); +#endif +typedef int (*__libc_socket) (int domain, int type, int protocol); +typedef int (*__libc_socketpair) (int domain, int type, int protocol, + int sv[2]); +#ifdef HAVE_TIMERFD_CREATE +typedef int (*__libc_timerfd_create) (int clockid, int flags); +#endif +typedef ssize_t (*__libc_write) (int fd, const void *buf, size_t count); +typedef ssize_t (*__libc_writev) (int fd, const struct iovec * iov, + int iovcnt); + +typedef int (*__libc_shutdown) (int fd, int how); + +typedef int (*__libc_select) (int __nfds, fd_set * __restrict __readfds, + fd_set * __restrict __writefds, + fd_set * __restrict __exceptfds, + struct timeval * __restrict __timeout); + +#ifdef __USE_XOPEN2K +typedef int (*__libc_pselect) (int __nfds, fd_set * __restrict __readfds, + fd_set * __restrict __writefds, + fd_set * __restrict __exceptfds, + const struct timespec * __restrict __timeout, + const __sigset_t * __restrict __sigmask); +#endif + +typedef int (*__libc_epoll_create) (int __size); + +typedef int (*__libc_epoll_create1) (int __flags); + +typedef int (*__libc_epoll_ctl) (int __epfd, int __op, int __fd, + struct epoll_event * __event); + +typedef int (*__libc_epoll_wait) (int __epfd, struct epoll_event * __events, + int __maxevents, int __timeout); + +typedef int (*__libc_epoll_pwait) (int __epfd, struct epoll_event * __events, + int __maxevents, int __timeout, + const __sigset_t * __ss); + +typedef int (*__libc_poll) (struct pollfd * __fds, nfds_t __nfds, + int __timeout); + +#ifdef __USE_GNU +typedef int (*__libc_ppoll) (struct pollfd * __fds, nfds_t __nfds, + const struct timespec * __timeout, + const __sigset_t * __ss); +#endif + + +#define SWRAP_SYMBOL_ENTRY(i) \ + union { \ + __libc_##i f; \ + void *obj; \ + } _libc_##i + +struct swrap_libc_symbols +{ + SWRAP_SYMBOL_ENTRY (accept4); + SWRAP_SYMBOL_ENTRY (accept); + SWRAP_SYMBOL_ENTRY (bind); + SWRAP_SYMBOL_ENTRY (close); + SWRAP_SYMBOL_ENTRY (connect); +#if 0 + /* TBD: dup and dup2 to be implemented later */ + SWRAP_SYMBOL_ENTRY (dup); + SWRAP_SYMBOL_ENTRY (dup2); +#endif + SWRAP_SYMBOL_ENTRY (fcntl); + SWRAP_SYMBOL_ENTRY (fopen); +#ifdef HAVE_FOPEN64 + SWRAP_SYMBOL_ENTRY (fopen64); +#endif +#ifdef HAVE_EVENTFD + SWRAP_SYMBOL_ENTRY (eventfd); +#endif + SWRAP_SYMBOL_ENTRY (getpeername); + SWRAP_SYMBOL_ENTRY (getsockname); + SWRAP_SYMBOL_ENTRY (getsockopt); + SWRAP_SYMBOL_ENTRY (ioctl); + SWRAP_SYMBOL_ENTRY (listen); + SWRAP_SYMBOL_ENTRY (open); +#ifdef HAVE_OPEN64 + SWRAP_SYMBOL_ENTRY (open64); +#endif + SWRAP_SYMBOL_ENTRY (openat); + SWRAP_SYMBOL_ENTRY (pipe); + SWRAP_SYMBOL_ENTRY (read); + SWRAP_SYMBOL_ENTRY (readv); + SWRAP_SYMBOL_ENTRY (recv); + SWRAP_SYMBOL_ENTRY (recvfrom); + SWRAP_SYMBOL_ENTRY (recvmsg); + SWRAP_SYMBOL_ENTRY (send); + SWRAP_SYMBOL_ENTRY (sendfile); + SWRAP_SYMBOL_ENTRY (sendmsg); + SWRAP_SYMBOL_ENTRY (sendto); + SWRAP_SYMBOL_ENTRY (setsockopt); +#ifdef HAVE_SIGNALFD + SWRAP_SYMBOL_ENTRY (signalfd); +#endif + SWRAP_SYMBOL_ENTRY (socket); + SWRAP_SYMBOL_ENTRY (socketpair); +#ifdef HAVE_TIMERFD_CREATE + SWRAP_SYMBOL_ENTRY (timerfd_create); +#endif + SWRAP_SYMBOL_ENTRY (write); + SWRAP_SYMBOL_ENTRY (writev); + + SWRAP_SYMBOL_ENTRY (shutdown); + SWRAP_SYMBOL_ENTRY (select); +#ifdef __USE_XOPEN2K + SWRAP_SYMBOL_ENTRY (pselect); +#endif + SWRAP_SYMBOL_ENTRY (epoll_create); + SWRAP_SYMBOL_ENTRY (epoll_create1); + SWRAP_SYMBOL_ENTRY (epoll_ctl); + SWRAP_SYMBOL_ENTRY (epoll_wait); + SWRAP_SYMBOL_ENTRY (epoll_pwait); + SWRAP_SYMBOL_ENTRY (poll); +#ifdef __USE_GNU + SWRAP_SYMBOL_ENTRY (ppoll); +#endif +}; + +struct swrap +{ + struct + { + void *handle; + void *socket_handle; + struct swrap_libc_symbols symbols; + } libc; +}; + +static struct swrap swrap; + +#define LIBC_NAME "libc.so" + +enum swrap_lib +{ + SWRAP_LIBC, +}; + +#ifndef NDEBUG +static const char * +swrap_str_lib (enum swrap_lib lib) +{ + switch (lib) + { + case SWRAP_LIBC: + return "libc"; + } + + /* Compiler would warn us about unhandled enum value if we get here */ + return "unknown"; +} +#endif + +static void * +swrap_load_lib_handle (enum swrap_lib lib) +{ + int flags = RTLD_LAZY; + void *handle = NULL; + int i; + +#ifdef RTLD_DEEPBIND + flags |= RTLD_DEEPBIND; +#endif + + switch (lib) + { + case SWRAP_LIBC: + handle = swrap.libc.handle; +#ifdef LIBC_SO + if (handle == NULL) + { + handle = dlopen (LIBC_SO, flags); + + swrap.libc.handle = handle; + } +#endif + if (handle == NULL) + { + for (i = 10; i >= 0; i--) + { + char soname[256] = { 0 }; + + snprintf (soname, sizeof (soname), "libc.so.%d", i); + handle = dlopen (soname, flags); + if (handle != NULL) + { + break; + } + } + + swrap.libc.handle = handle; + } + break; + } + + if (handle == NULL) + { + SWRAP_LOG (SWRAP_LOG_ERROR, + "Failed to dlopen library: %s\n", dlerror ()); + exit (-1); + } + + return handle; +} + +static void * +_swrap_bind_symbol (enum swrap_lib lib, const char *fn_name) +{ + void *handle; + void *func; + + handle = swrap_load_lib_handle (lib); + + func = dlsym (handle, fn_name); + if (func == NULL) + { + SWRAP_LOG (SWRAP_LOG_ERROR, + "Failed to find %s: %s\n", fn_name, dlerror ()); + exit (-1); + } + + SWRAP_LOG (SWRAP_LOG_TRACE, + "Loaded %s from %s", fn_name, swrap_str_lib (lib)); + + return func; +} + +#define swrap_bind_symbol_libc(sym_name) \ + SWRAP_LOCK(libc_symbol_binding); \ + if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ + swrap.libc.symbols._libc_##sym_name.obj = \ + _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \ + } \ + SWRAP_UNLOCK(libc_symbol_binding) + +/* + * IMPORTANT + * + * Functions especially from libc need to be loaded individually, you can't load + * all at once or gdb will segfault at startup. The same applies to valgrind and + * has probably something todo with with the linker. + * So we need load each function at the point it is called the first time. + */ +int +libc_accept4 (int sockfd, + struct sockaddr *addr, socklen_t * addrlen, int flags) +{ + swrap_bind_symbol_libc (accept4); + + return swrap.libc.symbols._libc_accept4.f (sockfd, addr, addrlen, flags); +} + +int +libc_accept (int sockfd, struct sockaddr *addr, socklen_t * addrlen) +{ + swrap_bind_symbol_libc (accept); + + return swrap.libc.symbols._libc_accept.f (sockfd, addr, addrlen); +} + +int +libc_bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + swrap_bind_symbol_libc (bind); + + return swrap.libc.symbols._libc_bind.f (sockfd, addr, addrlen); +} + +int +libc_close (int fd) +{ + swrap_bind_symbol_libc (close); + + return swrap.libc.symbols._libc_close.f (fd); +} + +int +libc_connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + swrap_bind_symbol_libc (connect); + + return swrap.libc.symbols._libc_connect.f (sockfd, addr, addrlen); +} + +#if 0 +/* TBD: dup and dup2 to be implemented later */ +int +libc_dup (int fd) +{ + swrap_bind_symbol_libc (dup); + + return swrap.libc.symbols._libc_dup.f (fd); +} + +int +libc_dup2 (int oldfd, int newfd) +{ + swrap_bind_symbol_libc (dup2); + + return swrap.libc.symbols._libc_dup2.f (oldfd, newfd); +} +#endif + +#ifdef HAVE_EVENTFD +int +libc_eventfd (int count, int flags) +{ + swrap_bind_symbol_libc (eventfd); + + return swrap.libc.symbols._libc_eventfd.f (count, flags); +} +#endif + +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int +libc_vfcntl (int fd, int cmd, va_list ap) +{ + long int args[4]; + int rc; + int i; + + swrap_bind_symbol_libc (fcntl); + + for (i = 0; i < 4; i++) + { + args[i] = va_arg (ap, long int); + } + + rc = swrap.libc.symbols._libc_fcntl.f (fd, + cmd, + args[0], args[1], args[2], args[3]); + + return rc; +} + +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int +libc_vioctl (int fd, int cmd, va_list ap) +{ + long int args[4]; + int rc; + int i; + + swrap_bind_symbol_libc (ioctl); + + for (i = 0; i < 4; i++) + { + args[i] = va_arg (ap, long int); + } + + rc = swrap.libc.symbols._libc_ioctl.f (fd, + cmd, + args[0], args[1], args[2], args[3]); + + return rc; +} + +int +libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen) +{ + swrap_bind_symbol_libc (getpeername); + + return swrap.libc.symbols._libc_getpeername.f (sockfd, addr, addrlen); +} + +int +libc_getsockname (int sockfd, struct sockaddr *addr, socklen_t * addrlen) +{ + swrap_bind_symbol_libc (getsockname); + + return swrap.libc.symbols._libc_getsockname.f (sockfd, addr, addrlen); +} + +int +libc_getsockopt (int sockfd, + int level, int optname, void *optval, socklen_t * optlen) +{ + swrap_bind_symbol_libc (getsockopt); + + return swrap.libc.symbols._libc_getsockopt.f (sockfd, + level, + optname, optval, optlen); +} + +int +libc_listen (int sockfd, int backlog) +{ + swrap_bind_symbol_libc (listen); + + return swrap.libc.symbols._libc_listen.f (sockfd, backlog); +} + +/* TBD: libc_read() should return ssize_t not an int */ +int +libc_read (int fd, void *buf, size_t count) +{ + swrap_bind_symbol_libc (read); + + return swrap.libc.symbols._libc_read.f (fd, buf, count); +} + +ssize_t +libc_readv (int fd, const struct iovec * iov, int iovcnt) +{ + swrap_bind_symbol_libc (readv); + + return swrap.libc.symbols._libc_readv.f (fd, iov, iovcnt); +} + +int +libc_recv (int sockfd, void *buf, size_t len, int flags) +{ + swrap_bind_symbol_libc (recv); + + return swrap.libc.symbols._libc_recv.f (sockfd, buf, len, flags); +} + +int +libc_recvfrom (int sockfd, + void *buf, + size_t len, + int flags, struct sockaddr *src_addr, socklen_t * addrlen) +{ + swrap_bind_symbol_libc (recvfrom); + + return swrap.libc.symbols._libc_recvfrom.f (sockfd, + buf, + len, flags, src_addr, addrlen); +} + +int +libc_recvmsg (int sockfd, struct msghdr *msg, int flags) +{ + swrap_bind_symbol_libc (recvmsg); + + return swrap.libc.symbols._libc_recvmsg.f (sockfd, msg, flags); +} + +int +libc_send (int sockfd, const void *buf, size_t len, int flags) +{ + swrap_bind_symbol_libc (send); + + return swrap.libc.symbols._libc_send.f (sockfd, buf, len, flags); +} + +ssize_t +libc_sendfile (int out_fd, int in_fd, off_t * offset, size_t len) +{ + swrap_bind_symbol_libc (sendfile); + + return swrap.libc.symbols._libc_sendfile.f (out_fd, in_fd, offset, len); +} + +int +libc_sendmsg (int sockfd, const struct msghdr *msg, int flags) +{ + swrap_bind_symbol_libc (sendmsg); + + return swrap.libc.symbols._libc_sendmsg.f (sockfd, msg, flags); +} + +int +libc_sendto (int sockfd, + const void *buf, + size_t len, + int flags, const struct sockaddr *dst_addr, socklen_t addrlen) +{ + swrap_bind_symbol_libc (sendto); + + return swrap.libc.symbols._libc_sendto.f (sockfd, + buf, + len, flags, dst_addr, addrlen); +} + +int +libc_setsockopt (int sockfd, + int level, int optname, const void *optval, socklen_t optlen) +{ + swrap_bind_symbol_libc (setsockopt); + + return swrap.libc.symbols._libc_setsockopt.f (sockfd, + level, + optname, optval, optlen); +} + +int +libc_socket (int domain, int type, int protocol) +{ + swrap_bind_symbol_libc (socket); + + return swrap.libc.symbols._libc_socket.f (domain, type, protocol); +} + +int +libc_socketpair (int domain, int type, int protocol, int sv[2]) +{ + swrap_bind_symbol_libc (socketpair); + + return swrap.libc.symbols._libc_socketpair.f (domain, type, protocol, sv); +} + +ssize_t +libc_write (int fd, const void *buf, size_t count) +{ + swrap_bind_symbol_libc (write); + + return swrap.libc.symbols._libc_write.f (fd, buf, count); +} + +ssize_t +libc_writev (int fd, const struct iovec * iov, int iovcnt) +{ + swrap_bind_symbol_libc (writev); + + return swrap.libc.symbols._libc_writev.f (fd, iov, iovcnt); +} + +int +libc_shutdown (int fd, int how) +{ + swrap_bind_symbol_libc (shutdown); + + return swrap.libc.symbols._libc_shutdown.f (fd, how); +} + +int +libc_select (int __nfds, fd_set * __restrict __readfds, + fd_set * __restrict __writefds, + fd_set * __restrict __exceptfds, + struct timeval *__restrict __timeout) +{ + swrap_bind_symbol_libc (select); + + return swrap.libc.symbols._libc_select.f (__nfds, __readfds, + __writefds, + __exceptfds, __timeout); +} + +#ifdef __USE_XOPEN2K +int +libc_pselect (int __nfds, fd_set * __restrict __readfds, + fd_set * __restrict __writefds, + fd_set * __restrict __exceptfds, + const struct timespec *__restrict __timeout, + const __sigset_t * __restrict __sigmask) +{ + swrap_bind_symbol_libc (pselect); + + return swrap.libc.symbols._libc_pselect.f (__nfds, __readfds, + __writefds, + __exceptfds, + __timeout, __sigmask); +} +#endif + +int +libc_epoll_create (int __size) +{ + swrap_bind_symbol_libc (epoll_create); + + return swrap.libc.symbols._libc_epoll_create.f (__size); +} + +int +libc_epoll_create1 (int __flags) +{ + swrap_bind_symbol_libc (epoll_create1); + + return swrap.libc.symbols._libc_epoll_create1.f (__flags); +} + +int +libc_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) +{ + swrap_bind_symbol_libc (epoll_ctl); + + return swrap.libc.symbols._libc_epoll_ctl.f (__epfd, __op, __fd, __event); +} + +int +libc_epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout) +{ + swrap_bind_symbol_libc (epoll_wait); + + return swrap.libc.symbols._libc_epoll_wait.f (__epfd, __events, + __maxevents, __timeout); +} + +int +libc_epoll_pwait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout, const __sigset_t * __ss) +{ + swrap_bind_symbol_libc (epoll_pwait); + + return swrap.libc.symbols._libc_epoll_pwait.f (__epfd, __events, + __maxevents, __timeout, + __ss); +} + +int +libc_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) +{ + swrap_bind_symbol_libc (poll); + + return swrap.libc.symbols._libc_poll.f (__fds, __nfds, __timeout); +} + +#ifdef __USE_GNU +int +libc_ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss) +{ + swrap_bind_symbol_libc (ppoll); + + return swrap.libc.symbols._libc_ppoll.f (__fds, __nfds, __timeout, __ss); +} +#endif + +static void +swrap_thread_prepare (void) +{ + SWRAP_LOCK_ALL; +} + +static void +swrap_thread_parent (void) +{ + SWRAP_UNLOCK_ALL; +} + +static void +swrap_thread_child (void) +{ + SWRAP_UNLOCK_ALL; +} + +/**************************** + * CONSTRUCTOR + ***************************/ +void +swrap_constructor (void) +{ + /* + * If we hold a lock and the application forks, then the child + * is not able to unlock the mutex and we are in a deadlock. + * This should prevent such deadlocks. + */ + pthread_atfork (&swrap_thread_prepare, + &swrap_thread_parent, &swrap_thread_child); +} + +/**************************** + * DESTRUCTOR + ***************************/ + +/* + * This function is called when the library is unloaded and makes sure that + * sockets get closed and the unix file for the socket are unlinked. + */ +void +swrap_destructor (void) +{ + if (swrap.libc.handle != NULL) + { + dlclose (swrap.libc.handle); + } + if (swrap.libc.socket_handle) + { + dlclose (swrap.libc.socket_handle); + } +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg