
Control use of apis that rely on _GNU_SOURCE being defined with compile time macro. Also fixes sendmmsg and recvmmsg which were not probably wrapped. Type: improvement Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: I207de23210d4b9dc960bb4289159502760c5614d
936 lines
23 KiB
C
936 lines
23 KiB
C
/*
|
|
* Copyright (c) 2016-2019 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 <jelmer@samba.org>
|
|
* Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
|
|
* Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#ifdef HAVE_GNU_SOURCE
|
|
#define _GNU_SOURCE
|
|
#endif
|
|
|
|
#include <signal.h>
|
|
#include <dlfcn.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
|
|
#include <vppinfra/clib.h>
|
|
|
|
#include <vcl/ldp_socket_wrapper.h>
|
|
|
|
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, __SOCKADDR_ARG addr,
|
|
socklen_t *addrlen, int flags);
|
|
typedef int (*__libc_accept) (int sockfd, __SOCKADDR_ARG addr,
|
|
socklen_t *addrlen);
|
|
typedef int (*__libc_bind) (int sockfd, __CONST_SOCKADDR_ARG addr,
|
|
socklen_t addrlen);
|
|
typedef int (*__libc_close) (int fd);
|
|
typedef int (*__libc_connect) (int sockfd, __CONST_SOCKADDR_ARG 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, ...);
|
|
#ifdef HAVE_FCNTL64
|
|
typedef int (*__libc_fcntl64) (int fd, int cmd, ...);
|
|
#endif
|
|
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, __SOCKADDR_ARG addr,
|
|
socklen_t *addrlen);
|
|
typedef int (*__libc_getsockname) (int sockfd, __SOCKADDR_ARG 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,
|
|
__SOCKADDR_ARG src_addr, socklen_t *addrlen);
|
|
typedef int (*__libc_recvmsg) (int sockfd, const struct msghdr *msg,
|
|
int flags);
|
|
#ifdef _GNU_SOURCE
|
|
typedef int (*__libc_recvmmsg) (int fd, struct mmsghdr *vmessages,
|
|
unsigned int vlen, int flags,
|
|
struct timespec *tmo);
|
|
#endif
|
|
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);
|
|
#ifdef _GNU_SOURCE
|
|
typedef int (*__libc_sendmmsg) (int __fd, struct mmsghdr *__vmessages,
|
|
unsigned int __vlen, int __flags);
|
|
#endif
|
|
typedef int (*__libc_sendto) (int sockfd, const void *buf, size_t len,
|
|
int flags, __CONST_SOCKADDR_ARG 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 _GNU_SOURCE
|
|
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);
|
|
#ifdef HAVE_FCNTL64
|
|
SWRAP_SYMBOL_ENTRY (fcntl64);
|
|
#endif
|
|
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);
|
|
#ifdef _GNU_SOURCE
|
|
SWRAP_SYMBOL_ENTRY (recvmmsg);
|
|
#endif
|
|
SWRAP_SYMBOL_ENTRY (send);
|
|
SWRAP_SYMBOL_ENTRY (sendfile);
|
|
SWRAP_SYMBOL_ENTRY (sendmsg);
|
|
#ifdef _GNU_SOURCE
|
|
SWRAP_SYMBOL_ENTRY (sendmmsg);
|
|
#endif
|
|
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 _GNU_SOURCE
|
|
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;
|
|
|
|
#if defined(RTLD_DEEPBIND) && !defined(CLIB_SANITIZE_ADDR)
|
|
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, __SOCKADDR_ARG 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, __SOCKADDR_ARG 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_SOCKADDR_ARG 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_SOCKADDR_ARG 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
|
|
|
|
int
|
|
libc_vfcntl (int fd, int cmd, va_list ap)
|
|
{
|
|
swrap_bind_symbol_libc (fcntl);
|
|
return swrap.libc.symbols._libc_fcntl.f (fd, cmd, va_arg (ap, long int));
|
|
}
|
|
|
|
#ifdef HAVE_FCNTL64
|
|
int
|
|
libc_vfcntl64 (int fd, int cmd, va_list ap)
|
|
{
|
|
swrap_bind_symbol_libc (fcntl64);
|
|
return swrap.libc.symbols._libc_fcntl64.f (fd, cmd, va_arg (ap, long int));
|
|
}
|
|
#endif
|
|
|
|
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, __SOCKADDR_ARG addr, socklen_t *addrlen)
|
|
{
|
|
swrap_bind_symbol_libc (getpeername);
|
|
|
|
return swrap.libc.symbols._libc_getpeername.f (sockfd, addr, addrlen);
|
|
}
|
|
|
|
int
|
|
libc_getsockname (int sockfd, __SOCKADDR_ARG 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,
|
|
__SOCKADDR_ARG 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);
|
|
}
|
|
|
|
#ifdef _GNU_SOURCE
|
|
int
|
|
libc_recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
|
|
struct timespec *tmo)
|
|
{
|
|
swrap_bind_symbol_libc (recvmmsg);
|
|
|
|
return swrap.libc.symbols._libc_recvmmsg.f (fd, vmessages, vlen, flags, tmo);
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
#ifdef _GNU_SOURCE
|
|
int
|
|
libc_sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
|
|
{
|
|
swrap_bind_symbol_libc (sendmmsg);
|
|
|
|
return swrap.libc.symbols._libc_sendmmsg.f (fd, vmessages, vlen, flags);
|
|
}
|
|
#endif
|
|
|
|
int
|
|
libc_sendto (int sockfd, const void *buf, size_t len, int flags,
|
|
__CONST_SOCKADDR_ARG 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 _GNU_SOURCE
|
|
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:
|
|
*/
|