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.am | 10 +- src/vcl/ldp.c | 3447 +++++++++++++++++++++++++++++++++++++++++ src/vcl/ldp.h | 47 + src/vcl/ldp_glibc_socket.h | 352 +++++ src/vcl/ldp_socket_wrapper.c | 909 +++++++++++ src/vcl/ldp_socket_wrapper.h | 235 +++ src/vcl/vcom.c | 3447 ----------------------------------------- src/vcl/vcom.h | 47 - src/vcl/vcom_glibc_socket.h | 352 ----- src/vcl/vcom_socket_wrapper.c | 909 ----------- src/vcl/vcom_socket_wrapper.h | 235 --- 11 files changed, 4995 insertions(+), 4995 deletions(-) create mode 100644 src/vcl/ldp.c create mode 100644 src/vcl/ldp.h create mode 100644 src/vcl/ldp_glibc_socket.h create mode 100644 src/vcl/ldp_socket_wrapper.c create mode 100644 src/vcl/ldp_socket_wrapper.h delete mode 100644 src/vcl/vcom.c delete mode 100644 src/vcl/vcom.h delete mode 100644 src/vcl/vcom_glibc_socket.h delete mode 100644 src/vcl/vcom_socket_wrapper.c delete mode 100644 src/vcl/vcom_socket_wrapper.h (limited to 'src') diff --git a/src/vcl.am b/src/vcl.am index eac3d7e48cb..f090041b884 100644 --- a/src/vcl.am +++ b/src/vcl.am @@ -34,14 +34,14 @@ nobase_include_HEADERS += \ libvcl_ldpreload_la_LIBADD = $(libvppcom_la_DEPENDENCIES) -lpthread -lrt -ldl libvcl_ldpreload_la_SOURCES += \ - vcl/vcom_socket_wrapper.c \ - vcl/vcom.c \ + vcl/ldp_socket_wrapper.c \ + vcl/ldp.c \ $(libvppcom_la_SOURCES) nobase_include_HEADERS += \ - vcl/vcom_socket_wrapper.h \ - vcl/vcom_glibc_socket.h \ - vcl/vcom.h + vcl/ldp_socket_wrapper.h \ + vcl/ldp_glibc_socket.h \ + vcl/ldp.h noinst_PROGRAMS += \ vcl_test_server \ diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c new file mode 100644 index 00000000000..1cf2445f4fc --- /dev/null +++ b/src/vcl/ldp.c @@ -0,0 +1,3447 @@ +/* + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define HAVE_CONSTRUCTOR_ATTRIBUTE +#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE +#define CONSTRUCTOR_ATTRIBUTE \ + __attribute__ ((constructor)) +#else +#define CONSTRUCTOR_ATTRIBUTE +#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ + +#define HAVE_DESTRUCTOR_ATTRIBUTE +#ifdef HAVE_DESTRUCTOR_ATTRIBUTE +#define DESTRUCTOR_ATTRIBUTE \ + __attribute__ ((destructor)) +#else +#define DESTRUCTOR_ATTRIBUTE +#endif + +typedef struct +{ + int init; + char app_name[LDP_APP_NAME_MAX]; + u32 sid_bit_val; + u32 sid_bit_mask; + u32 debug; + u8 *io_buffer; + clib_time_t clib_time; + clib_bitmap_t *rd_bitmap; + clib_bitmap_t *wr_bitmap; + clib_bitmap_t *ex_bitmap; + clib_bitmap_t *sid_rd_bitmap; + clib_bitmap_t *sid_wr_bitmap; + clib_bitmap_t *sid_ex_bitmap; + clib_bitmap_t *libc_rd_bitmap; + clib_bitmap_t *libc_wr_bitmap; + clib_bitmap_t *libc_ex_bitmap; + vcl_poll_t *vcl_poll; + u8 select_vcl; + u8 epoll_wait_vcl; +} ldp_main_t; +#define LDP_DEBUG ldp->debug + +static ldp_main_t ldp_main = { + .sid_bit_val = (1 << LDP_SID_BIT_MIN), + .sid_bit_mask = (1 << LDP_SID_BIT_MIN) - 1, + .debug = LDP_DEBUG_INIT, +}; + +static ldp_main_t *ldp = &ldp_main; + +/* + * RETURN: 0 on success or -1 on error. + * */ +static inline void +ldp_set_app_name (char *app_name) +{ + int rv = snprintf (ldp->app_name, LDP_APP_NAME_MAX, + "ldp-%d-%s", getpid (), app_name); + + if (rv >= LDP_APP_NAME_MAX) + app_name[LDP_APP_NAME_MAX - 1] = 0; +} + +static inline char * +ldp_get_app_name () +{ + if (ldp->app_name[0] == '\0') + ldp_set_app_name ("app"); + + return ldp->app_name; +} + +static inline int +ldp_fd_from_sid (u32 sid) +{ + if (PREDICT_FALSE (sid >= ldp->sid_bit_val)) + return -EMFILE; + else + return (sid | ldp->sid_bit_val); +} + +static inline int +ldp_fd_is_sid (int fd) +{ + return ((u32) fd & ldp->sid_bit_val) ? 1 : 0; +} + +static inline u32 +ldp_sid_from_fd (int fd) +{ + return (ldp_fd_is_sid (fd) ? ((u32) fd & ldp->sid_bit_mask) : + INVALID_SESSION_ID); +} + +static inline int +ldp_init (void) +{ + int rv = 0; + + if (PREDICT_FALSE (!ldp->init)) + { + ldp->init = 1; + rv = vppcom_app_create (ldp_get_app_name ()); + if (rv == VPPCOM_OK) + { + char *env_var_str = getenv (LDP_ENV_DEBUG); + if (env_var_str) + { + u32 tmp; + if (sscanf (env_var_str, "%u", &tmp) != 1) + clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level " + "specified in the env var " LDP_ENV_DEBUG + " (%s)!", getpid (), env_var_str); + else + { + ldp->debug = tmp; + clib_warning ("LDP<%d>: configured LDP debug level (%u) " + "from the env var " LDP_ENV_DEBUG "!", + getpid (), ldp->debug); + } + } + + env_var_str = getenv (LDP_ENV_APP_NAME); + if (env_var_str) + { + ldp_set_app_name (env_var_str); + clib_warning ("LDP<%d>: configured LDP app name (%s) " + "from the env var " LDP_ENV_APP_NAME "!", + getpid (), ldp->app_name); + } + + env_var_str = getenv (LDP_ENV_SID_BIT); + if (env_var_str) + { + u32 sb; + if (sscanf (env_var_str, "%u", &sb) != 1) + { + clib_warning ("LDP<%d>: WARNING: Invalid LDP sid bit " + "specified in the env var " + LDP_ENV_SID_BIT " (%s)!" + "sid bit value %d (0x%x)", + getpid (), env_var_str, + ldp->sid_bit_val, ldp->sid_bit_val); + } + else if (sb < LDP_SID_BIT_MIN) + { + ldp->sid_bit_val = (1 << LDP_SID_BIT_MIN); + ldp->sid_bit_mask = ldp->sid_bit_val - 1; + + clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) " + "specified in the env var " + LDP_ENV_SID_BIT " (%s) is too small. " + "Using LDP_SID_BIT_MIN (%d)! " + "sid bit value %d (0x%x)", + getpid (), sb, env_var_str, LDP_SID_BIT_MIN, + ldp->sid_bit_val, ldp->sid_bit_val); + } + else if (sb > LDP_SID_BIT_MAX) + { + ldp->sid_bit_val = (1 << LDP_SID_BIT_MAX); + ldp->sid_bit_mask = ldp->sid_bit_val - 1; + + clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) " + "specified in the env var " + LDP_ENV_SID_BIT " (%s) is too big. " + "Using LDP_SID_BIT_MAX (%d)! " + "sid bit value %d (0x%x)", + getpid (), sb, env_var_str, LDP_SID_BIT_MAX, + ldp->sid_bit_val, ldp->sid_bit_val); + } + else + { + ldp->sid_bit_val = (1 << sb); + ldp->sid_bit_mask = ldp->sid_bit_val - 1; + + clib_warning ("LDP<%d>: configured LDP sid bit (%u) " + "from " LDP_ENV_SID_BIT + "! sid bit value %d (0x%x)", getpid (), + sb, ldp->sid_bit_val, ldp->sid_bit_val); + } + } + + clib_time_init (&ldp->clib_time); + clib_warning ("LDP<%d>: LDP initialization: done!", getpid ()); + } + else + { + fprintf (stderr, "\nLDP<%d>: ERROR: ldp_init: vppcom_app_create()" + " failed! rv = %d (%s)\n", + getpid (), rv, vppcom_retval_str (rv)); + ldp->init = 0; + } + } + return rv; +} + +int +close (int fd) +{ + int rv; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + int epfd; + + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + epfd = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); + if (epfd > 0) + { + func_str = "libc_close"; + + if (LDP_DEBUG > 0) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): epfd %u (0x%x)", + getpid (), fd, fd, func_str, epfd, epfd); + + rv = libc_close (epfd); + if (rv < 0) + { + u32 size = sizeof (epfd); + epfd = 0; + + (void) vppcom_session_attr (sid, VPPCOM_ATTR_SET_LIBC_EPFD, + &epfd, &size); + } + } + else if (PREDICT_FALSE (epfd < 0)) + { + errno = -epfd; + rv = -1; + goto done; + } + + func_str = "vppcom_session_close"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + + rv = vppcom_session_close (sid); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_close"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s()", + getpid (), fd, fd, func_str); + + rv = libc_close (fd); + } + +done: + if (LDP_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +ssize_t +read (int fd, void *buf, size_t nbytes) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_read"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, nbytes %u", getpid (), + fd, fd, func_str, sid, sid, buf, nbytes); + + size = vppcom_session_read (sid, buf, nbytes); + if (size < 0) + { + errno = -size; + size = -1; + } + } + else + { + func_str = "libc_read"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, nbytes %u", getpid (), + fd, fd, func_str, buf, nbytes); + + size = libc_read (fd, buf, nbytes); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +readv (int fd, const struct iovec * iov, int iovcnt) +{ + const char *func_str; + ssize_t size = 0; + u32 sid = ldp_sid_from_fd (fd); + int rv = 0, i, total = 0; + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_read"; + do + { + for (i = 0; i < iovcnt; ++i) + { + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s() [%d]: " + "sid %u (0x%x), iov %p, iovcnt %d, total %d", + getpid (), fd, fd, func_str, i, sid, sid, + iov, iovcnt, total); + + rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len); + if (rv < 0) + break; + else + { + total += rv; + if (rv < iov[i].iov_len) + { + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): " + "rv (%d) < iov[%d].iov_len (%d)", + getpid (), fd, fd, rv, i, + iov[i].iov_len); + break; + } + } + } + } + while ((rv >= 0) && (total == 0)); + + if (rv < 0) + { + errno = -rv; + size = -1; + } + else + size = total; + } + else + { + func_str = "libc_readv"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "iov %p, iovcnt %d", getpid (), fd, fd, iov, iovcnt); + + size = libc_readv (fd, iov, iovcnt); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +write (int fd, const void *buf, size_t nbytes) +{ + const char *func_str; + ssize_t size = 0; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_write"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, nbytes %u", getpid (), + fd, fd, func_str, sid, sid, buf, nbytes); + + size = vppcom_session_write (sid, (void *) buf, nbytes); + if (size < 0) + { + errno = -size; + size = -1; + } + } + else + { + func_str = "libc_write"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, nbytes %u", getpid (), + fd, fd, func_str, buf, nbytes); + + size = libc_write (fd, buf, nbytes); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +writev (int fd, const struct iovec * iov, int iovcnt) +{ + const char *func_str; + ssize_t size = 0, total = 0; + u32 sid = ldp_sid_from_fd (fd); + int i, rv = 0; + + /* + * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV. + */ + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_write"; + do + { + for (i = 0; i < iovcnt; ++i) + { + if (LDP_DEBUG > 4) + printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s() [%d]: " + "sid %u (0x%x), buf %p, nbytes %ld, total %ld", + __func__, __LINE__, getpid (), fd, fd, func_str, + i, sid, sid, iov[i].iov_base, iov[i].iov_len, total); + + rv = vppcom_session_write (sid, iov[i].iov_base, + iov[i].iov_len); + if (rv < 0) + break; + else + { + total += rv; + if (rv < iov[i].iov_len) + { + if (LDP_DEBUG > 4) + printf ("%s:%d: LDP<%d>: fd %d (0x%x): " + "rv (%d) < iov[%d].iov_len (%ld)", + __func__, __LINE__, getpid (), fd, fd, + rv, i, iov[i].iov_len); + break; + } + } + } + } + while ((rv >= 0) && (total == 0)); + + if (rv < 0) + { + errno = -rv; + size = -1; + } + else + size = total; + } + else + { + func_str = "libc_writev"; + + if (LDP_DEBUG > 4) + printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s(): " + "iov %p, iovcnt %d\n", __func__, __LINE__, getpid (), + fd, fd, func_str, iov, iovcnt); + + size = libc_writev (fd, iov, iovcnt); + } + + if (LDP_DEBUG > 4) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + fprintf (stderr, + "%s:%d: LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %ld, errno = %d\n", __func__, __LINE__, getpid (), fd, + fd, func_str, size, errno_val); + errno = errno_val; + } + else + printf ("%s:%d: LDP<%d>: fd %d (0x%x): returning %ld\n", + __func__, __LINE__, getpid (), fd, fd, size); + } + return size; +} + +int +fcntl (int fd, int cmd, ...) +{ + const char *func_str = __func__; + int rv = 0; + va_list ap; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + va_start (ap, cmd); + if (sid != INVALID_SESSION_ID) + { + int flags = va_arg (ap, int); + u32 size; + + size = sizeof (flags); + rv = -EOPNOTSUPP; + switch (cmd) + { + case F_SETFL: + func_str = "vppcom_session_attr[SET_FLAGS]"; + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x) flags %d (0x%x), size %d", + getpid (), fd, fd, func_str, sid, sid, + flags, flags, size); + + rv = + vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size); + break; + + case F_GETFL: + func_str = "vppcom_session_attr[GET_FLAGS]"; + if (LDP_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid, + sid, flags, flags, size); + + rv = + vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size); + if (rv == VPPCOM_OK) + { + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x), cmd %d (F_GETFL): " + "%s() returned flags %d (0x%x)", + getpid (), fd, fd, cmd, func_str, flags, flags); + rv = flags; + } + break; + + default: + rv = -EOPNOTSUPP; + break; + } + if (rv < 0) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_vfcntl"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d", + getpid (), fd, fd, func_str, cmd); + + rv = libc_vfcntl (fd, cmd, ap); + } + + va_end (ap); + + if (LDP_DEBUG > 2) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +int +ioctl (int fd, unsigned long int cmd, ...) +{ + const char *func_str; + int rv; + va_list ap; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + va_start (ap, cmd); + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_attr[GET_NREAD]"; + + switch (cmd) + { + case FIONREAD: + if (LDP_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0); + break; + + case FIONBIO: + { + u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0; + u32 size = sizeof (flags); + + /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than + * non-blocking, the flags should be read here and merged + * with O_NONBLOCK. + */ + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), flags %d (0x%x), size %d", + getpid (), fd, fd, func_str, sid, sid, + flags, flags, size); + + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, + &size); + } + break; + + default: + rv = -EOPNOTSUPP; + break; + } + if (rv < 0) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_vioctl"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d", + getpid (), fd, fd, func_str, cmd); + + rv = libc_vioctl (fd, cmd, ap); + } + + if (LDP_DEBUG > 2) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + va_end (ap); + return rv; +} + +int +ldp_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) +{ + int rv; + char *func_str = "##"; + f64 time_out; + int fd; + uword sid_bits, sid_bits_set, libc_bits, libc_bits_set; + u32 minbits = clib_max (nfds, BITS (uword)); + u32 sid; + + if (nfds < 0) + { + errno = EINVAL; + return -1; + } + + if (nfds <= ldp->sid_bit_val) + { + func_str = "libc_pselect"; + + if (LDP_DEBUG > 3) + clib_warning + ("LDP<%d>: calling %s(): nfds %d, readfds %p, writefds %p, " + "exceptfds %p, timeout %p, sigmask %p", getpid (), func_str, nfds, + readfds, writefds, exceptfds, timeout, sigmask); + + rv = libc_pselect (nfds, readfds, writefds, exceptfds, + timeout, sigmask); + goto done; + } + + if (PREDICT_FALSE (ldp->sid_bit_val > FD_SETSIZE / 2)) + { + clib_warning ("LDP<%d>: ERROR: LDP sid bit value %d (0x%x) > " + "FD_SETSIZE/2 %d (0x%x)!", getpid (), + ldp->sid_bit_val, ldp->sid_bit_val, + FD_SETSIZE / 2, FD_SETSIZE / 2); + errno = EOVERFLOW; + return -1; + } + + if (timeout) + { + time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ? + (f64) 0 : (f64) timeout->tv_sec + + (f64) timeout->tv_nsec / (f64) 1000000000 + + (f64) (timeout->tv_nsec % 1000000000) / (f64) 1000000000; + + /* select as fine grained sleep */ + if (!nfds) + { + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: sleeping for %f seconds", + getpid (), time_out); + + time_out += clib_time_now (&ldp->clib_time); + while (clib_time_now (&ldp->clib_time) < time_out) + ; + return 0; + } + } + else if (!nfds) + { + errno = EINVAL; + return -1; + } + else + time_out = -1; + + sid_bits = libc_bits = 0; + if (readfds) + { + clib_bitmap_validate (ldp->sid_rd_bitmap, minbits); + clib_bitmap_validate (ldp->libc_rd_bitmap, minbits); + clib_bitmap_validate (ldp->rd_bitmap, minbits); + clib_memcpy (ldp->rd_bitmap, readfds, + vec_len (ldp->rd_bitmap) * sizeof (clib_bitmap_t)); + FD_ZERO (readfds); + + /* *INDENT-OFF* */ + clib_bitmap_foreach (fd, ldp->rd_bitmap, + ({ + sid = ldp_sid_from_fd (fd); + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: readfds: fd %d (0x%x), sid %u (0x%x)", + getpid (), fd, fd, sid, sid); + if (sid == INVALID_SESSION_ID) + clib_bitmap_set_no_check (ldp->libc_rd_bitmap, fd, 1); + else + clib_bitmap_set_no_check (ldp->sid_rd_bitmap, sid, 1); + })); + /* *INDENT-ON* */ + + sid_bits_set = clib_bitmap_last_set (ldp->sid_rd_bitmap) + 1; + sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; + + libc_bits_set = clib_bitmap_last_set (ldp->libc_rd_bitmap) + 1; + libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: readfds: sid_bits_set %d, sid_bits %d, " + "libc_bits_set %d, libc_bits %d", getpid (), + sid_bits_set, sid_bits, libc_bits_set, libc_bits); + } + if (writefds) + { + clib_bitmap_validate (ldp->sid_wr_bitmap, minbits); + clib_bitmap_validate (ldp->libc_wr_bitmap, minbits); + clib_bitmap_validate (ldp->wr_bitmap, minbits); + clib_memcpy (ldp->wr_bitmap, writefds, + vec_len (ldp->wr_bitmap) * sizeof (clib_bitmap_t)); + FD_ZERO (writefds); + + /* *INDENT-OFF* */ + clib_bitmap_foreach (fd, ldp->wr_bitmap, + ({ + sid = ldp_sid_from_fd (fd); + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: writefds: fd %d (0x%x), sid %u (0x%x)", + getpid (), fd, fd, sid, sid); + if (sid == INVALID_SESSION_ID) + clib_bitmap_set_no_check (ldp->libc_wr_bitmap, fd, 1); + else + clib_bitmap_set_no_check (ldp->sid_wr_bitmap, sid, 1); + })); + /* *INDENT-ON* */ + + sid_bits_set = clib_bitmap_last_set (ldp->sid_wr_bitmap) + 1; + sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; + + libc_bits_set = clib_bitmap_last_set (ldp->libc_wr_bitmap) + 1; + libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: writefds: sid_bits_set %d, sid_bits %d, " + "libc_bits_set %d, libc_bits %d", getpid (), + sid_bits_set, sid_bits, libc_bits_set, libc_bits); + } + if (exceptfds) + { + clib_bitmap_validate (ldp->sid_ex_bitmap, minbits); + clib_bitmap_validate (ldp->libc_ex_bitmap, minbits); + clib_bitmap_validate (ldp->ex_bitmap, minbits); + clib_memcpy (ldp->ex_bitmap, exceptfds, + vec_len (ldp->ex_bitmap) * sizeof (clib_bitmap_t)); + FD_ZERO (exceptfds); + + /* *INDENT-OFF* */ + clib_bitmap_foreach (fd, ldp->ex_bitmap, + ({ + sid = ldp_sid_from_fd (fd); + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: exceptfds: fd %d (0x%x), sid %u (0x%x)", + getpid (), fd, fd, sid, sid); + if (sid == INVALID_SESSION_ID) + clib_bitmap_set_no_check (ldp->libc_ex_bitmap, fd, 1); + else + clib_bitmap_set_no_check (ldp->sid_ex_bitmap, sid, 1); + })); + /* *INDENT-ON* */ + + sid_bits_set = clib_bitmap_last_set (ldp->sid_ex_bitmap) + 1; + sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; + + libc_bits_set = clib_bitmap_last_set (ldp->libc_ex_bitmap) + 1; + libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: exceptfds: sid_bits_set %d, sid_bits %d, " + "libc_bits_set %d, libc_bits %d", getpid (), + sid_bits_set, sid_bits, libc_bits_set, libc_bits); + } + + if (PREDICT_FALSE (!sid_bits && !libc_bits)) + { + errno = EINVAL; + rv = -1; + goto done; + } + + do + { + if (sid_bits) + { + if (!ldp->select_vcl) + { + func_str = "vppcom_select"; + + if (readfds) + clib_memcpy (ldp->rd_bitmap, ldp->sid_rd_bitmap, + vec_len (ldp->rd_bitmap) * + sizeof (clib_bitmap_t)); + if (writefds) + clib_memcpy (ldp->wr_bitmap, ldp->sid_wr_bitmap, + vec_len (ldp->wr_bitmap) * + sizeof (clib_bitmap_t)); + if (exceptfds) + clib_memcpy (ldp->ex_bitmap, ldp->sid_ex_bitmap, + vec_len (ldp->ex_bitmap) * + sizeof (clib_bitmap_t)); + + rv = vppcom_select (sid_bits, + readfds ? ldp->rd_bitmap : NULL, + writefds ? ldp->wr_bitmap : NULL, + exceptfds ? ldp->ex_bitmap : NULL, 0); + if (rv < 0) + { + errno = -rv; + rv = -1; + } + else if (rv > 0) + { + if (readfds) + { + /* *INDENT-OFF* */ + clib_bitmap_foreach (sid, ldp->rd_bitmap, + ({ + fd = ldp_fd_from_sid (sid); + if (PREDICT_FALSE (fd < 0)) + { + errno = EBADFD; + rv = -1; + goto done; + } + FD_SET (fd, readfds); + })); + /* *INDENT-ON* */ + } + if (writefds) + { + /* *INDENT-OFF* */ + clib_bitmap_foreach (sid, ldp->wr_bitmap, + ({ + fd = ldp_fd_from_sid (sid); + if (PREDICT_FALSE (fd < 0)) + { + errno = EBADFD; + rv = -1; + goto done; + } + FD_SET (fd, writefds); + })); + /* *INDENT-ON* */ + } + if (exceptfds) + { + /* *INDENT-OFF* */ + clib_bitmap_foreach (sid, ldp->ex_bitmap, + ({ + fd = ldp_fd_from_sid (sid); + if (PREDICT_FALSE (fd < 0)) + { + errno = EBADFD; + rv = -1; + goto done; + } + FD_SET (fd, exceptfds); + })); + /* *INDENT-ON* */ + } + ldp->select_vcl = 1; + goto done; + } + } + else + ldp->select_vcl = 0; + } + if (libc_bits) + { + struct timespec tspec; + + func_str = "libc_pselect"; + + if (readfds) + clib_memcpy (readfds, ldp->libc_rd_bitmap, + vec_len (ldp->rd_bitmap) * sizeof (clib_bitmap_t)); + if (writefds) + clib_memcpy (writefds, ldp->libc_wr_bitmap, + vec_len (ldp->wr_bitmap) * sizeof (clib_bitmap_t)); + if (exceptfds) + clib_memcpy (exceptfds, ldp->libc_ex_bitmap, + vec_len (ldp->ex_bitmap) * sizeof (clib_bitmap_t)); + tspec.tv_sec = tspec.tv_nsec = 0; + rv = libc_pselect (libc_bits, + readfds ? readfds : NULL, + writefds ? writefds : NULL, + exceptfds ? exceptfds : NULL, &tspec, sigmask); + if (rv != 0) + goto done; + } + } + while ((time_out == -1) || (clib_time_now (&ldp->clib_time) < time_out)); + rv = 0; + +done: + /* TBD: set timeout to amount of time left */ + vec_reset_length (ldp->rd_bitmap); + vec_reset_length (ldp->sid_rd_bitmap); + vec_reset_length (ldp->libc_rd_bitmap); + vec_reset_length (ldp->wr_bitmap); + vec_reset_length (ldp->sid_wr_bitmap); + vec_reset_length (ldp->libc_wr_bitmap); + vec_reset_length (ldp->ex_bitmap); + vec_reset_length (ldp->sid_ex_bitmap); + vec_reset_length (ldp->libc_ex_bitmap); + + if (LDP_DEBUG > 3) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", getpid (), + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv); + } + return rv; +} + +int +select (int nfds, fd_set * __restrict readfds, + fd_set * __restrict writefds, + fd_set * __restrict exceptfds, struct timeval *__restrict timeout) +{ + struct timespec tspec; + + if (timeout) + { + tspec.tv_sec = timeout->tv_sec; + tspec.tv_nsec = timeout->tv_usec * 1000; + } + return ldp_pselect (nfds, readfds, writefds, exceptfds, + timeout ? &tspec : NULL, NULL); +} + +#ifdef __USE_XOPEN2K +int +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) +{ + return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0); +} +#endif + +int +socket (int domain, int type, int protocol) +{ + const char *func_str; + int rv; + u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0; + int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); + + if ((errno = -ldp_init ())) + return -1; + + if (((domain == AF_INET) || (domain == AF_INET6)) && + ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM))) + { + int sid; + u8 proto = ((sock_type == SOCK_DGRAM) ? + VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP); + + func_str = "vppcom_session_create"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: : calling %s(): " + "proto %u (%s), is_nonblocking %u", + getpid (), func_str, proto, + vppcom_proto_str (proto), is_nonblocking); + + sid = vppcom_session_create (proto, is_nonblocking); + if (sid < 0) + { + errno = -sid; + rv = -1; + } + else + { + func_str = "ldp_fd_from_sid"; + rv = ldp_fd_from_sid (sid); + if (rv < 0) + { + (void) vppcom_session_close (sid); + errno = -rv; + rv = -1; + } + } + } + else + { + func_str = "libc_socket"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); + + rv = libc_socket (domain, type, protocol); + } + + if (LDP_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", + getpid (), func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv); + } + return rv; +} + +/* + * Create two new sockets, of type TYPE in domain DOMAIN and using + * protocol PROTOCOL, which are connected to each other, and put file + * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, + * one will be chosen automatically. + * Returns 0 on success, -1 for errors. + * */ +int +socketpair (int domain, int type, int protocol, int fds[2]) +{ + const char *func_str; + int rv; + int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); + + if ((errno = -ldp_init ())) + return -1; + + if (((domain == AF_INET) || (domain == AF_INET6)) && + ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM))) + { + func_str = __func__; + + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + rv = -1; + } + else + { + func_str = "libc_socket"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); + + rv = libc_socket (domain, type, protocol); + } + + if (LDP_DEBUG > 1) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", + getpid (), func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv); + } + return rv; +} + +int +bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) +{ + int rv; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + vppcom_endpt_t ep; + + func_str = "vppcom_session_bind"; + + switch (addr->sa_family) + { + case AF_INET: + if (len != sizeof (struct sockaddr_in)) + { + clib_warning + ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid " + "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP4; + ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr; + ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port; + break; + + case AF_INET6: + if (len != sizeof (struct sockaddr_in6)) + { + clib_warning + ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid " + "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP6; + ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; + ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port; + break; + + default: + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): " + "Unsupported address family %u!", + getpid (), fd, fd, sid, sid, addr->sa_family); + errno = EAFNOSUPPORT; + rv = -1; + goto done; + } + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "addr %p, len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); + + rv = vppcom_session_bind (sid, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_bind"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); + + rv = libc_bind (fd, addr, len); + } + +done: + if (LDP_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +static inline int +ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len, + vppcom_endpt_t * ep) +{ + int rv = 0; + int sa_len, copy_len; + + if ((errno = -ldp_init ())) + return -1; + + if (addr && len && ep) + { + addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6; + switch (addr->sa_family) + { + case AF_INET: + ((struct sockaddr_in *) addr)->sin_port = ep->port; + if (*len > sizeof (struct sockaddr_in)) + *len = sizeof (struct sockaddr_in); + sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr); + copy_len = *len - sa_len; + if (copy_len > 0) + memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip, + copy_len); + break; + + case AF_INET6: + ((struct sockaddr_in6 *) addr)->sin6_port = ep->port; + if (*len > sizeof (struct sockaddr_in6)) + *len = sizeof (struct sockaddr_in6); + sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr); + copy_len = *len - sa_len; + if (copy_len > 0) + memcpy (((struct sockaddr_in6 *) addr)->sin6_addr. + __in6_u.__u6_addr8, ep->ip, copy_len); + break; + + default: + /* Not possible */ + rv = -EAFNOSUPPORT; + break; + } + } + return rv; +} + +int +getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len) +{ + int rv; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + vppcom_endpt_t ep; + u8 addr_buf[sizeof (struct in6_addr)]; + u32 size = sizeof (ep); + + ep.ip = addr_buf; + func_str = "vppcom_session_attr[GET_LCL_ADDR]"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "addr %p, len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); + + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + else + { + rv = ldp_copy_ep_to_sockaddr (addr, len, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + } + else + { + func_str = "libc_getsockname"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); + + rv = libc_getsockname (fd, addr, len); + } + + if (LDP_DEBUG > 2) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +int +connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) +{ + int rv; + const char *func_str = __func__; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (!addr) + { + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u", + getpid (), fd, fd, len); + errno = EINVAL; + rv = -1; + goto done; + } + + if (sid != INVALID_SESSION_ID) + { + vppcom_endpt_t ep; + + func_str = "vppcom_session_connect"; + + switch (addr->sa_family) + { + case AF_INET: + if (len != sizeof (struct sockaddr_in)) + { + clib_warning + ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid " + "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP4; + ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr; + ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port; + break; + + case AF_INET6: + if (len != sizeof (struct sockaddr_in6)) + { + clib_warning + ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid " + "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP6; + ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; + ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port; + break; + + default: + clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): " + "Unsupported address family %u!", + getpid (), fd, fd, sid, sid, addr->sa_family); + errno = EAFNOSUPPORT; + rv = -1; + goto done; + } + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) " + "addr %p len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); + + rv = vppcom_session_connect (sid, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_connect"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); + + rv = libc_connect (fd, addr, len); + } + +done: + if (LDP_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +int +getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len) +{ + int rv; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + vppcom_endpt_t ep; + u8 addr_buf[sizeof (struct in6_addr)]; + u32 size = sizeof (ep); + + ep.ip = addr_buf; + func_str = "vppcom_session_attr[GET_PEER_ADDR]"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "addr %p, len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); + + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + else + { + rv = ldp_copy_ep_to_sockaddr (addr, len, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + } + else + { + func_str = "libc_getpeername"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); + + rv = libc_getpeername (fd, addr, len); + } + + if (LDP_DEBUG > 2) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +ssize_t +send (int fd, const void *buf, size_t n, int flags) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + + func_str = "vppcom_session_sendto"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "buf %p, n %u, flags 0x%x", + getpid (), fd, fd, func_str, sid, sid, buf, n, flags); + + size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL); + if (size != VPPCOM_OK) + { + errno = -size; + size = -1; + } + } + else + { + func_str = "libc_send"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x", + getpid (), fd, fd, func_str, buf, n, flags); + + size = libc_send (fd, buf, n, flags); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +sendfile (int out_fd, int in_fd, off_t * offset, size_t len) +{ + ssize_t size = 0; + const char *func_str; + u32 sid = ldp_sid_from_fd (out_fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + int rv; + ssize_t results = 0; + size_t n_bytes_left = len; + size_t bytes_to_read; + int nbytes; + int errno_val; + u8 eagain = 0; + u32 flags, flags_len = sizeof (flags); + + func_str = "vppcom_session_attr[GET_FLAGS]"; + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, + &flags_len); + if (PREDICT_FALSE (rv != VPPCOM_OK)) + { + clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): " + "sid %u (0x%x), returned %d (%s)!", getpid (), + out_fd, out_fd, func_str, sid, sid, rv, + vppcom_retval_str (rv)); + + vec_reset_length (ldp->io_buffer); + errno = -rv; + size = -1; + goto done; + } + + if (offset) + { + off_t off = lseek (in_fd, *offset, SEEK_SET); + if (PREDICT_FALSE (off == -1)) + { + func_str = "lseek"; + errno_val = errno; + clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): " + "SEEK_SET failed: in_fd %d, offset %p, " + "*offset %ld, rv %ld, errno %d", getpid (), + out_fd, out_fd, in_fd, offset, *offset, off, + errno_val); + errno = errno_val; + size = -1; + goto done; + } + + ASSERT (off == *offset); + } + + do + { + func_str = "vppcom_session_attr[GET_NWRITE]"; + size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0); + if (size < 0) + { + clib_warning + ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), " + "returned %d (%s)!", getpid (), out_fd, out_fd, func_str, + sid, sid, size, vppcom_retval_str (size)); + vec_reset_length (ldp->io_buffer); + errno = -size; + size = -1; + goto done; + } + + bytes_to_read = size; + if (LDP_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), " + "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (), + out_fd, out_fd, func_str, sid, sid, results, n_bytes_left, + bytes_to_read); + + if (bytes_to_read == 0) + { + if (flags & O_NONBLOCK) + { + if (!results) + { + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): " + "EAGAIN", + getpid (), out_fd, out_fd, sid, sid); + eagain = 1; + } + goto update_offset; + } + else + continue; + } + bytes_to_read = clib_min (n_bytes_left, bytes_to_read); + vec_validate (ldp->io_buffer, bytes_to_read); + nbytes = libc_read (in_fd, ldp->io_buffer, bytes_to_read); + if (nbytes < 0) + { + func_str = "libc_read"; + errno_val = errno; + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), " + "io_buffer %p, bytes_to_read %lu, rv %d, " + "errno %d", getpid (), out_fd, out_fd, func_str, + in_fd, ldp->io_buffer, bytes_to_read, nbytes, + errno_val); + errno = errno_val; + + if (results == 0) + { + vec_reset_length (ldp->io_buffer); + size = -1; + goto done; + } + goto update_offset; + } + func_str = "vppcom_session_write"; + if (LDP_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (), + out_fd, out_fd, func_str, sid, sid, ldp->io_buffer, nbytes, + results, n_bytes_left); + + size = vppcom_session_write (sid, ldp->io_buffer, nbytes); + if (size < 0) + { + if (size == VPPCOM_EAGAIN) + { + if (flags & O_NONBLOCK) + { + if (!results) + { + if (LDP_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): " + "EAGAIN", getpid (), out_fd, out_fd, sid, sid); + eagain = 1; + } + goto update_offset; + } + else + continue; + } + else + { + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():" + "sid %u, io_buffer %p, nbytes %u " + "returned %d (%s)", + getpid (), out_fd, out_fd, func_str, + sid, ldp->io_buffer, nbytes, + size, vppcom_retval_str (size)); + } + if (results == 0) + { + vec_reset_length (ldp->io_buffer); + errno = -size; + size = -1; + goto done; + } + goto update_offset; + } + + results += nbytes; + ASSERT (n_bytes_left >= nbytes); + n_bytes_left = n_bytes_left - nbytes; + } + while (n_bytes_left > 0); + + update_offset: + vec_reset_length (ldp->io_buffer); + if (offset) + { + off_t off = lseek (in_fd, *offset, SEEK_SET); + if (PREDICT_FALSE (off == -1)) + { + func_str = "lseek"; + errno_val = errno; + clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: " + "in_fd %d, offset %p, *offset %ld, " + "rv %ld, errno %d", getpid (), in_fd, + offset, *offset, off, errno_val); + errno = errno_val; + size = -1; + goto done; + } + + ASSERT (off == *offset); + *offset += results + 1; + } + if (eagain) + { + errno = EAGAIN; + size = -1; + } + else + size = results; + } + else + { + func_str = "libc_send"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "in_fd %d, offset %p, len %u", + getpid (), out_fd, out_fd, func_str, + in_fd, offset, len); + + size = libc_sendfile (out_fd, in_fd, offset, len); + } + +done: + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), out_fd, out_fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), out_fd, out_fd, size, size); + } + return size; +} + +ssize_t +sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len) +{ + return sendfile (out_fd, in_fd, offset, len); +} + +ssize_t +recv (int fd, void *buf, size_t n, int flags) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_recvfrom"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (), + fd, fd, func_str, sid, sid, buf, n, flags); + + size = vppcom_session_recvfrom (sid, buf, n, flags, NULL); + if (size < 0) + { + errno = -size; + size = -1; + } + } + else + { + func_str = "libc_recv"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x", getpid (), + fd, fd, func_str, buf, n, flags); + + size = libc_recv (fd, buf, n, flags); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +sendto (int fd, const void *buf, size_t n, int flags, + __CONST_SOCKADDR_ARG addr, socklen_t addr_len) +{ + ssize_t size; + const char *func_str = __func__; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + vppcom_endpt_t *ep = 0; + vppcom_endpt_t _ep; + + if (addr) + { + ep = &_ep; + switch (addr->sa_family) + { + case AF_INET: + ep->is_ip4 = VPPCOM_IS_IP4; + ep->ip = + (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr; + ep->port = + (uint16_t) ((const struct sockaddr_in *) addr)->sin_port; + break; + + case AF_INET6: + ep->is_ip4 = VPPCOM_IS_IP6; + ep->ip = + (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; + ep->port = + (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port; + break; + + default: + errno = EAFNOSUPPORT; + size = -1; + goto done; + } + } + + func_str = "vppcom_session_sendto"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p", + getpid (), fd, fd, func_str, sid, sid, buf, n, + flags, ep); + + size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep); + if (size < 0) + { + errno = -size; + size = -1; + } + } + else + { + func_str = "libc_sendto"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x, addr %p, addr_len %d", + getpid (), fd, fd, func_str, buf, n, flags, + addr, addr_len); + + size = libc_sendto (fd, buf, n, flags, addr, addr_len); + } + +done: + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +recvfrom (int fd, void *__restrict buf, size_t n, int flags, + __SOCKADDR_ARG addr, socklen_t * __restrict addr_len) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + vppcom_endpt_t ep; + u8 src_addr[sizeof (struct sockaddr_in6)]; + + func_str = "vppcom_session_recvfrom"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p", + getpid (), fd, fd, func_str, sid, sid, buf, n, + flags, &ep); + if (addr) + { + ep.ip = src_addr; + size = vppcom_session_recvfrom (sid, buf, n, flags, &ep); + + if (size > 0) + size = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep); + } + else + size = vppcom_session_recvfrom (sid, buf, n, flags, NULL); + + if (size < 0) + { + errno = -size; + size = -1; + } + } + else + { + func_str = "libc_recvfrom"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x, addr %p, addr_len %d", + getpid (), fd, fd, func_str, buf, n, flags, + addr, addr_len); + + size = libc_recvfrom (fd, buf, n, flags, addr, addr_len); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +ssize_t +sendmsg (int fd, const struct msghdr * message, int flags) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = __func__; + + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; + } + else + { + func_str = "libc_sendmsg"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "message %p, flags 0x%x", + getpid (), fd, fd, func_str, message, flags); + + size = libc_sendmsg (fd, message, flags); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +#ifdef USE_GNU +int +sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; + } + else + { + func_str = "libc_sendmmsg"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "vmessages %p, vlen %u, flags 0x%x", + getpid (), fd, fd, func_str, vmessages, vlen, flags); + + size = libc_sendmmsg (fd, vmessages, vlen, flags); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} +#endif + +ssize_t +recvmsg (int fd, struct msghdr * message, int flags) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = __func__; + + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; + } + else + { + func_str = "libc_recvmsg"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "message %p, flags 0x%x", + getpid (), fd, fd, func_str, message, flags); + + size = libc_recvmsg (fd, message, flags); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} + +#ifdef USE_GNU +int +recvmmsg (int fd, struct mmsghdr *vmessages, + unsigned int vlen, int flags, struct timespec *tmo) +{ + ssize_t size; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; + } + else + { + func_str = "libc_recvmmsg"; + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "vmessages %p, vlen %u, flags 0x%x, tmo %p", + getpid (), fd, fd, func_str, vmessages, vlen, + flags, tmo); + + size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo); + } + + if (LDP_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; +} +#endif + +int +getsockopt (int fd, int level, int optname, + void *__restrict optval, socklen_t * __restrict optlen) +{ + int rv; + const char *func_str = __func__; + u32 sid = ldp_sid_from_fd (fd); + u32 buflen = optlen ? (u32) * optlen : 0; + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + rv = -EOPNOTSUPP; + + switch (level) + { + case SOL_TCP: + switch (optname) + { + case TCP_NODELAY: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY, + optval, optlen); + break; + case TCP_MAXSEG: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS, + optval, optlen); + break; + case TCP_KEEPIDLE: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE, + optval, optlen); + break; + case TCP_KEEPINTVL: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), SOL_TCP", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL, + optval, optlen); + break; + case TCP_INFO: + if (optval && optlen && (*optlen == sizeof (struct tcp_info))) + { + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), " + "SOL_TCP, TCP_INFO, optval %p, " + "optlen %d: #LDP-NOP#", + getpid (), fd, fd, sid, sid, + optval, *optlen); + memset (optval, 0, *optlen); + rv = VPPCOM_OK; + } + else + rv = -EFAULT; + break; + default: + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_TCP, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_IPV6: + switch (optname) + { + case IPV6_V6ONLY: + func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY, + optval, optlen); + break; + default: + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_IPV6, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_SOCKET: + switch (optname) + { + case SO_ACCEPTCONN: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN, + optval, optlen); + break; + case SO_KEEPALIVE: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE, + optval, optlen); + break; + case SO_PROTOCOL: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL, + optval, optlen); + *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM; + break; + case SO_SNDBUF: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), optlen %d", + getpid (), fd, fd, func_str, sid, sid, buflen); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN, + optval, optlen); + break; + case SO_RCVBUF: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), optlen %d", + getpid (), fd, fd, func_str, sid, sid, buflen); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN, + optval, optlen); + break; + case SO_REUSEADDR: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR, + optval, optlen); + break; + case SO_BROADCAST: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST, + optval, optlen); + break; + case SO_ERROR: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR, + optval, optlen); + break; + default: + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_SOCKET, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + default: + break; + } + + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_getsockopt"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, " + "optname %d, optval %p, optlen %d", + getpid (), fd, fd, func_str, level, optname, + optval, optlen); + + rv = libc_getsockopt (fd, level, optname, optval, optlen); + } + + if (LDP_DEBUG > 1) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +int +setsockopt (int fd, int level, int optname, + const void *optval, socklen_t optlen) +{ + int rv; + const char *func_str = __func__; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + rv = -EOPNOTSUPP; + + switch (level) + { + case SOL_TCP: + switch (optname) + { + case TCP_NODELAY: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY, + (void *) optval, &optlen); + break; + case TCP_MAXSEG: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS, + (void *) optval, &optlen); + break; + case TCP_KEEPIDLE: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, + (void *) optval, &optlen); + break; + case TCP_KEEPINTVL: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), SOL_TCP", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, + (void *) optval, &optlen); + break; + default: + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_TCP, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_IPV6: + switch (optname) + { + case IPV6_V6ONLY: + func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY, + (void *) optval, &optlen); + break; + default: + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_IPV6, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_SOCKET: + switch (optname) + { + case SO_KEEPALIVE: + func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE, + (void *) optval, &optlen); + break; + case SO_REUSEADDR: + func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR, + (void *) optval, &optlen); + break; + case SO_BROADCAST: + func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]"; + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST, + (void *) optval, &optlen); + break; + default: + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_SOCKET, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + default: + break; + } + + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_setsockopt"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, " + "optname %d, optval %p, optlen %d", + getpid (), fd, fd, func_str, level, optname, + optval, optlen); + + rv = libc_setsockopt (fd, level, optname, optval, optlen); + } + + if (LDP_DEBUG > 1) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +int +listen (int fd, int n) +{ + int rv; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_session_listen"; + + if (LDP_DEBUG > 0) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d", + getpid (), fd, fd, func_str, sid, sid, n); + + rv = vppcom_session_listen (sid, n); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + func_str = "libc_listen"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d", + getpid (), fd, fd, func_str, n); + + rv = libc_listen (fd, n); + } + + if (LDP_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +static inline int +ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr, + socklen_t * __restrict addr_len, int flags) +{ + int rv; + const char *func_str; + u32 listen_sid = ldp_sid_from_fd (listen_fd); + int accept_sid; + + if ((errno = -ldp_init ())) + return -1; + + if (listen_sid != INVALID_SESSION_ID) + { + vppcom_endpt_t ep; + u8 src_addr[sizeof (struct sockaddr_in6)]; + memset (&ep, 0, sizeof (ep)); + ep.ip = src_addr; + + func_str = "vppcom_session_accept"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " + "listen sid %u (0x%x), ep %p, flags 0x%x", + getpid (), listen_fd, listen_fd, func_str, + listen_sid, listen_sid, ep, flags); + + accept_sid = vppcom_session_accept (listen_sid, &ep, flags); + if (accept_sid < 0) + { + errno = -accept_sid; + rv = -1; + } + else + { + rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep); + if (rv != VPPCOM_OK) + { + (void) vppcom_session_close ((u32) accept_sid); + errno = -rv; + rv = -1; + } + else + { + func_str = "ldp_fd_from_sid"; + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " + "accept sid %u (0x%x), ep %p, flags 0x%x", + getpid (), listen_fd, listen_fd, + func_str, accept_sid, accept_sid, ep, flags); + rv = ldp_fd_from_sid ((u32) accept_sid); + if (rv < 0) + { + (void) vppcom_session_close ((u32) accept_sid); + errno = -rv; + rv = -1; + } + } + } + } + else + { + func_str = "libc_accept4"; + + if (LDP_DEBUG > 0) + clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " + "addr %p, addr_len %p, flags 0x%x", + getpid (), listen_fd, listen_fd, func_str, + addr, addr_len, flags); + + rv = libc_accept4 (listen_fd, addr, addr_len, flags); + } + + if (LDP_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), listen_fd, + listen_fd, func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)", + getpid (), listen_fd, listen_fd, rv, rv); + } + return rv; +} + +int +accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len, + int flags) +{ + return ldp_accept4 (fd, addr, addr_len, flags); +} + +int +accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len) +{ + return ldp_accept4 (fd, addr, addr_len, 0); +} + +int +shutdown (int fd, int how) +{ + int rv; + const char *func_str; + u32 sid = ldp_sid_from_fd (fd); + + if ((errno = -ldp_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + func_str = __func__; + + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + rv = -1; + } + else + { + func_str = "libc_shutdown"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d", + getpid (), fd, fd, func_str, how); + + rv = libc_shutdown (fd, how); + } + + if (LDP_DEBUG > 1) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +int +epoll_create1 (int flags) +{ + const char *func_str; + int rv; + + if ((errno = -ldp_init ())) + return -1; + + func_str = "vppcom_epoll_create"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: calling %s()", getpid (), func_str); + + rv = vppcom_epoll_create (); + + if (PREDICT_FALSE (rv < 0)) + { + errno = -rv; + rv = -1; + } + else + rv = ldp_fd_from_sid ((u32) rv); + + if (LDP_DEBUG > 1) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", + getpid (), func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv); + } + return rv; +} + +int +epoll_create (int size) +{ + return epoll_create1 (0); +} + +int +epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) +{ + int rv; + const char *func_str; + u32 vep_idx = ldp_sid_from_fd (epfd); + + if ((errno = -ldp_init ())) + return -1; + + if (vep_idx != INVALID_SESSION_ID) + { + u32 sid = ldp_sid_from_fd (fd); + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_epoll_create"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p", + getpid (), epfd, epfd, func_str, vep_idx, vep_idx, + sid, sid, event); + + rv = vppcom_epoll_ctl (vep_idx, op, sid, event); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + int epfd; + u32 size = sizeof (epfd); + + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, + 0, 0); + if (!epfd) + { + func_str = "libc_epoll_create1"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: calling %s(): EPOLL_CLOEXEC", + getpid (), func_str); + + epfd = libc_epoll_create1 (EPOLL_CLOEXEC); + if (epfd < 0) + { + rv = epfd; + goto done; + } + + func_str = "vppcom_session_attr[SET_LIBC_EPFD]"; + rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD, + &epfd, &size); + if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } + } + else if (PREDICT_FALSE (epfd < 0)) + { + errno = -epfd; + rv = -1; + goto done; + } + + rv = libc_epoll_ctl (epfd, op, fd, event); + } + } + else + { + func_str = "libc_epoll_ctl"; + + if (LDP_DEBUG > 1) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "op %d, fd %d (0x%x), event %p", + getpid (), epfd, epfd, func_str, op, fd, fd, event); + + rv = libc_epoll_ctl (epfd, op, fd, event); + } + +done: + if (LDP_DEBUG > 1) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; +} + +static inline int +ldp_epoll_pwait (int epfd, struct epoll_event *events, + int maxevents, int timeout, const sigset_t * sigmask) +{ + const char *func_str; + int rv = 0; + double time_to_wait = (double) 0; + double time_out, now = 0; + u32 vep_idx = ldp_sid_from_fd (epfd); + int libc_epfd; + + if ((errno = -ldp_init ())) + return -1; + + if (PREDICT_FALSE (!events || (timeout < -1))) + { + errno = EFAULT; + return -1; + } + + if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID)) + { + clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!", + getpid (), epfd, epfd, vep_idx, vep_idx); + errno = EBADFD; + return -1; + } + + time_to_wait = ((timeout >= 0) ? (double) timeout / (double) 1000 : 0); + time_out = clib_time_now (&ldp->clib_time) + time_to_wait; + + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); + if (PREDICT_FALSE (libc_epfd < 0)) + { + errno = -libc_epfd; + rv = -1; + goto done; + } + + if (LDP_DEBUG > 2) + clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), " + "libc_epfd %d (0x%x), events %p, maxevents %d, " + "timeout %d, sigmask %p", getpid (), epfd, epfd, + vep_idx, vep_idx, libc_epfd, libc_epfd, events, + maxevents, timeout, sigmask); + do + { + if (!ldp->epoll_wait_vcl) + { + func_str = "vppcom_epoll_wait"; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "vep_idx %d (0x%x), events %p, maxevents %d", + getpid (), epfd, epfd, func_str, + vep_idx, vep_idx, events, maxevents); + + rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0); + if (rv > 0) + { + ldp->epoll_wait_vcl = 1; + goto done; + } + else if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } + } + else + ldp->epoll_wait_vcl = 0; + + if (libc_epfd > 0) + { + func_str = "libc_epoll_pwait"; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "libc_epfd %d (0x%x), events %p, " + "maxevents %d, sigmask %p", + getpid (), epfd, epfd, func_str, + libc_epfd, libc_epfd, events, maxevents, sigmask); + + rv = libc_epoll_pwait (libc_epfd, events, maxevents, 1, sigmask); + if (rv != 0) + goto done; + } + + if (timeout != -1) + now = clib_time_now (&ldp->clib_time); + } + while (now < time_out); + +done: + if (LDP_DEBUG > 3) + { + if (libc_epfd > 0) + epfd = libc_epfd; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), epfd, epfd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)", + getpid (), epfd, epfd, rv, rv); + } + return rv; +} + +int +epoll_pwait (int epfd, struct epoll_event *events, + int maxevents, int timeout, const sigset_t * sigmask) +{ + return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask); +} + +int +epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL); +} + +int +poll (struct pollfd *fds, nfds_t nfds, int timeout) +{ + const char *func_str = __func__; + int rv, i, n_libc_fds, n_revents; + u32 sid; + vcl_poll_t *vp; + double wait_for_time; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: fds %p, nfds %d, timeout %d", + getpid (), fds, nfds, timeout); + + if (timeout >= 0) + wait_for_time = (f64) timeout / 1000; + else + wait_for_time = -1; + + n_libc_fds = 0; + for (i = 0; i < nfds; i++) + { + if (fds[i].fd >= 0) + { + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), .events = 0x%x, " + ".revents = 0x%x", getpid (), i, fds[i].fd, + fds[i].fd, fds[i].events, fds[i].revents); + + sid = ldp_sid_from_fd (fds[i].fd); + if (sid != INVALID_SESSION_ID) + { + fds[i].fd = -fds[i].fd; + vec_add2 (ldp->vcl_poll, vp, 1); + vp->fds_ndx = i; + vp->sid = sid; + vp->events = fds[i].events; +#ifdef __USE_XOPEN2K + if (fds[i].events & POLLRDNORM) + vp->events |= POLLIN; + if (fds[i].events & POLLWRNORM) + vp->events |= POLLOUT; +#endif + vp->revents = &fds[i].revents; + } + else + n_libc_fds++; + } + } + + n_revents = 0; + do + { + if (vec_len (ldp->vcl_poll)) + { + func_str = "vppcom_poll"; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: calling %s(): " + "vcl_poll %p, n_sids %u (0x%x): " + "n_libc_fds %u", + getpid (), func_str, ldp->vcl_poll, + vec_len (ldp->vcl_poll), vec_len (ldp->vcl_poll), + n_libc_fds); + + rv = vppcom_poll (ldp->vcl_poll, vec_len (ldp->vcl_poll), 0); + if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } + else + n_revents += rv; + } + + if (n_libc_fds) + { + func_str = "libc_poll"; + + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u", + getpid (), fds, nfds, vec_len (ldp->vcl_poll)); + + rv = libc_poll (fds, nfds, 0); + if (rv < 0) + goto done; + else + n_revents += rv; + } + + if (n_revents) + { + rv = n_revents; + goto done; + } + } + while ((wait_for_time == -1) || + (clib_time_now (&ldp->clib_time) < wait_for_time)); + rv = 0; + +done: + vec_foreach (vp, ldp->vcl_poll) + { + fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd; +#ifdef __USE_XOPEN2K + if ((fds[vp->fds_ndx].revents & POLLIN) && + (fds[vp->fds_ndx].events & POLLRDNORM)) + fds[vp->fds_ndx].revents |= POLLRDNORM; + if ((fds[vp->fds_ndx].revents & POLLOUT) && + (fds[vp->fds_ndx].events & POLLWRNORM)) + fds[vp->fds_ndx].revents |= POLLWRNORM; +#endif + } + vec_reset_length (ldp->vcl_poll); + + if (LDP_DEBUG > 3) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", getpid (), + func_str, rv, errno_val); + errno = errno_val; + } + else + { + clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, " + "n_libc_fds %d", getpid (), rv, rv, + vec_len (ldp->vcl_poll), n_libc_fds); + + for (i = 0; i < nfds; i++) + { + if (fds[i].fd >= 0) + { + if (LDP_DEBUG > 3) + clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), " + ".events = 0x%x, .revents = 0x%x", + getpid (), i, fds[i].fd, fds[i].fd, + fds[i].events, fds[i].revents); + } + } + } + } + + return rv; +} + +#ifdef USE_GNU +int +ppoll (struct pollfd *fds, nfds_t nfds, + const struct timespec *timeout, const sigset_t * sigmask) +{ + if ((errno = -ldp_init ())) + return -1; + + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + + + return -1; +} +#endif + +void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void); + +void DESTRUCTOR_ATTRIBUTE ldp_destructor (void); + +/* + * This function is called when the library is loaded + */ +void +ldp_constructor (void) +{ + swrap_constructor (); + if (ldp_init () != 0) + fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n", + getpid ()); + else + clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ()); +} + +/* + * This function is called when the library is unloaded + */ +void +ldp_destructor (void) +{ + swrap_destructor (); + if (ldp->init) + { + vppcom_app_destroy (); + ldp->init = 0; + } + + /* Don't use clib_warning() here because that calls writev() + * which will call ldp_init(). + */ + printf ("%s:%d: LDP<%d>: LDP destructor: done!\n", + __func__, __LINE__, getpid ()); +} + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vcl/ldp.h b/src/vcl/ldp.h new file mode 100644 index 00000000000..f96219f753b --- /dev/null +++ b/src/vcl/ldp.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 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. + */ + +#ifndef included_ldp_h +#define included_ldp_h + +#if (CLIB_DEBUG > 0) +/* Set LDP_DEBUG 2 for connection debug, 3 for read/write debug output */ +#define LDP_DEBUG_INIT 1 +#else +#define LDP_DEBUG_INIT 0 +#endif + +#include +#include +#include + +#define LDP_ENV_DEBUG "LDP_DEBUG" +#define LDP_ENV_APP_NAME "LDP_APP_NAME" +#define LDP_ENV_SID_BIT "LDP_SID_BIT" + +#define LDP_SID_BIT_MIN 9 +#define LDP_SID_BIT_MAX 30 + +#define LDP_APP_NAME_MAX 256 + +#endif /* included_ldp_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vcl/ldp_glibc_socket.h b/src/vcl/ldp_glibc_socket.h new file mode 100644 index 00000000000..a9e5dbe04e0 --- /dev/null +++ b/src/vcl/ldp_glibc_socket.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2017 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. + */ + +#ifndef included_ldp_glibc_socket_h +#define included_ldp_glibc_socket_h + +#include +#include +#include +#include +#include + +#include + +#include +#include + +/* + * + * Generic glibc fd api + * + */ +/* + * glibc APIs from + */ + +/* Close the file descriptor FD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int close (int __fd); + +/* Read NBYTES into BUF from FD. Return the + number read, -1 for errors or 0 for EOF. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t __wur read (int __fd, void *__buf, size_t __nbytes); + +/* Write N bytes of BUF to FD. Return the number written, or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t __wur write (int __fd, const void *__buf, size_t __n); + + +/* + * glibc APIs from + */ + +/* Do the file control operation described by CMD on FD. + The remaining arguments are interpreted depending on CMD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int fcntl (int __fd, int __cmd, ...); + + +/* + * glibc APIs from + */ + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Returns the number of ready + descriptors, or -1 for errors. + + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +select (int __nfds, fd_set * __restrict __readfds, + fd_set * __restrict __writefds, + fd_set * __restrict __exceptfds, + struct timeval *__restrict __timeout); + +#ifdef __USE_XOPEN2K +/* Same as above only that the TIMEOUT value is given with higher + resolution and a sigmask which is been set temporarily. This version + should be used. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +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 + + +/* + * + * Socket specific glibc api + * + */ + +/* + * glibc APIs from + */ + +/* Create a new socket of type TYPE in domain DOMAIN, using + protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. + Returns a file descriptor for the new socket, or -1 for errors. */ +extern int __THROW socket (int __domain, int __type, int __protocol); + +/* Create two new sockets, of type TYPE in domain DOMAIN and using + protocol PROTOCOL, which are connected to each other, and put file + descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, + one will be chosen automatically. Returns 0 on success, -1 for errors. */ +extern int __THROW +socketpair (int __domain, int __type, int __protocol, int __fds[2]); + +/* Give the socket FD the local address ADDR (which is LEN bytes long). */ +extern int __THROW +bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); + +/* Put the local address of FD into *ADDR and its length in *LEN. */ +extern int __THROW +getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len); + +/* Open a connection on socket FD to peer at ADDR (which LEN bytes long). + For connectionless socket types, just set the default address to send to + and the only address from which to accept transmissions. + Return 0 on success, -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); + +/* Put the address of the peer connected to socket FD into *ADDR + (which is *LEN bytes long), and its actual length into *LEN. */ +extern int __THROW +getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len); + +/* Send N bytes of BUF to socket FD. Returns the number sent or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); + +extern ssize_t sendfile (int __out_fd, int __in_fd, off_t * __offset, + size_t __len); + +/* Read N bytes into BUF from socket FD. + Returns the number read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); + +/* Send N bytes of BUF on socket FD to peer at address ADDR (which is + ADDR_LEN bytes long). Returns the number sent, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t +sendto (int __fd, const void *__buf, size_t __n, + int __flags, __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len); + +/* Read N bytes into BUF through socket FD. + If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of + the sender, and store the actual size of the address in *ADDR_LEN. + Returns the number of bytes read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t +recvfrom (int __fd, void *__restrict __buf, + size_t __n, int __flags, + __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len); + +/* Send a message described MESSAGE on socket FD. + Returns the number of bytes sent, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t +sendmsg (int __fd, const struct msghdr *__message, int __flags); + +#ifdef __USE_GNU +/* Send a VLEN messages as described by VMESSAGES to socket FD. + Returns the number of datagrams successfully written or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +sendmmsg (int __fd, struct mmsghdr *__vmessages, + unsigned int __vlen, int __flags); +#endif + +/* Receive a message as described by MESSAGE from socket FD. + Returns the number of bytes read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); + +#ifdef __USE_GNU +/* Receive up to VLEN messages as described by VMESSAGES from socket FD. + Returns the number of messages received or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +recvmmsg (int __fd, struct mmsghdr *__vmessages, + unsigned int __vlen, int __flags, struct timespec *__tmo); +#endif + + +/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL + into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's + actual length. Returns 0 on success, -1 for errors. */ +extern int __THROW +getsockopt (int __fd, int __level, int __optname, + void *__restrict __optval, socklen_t * __restrict __optlen); + +/* Set socket FD's option OPTNAME at protocol level LEVEL + to *OPTVAL (which is OPTLEN bytes long). + Returns 0 on success, -1 for errors. */ +extern int __THROW +setsockopt (int __fd, int __level, int __optname, + const void *__optval, socklen_t __optlen); + +/* Prepare to accept connections on socket FD. + N connection requests will be queued before further requests are refused. + Returns 0 on success, -1 for errors. */ +extern int __THROW listen (int __fd, int __n); + +/* Await a connection on socket FD. + When a connection arrives, open a new socket to communicate with it, + set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting + peer and *ADDR_LEN to the address's actual length, and return the + new socket's descriptor, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len); + +/* Similar to 'accept' but takes an additional parameter to specify flags. + + This function is a cancellation point and therefore not marked with + __THROW. */ + /* TBD: implemented later */ +extern int +accept4 (int __fd, __SOCKADDR_ARG __addr, + socklen_t * __restrict __addr_len, int __flags); + +/* Shut down all or part of the connection open on socket FD. + HOW determines what to shut down: + SHUT_RD = No more receptions; + SHUT_WR = No more transmissions; + SHUT_RDWR = No more receptions or transmissions. + Returns 0 on success, -1 for errors. */ +extern int __THROW shutdown (int __fd, int __how); + + +/* + * glibc APIs from + */ + +/* Creates an epoll instance. Returns an fd for the new instance. + The "size" parameter is a hint specifying the number of file + descriptors to be associated with the new instance. The fd + returned by epoll_create() should be closed with close(). */ +extern int __THROW epoll_create (int __size); + +/* Same as epoll_create but with an FLAGS parameter. The unused SIZE + parameter has been dropped. */ +extern int __THROW epoll_create1 (int __flags); + +/* Manipulate an epoll instance "epfd". Returns 0 in case of success, + -1 in case of error ( the "errno" variable will contain the + specific error code ) The "op" parameter is one of the EPOLL_CTL_* + constants defined above. The "fd" parameter is the target of the + operation. The "event" parameter describes which events the caller + is interested in and any associated user data. */ +extern int __THROW +epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event); + +#define EP_INT_MAX ((int)(~0U>>1)) +#define EP_MAX_EVENTS (EP_INT_MAX / sizeof(struct epoll_event)) + +/* Wait for events on an epoll instance "epfd". Returns the number of + triggered events returned in "events" buffer. Or -1 in case of + error with the "errno" variable set to the specific error code. The + "events" parameter is a buffer that will contain triggered + events. The "maxevents" is the maximum number of events to be + returned ( usually size of "events" ). The "timeout" parameter + specifies the maximum wait time in milliseconds (-1 == infinite). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout); + +/* Same as epoll_wait, but the thread's signal mask is temporarily + and atomically replaced with the one provided as parameter. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int +epoll_pwait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout, const __sigset_t * __ss); + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); + +#ifdef __USE_GNU +/* Like poll, but before waiting the threads signal mask is replaced + with that specified in the fourth parameter. For better usability, + the timeout value is specified using a TIMESPEC object. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss); +#endif + + +#endif /* included_ldp_glibc_socket_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ 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: + */ diff --git a/src/vcl/ldp_socket_wrapper.h b/src/vcl/ldp_socket_wrapper.h new file mode 100644 index 00000000000..59e4eaef394 --- /dev/null +++ b/src/vcl/ldp_socket_wrapper.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2017 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. +*/ + +#ifndef included_ldp_socket_wrapper_h +#define included_ldp_socket_wrapper_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* GCC have printf type attribute check. */ +#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT +#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) +#else +#define PRINTF_ATTRIBUTE(a,b) +#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */ + +#define HAVE_CONSTRUCTOR_ATTRIBUTE +#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE +#define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor)) +#else +#define CONSTRUCTOR_ATTRIBUTE +#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ + +#define HAVE_DESTRUCTOR_ATTRIBUTE +#ifdef HAVE_DESTRUCTOR_ATTRIBUTE +#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) +#else +#define DESTRUCTOR_ATTRIBUTE +#endif + +#define HAVE_ADDRESS_SANITIZER_ATTRIBUTE +#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE +#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address)) +#else +#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE +#endif + +/* + * 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); + +int libc_accept (int sockfd, struct sockaddr *addr, socklen_t * addrlen); + +int libc_bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen); + +int libc_close (int fd); + +int libc_connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen); + +#if 0 +/* TBD: dup and dup2 to be implemented later */ +int libc_dup (int fd); + +int libc_dup2 (int oldfd, int newfd); +#endif + +#ifdef HAVE_EVENTFD +int libc_eventfd (int count, int flags); +#endif + +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int +libc_vfcntl (int fd, int cmd, va_list ap); + +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int +libc_vioctl (int fd, int cmd, va_list ap); + +int libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen); + +int libc_getsockname (int sockfd, struct sockaddr *addr, socklen_t * addrlen); + +int +libc_getsockopt (int sockfd, + int level, int optname, void *optval, socklen_t * optlen); + +int libc_listen (int sockfd, int backlog); + +int libc_read (int fd, void *buf, size_t count); + +ssize_t libc_readv (int fd, const struct iovec *iov, int iovcnt); + +int libc_recv (int sockfd, void *buf, size_t len, int flags); + +int +libc_recvfrom (int sockfd, + void *buf, + size_t len, + int flags, struct sockaddr *src_addr, socklen_t * addrlen); + +int libc_recvmsg (int sockfd, struct msghdr *msg, int flags); + +int libc_send (int sockfd, const void *buf, size_t len, int flags); + +ssize_t libc_sendfile (int out_fd, int in_fd, off_t * offset, size_t len); + +int libc_sendmsg (int sockfd, const struct msghdr *msg, int flags); + +int +libc_sendto (int sockfd, + const void *buf, + size_t len, + int flags, const struct sockaddr *dst_addr, socklen_t addrlen); + +int +libc_setsockopt (int sockfd, + int level, int optname, const void *optval, + socklen_t optlen); + +int libc_socket (int domain, int type, int protocol); + +int libc_socketpair (int domain, int type, int protocol, int sv[2]); + +ssize_t libc_write (int fd, const void *buf, size_t count); + +ssize_t libc_writev (int fd, const struct iovec *iov, int iovcnt); + +int libc_shutdown (int fd, int how); + +int +libc_select (int __nfds, fd_set * __restrict __readfds, + fd_set * __restrict __writefds, + fd_set * __restrict __exceptfds, + struct timeval *__restrict __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); +#endif + +int libc_epoll_create (int __size); + +int libc_epoll_create1 (int __flags); + +int libc_epoll_ctl (int __epfd, int __op, int __fd, + struct epoll_event *__event); + +int libc_epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout); + +int libc_epoll_pwait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout, + const __sigset_t * __ss); + +int libc_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); + +#ifdef __USE_GNU +int libc_ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss); +#endif + +void swrap_constructor (void); + +void swrap_destructor (void); + +#endif /* included_ldp_socket_wrapper_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vcl/vcom.c b/src/vcl/vcom.c deleted file mode 100644 index 82c65e854e0..00000000000 --- a/src/vcl/vcom.c +++ /dev/null @@ -1,3447 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#define HAVE_CONSTRUCTOR_ATTRIBUTE -#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE -#define CONSTRUCTOR_ATTRIBUTE \ - __attribute__ ((constructor)) -#else -#define CONSTRUCTOR_ATTRIBUTE -#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ - -#define HAVE_DESTRUCTOR_ATTRIBUTE -#ifdef HAVE_DESTRUCTOR_ATTRIBUTE -#define DESTRUCTOR_ATTRIBUTE \ - __attribute__ ((destructor)) -#else -#define DESTRUCTOR_ATTRIBUTE -#endif - -typedef struct -{ - int init; - char app_name[VCOM_APP_NAME_MAX]; - u32 sid_bit_val; - u32 sid_bit_mask; - u32 debug; - u8 *io_buffer; - clib_time_t clib_time; - clib_bitmap_t *rd_bitmap; - clib_bitmap_t *wr_bitmap; - clib_bitmap_t *ex_bitmap; - clib_bitmap_t *sid_rd_bitmap; - clib_bitmap_t *sid_wr_bitmap; - clib_bitmap_t *sid_ex_bitmap; - clib_bitmap_t *libc_rd_bitmap; - clib_bitmap_t *libc_wr_bitmap; - clib_bitmap_t *libc_ex_bitmap; - vcl_poll_t *vcl_poll; - u8 select_vcl; - u8 epoll_wait_vcl; -} vcom_main_t; -#define VCOM_DEBUG vcom->debug - -static vcom_main_t vcom_main = { - .sid_bit_val = (1 << VCOM_SID_BIT_MIN), - .sid_bit_mask = (1 << VCOM_SID_BIT_MIN) - 1, - .debug = VCOM_DEBUG_INIT, -}; - -static vcom_main_t *vcom = &vcom_main; - -/* - * RETURN: 0 on success or -1 on error. - * */ -static inline void -vcom_set_app_name (char *app_name) -{ - int rv = snprintf (vcom->app_name, VCOM_APP_NAME_MAX, - "vcom-%d-%s", getpid (), app_name); - - if (rv >= VCOM_APP_NAME_MAX) - app_name[VCOM_APP_NAME_MAX - 1] = 0; -} - -static inline char * -vcom_get_app_name () -{ - if (vcom->app_name[0] == '\0') - vcom_set_app_name ("app"); - - return vcom->app_name; -} - -static inline int -vcom_fd_from_sid (u32 sid) -{ - if (PREDICT_FALSE (sid >= vcom->sid_bit_val)) - return -EMFILE; - else - return (sid | vcom->sid_bit_val); -} - -static inline int -vcom_fd_is_sid (int fd) -{ - return ((u32) fd & vcom->sid_bit_val) ? 1 : 0; -} - -static inline u32 -vcom_sid_from_fd (int fd) -{ - return (vcom_fd_is_sid (fd) ? ((u32) fd & vcom->sid_bit_mask) : - INVALID_SESSION_ID); -} - -static inline int -vcom_init (void) -{ - int rv = 0; - - if (PREDICT_FALSE (!vcom->init)) - { - vcom->init = 1; - rv = vppcom_app_create (vcom_get_app_name ()); - if (rv == VPPCOM_OK) - { - char *env_var_str = getenv (VCOM_ENV_DEBUG); - if (env_var_str) - { - u32 tmp; - if (sscanf (env_var_str, "%u", &tmp) != 1) - clib_warning ("LDP<%d>: WARNING: Invalid VCOM debug level " - "specified in the env var " VCOM_ENV_DEBUG - " (%s)!", getpid (), env_var_str); - else - { - vcom->debug = tmp; - clib_warning ("LDP<%d>: configured VCOM debug level (%u) " - "from the env var " VCOM_ENV_DEBUG "!", - getpid (), vcom->debug); - } - } - - env_var_str = getenv (VCOM_ENV_APP_NAME); - if (env_var_str) - { - vcom_set_app_name (env_var_str); - clib_warning ("LDP<%d>: configured VCOM app name (%s) " - "from the env var " VCOM_ENV_APP_NAME "!", - getpid (), vcom->app_name); - } - - env_var_str = getenv (VCOM_ENV_SID_BIT); - if (env_var_str) - { - u32 sb; - if (sscanf (env_var_str, "%u", &sb) != 1) - { - clib_warning ("LDP<%d>: WARNING: Invalid VCOM sid bit " - "specified in the env var " - VCOM_ENV_SID_BIT " (%s)!" - "sid bit value %d (0x%x)", - getpid (), env_var_str, - vcom->sid_bit_val, vcom->sid_bit_val); - } - else if (sb < VCOM_SID_BIT_MIN) - { - vcom->sid_bit_val = (1 << VCOM_SID_BIT_MIN); - vcom->sid_bit_mask = vcom->sid_bit_val - 1; - - clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) " - "specified in the env var " - VCOM_ENV_SID_BIT " (%s) is too small. " - "Using VCOM_SID_BIT_MIN (%d)! " - "sid bit value %d (0x%x)", - getpid (), sb, env_var_str, VCOM_SID_BIT_MIN, - vcom->sid_bit_val, vcom->sid_bit_val); - } - else if (sb > VCOM_SID_BIT_MAX) - { - vcom->sid_bit_val = (1 << VCOM_SID_BIT_MAX); - vcom->sid_bit_mask = vcom->sid_bit_val - 1; - - clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) " - "specified in the env var " - VCOM_ENV_SID_BIT " (%s) is too big. " - "Using VCOM_SID_BIT_MAX (%d)! " - "sid bit value %d (0x%x)", - getpid (), sb, env_var_str, VCOM_SID_BIT_MAX, - vcom->sid_bit_val, vcom->sid_bit_val); - } - else - { - vcom->sid_bit_val = (1 << sb); - vcom->sid_bit_mask = vcom->sid_bit_val - 1; - - clib_warning ("LDP<%d>: configured VCOM sid bit (%u) " - "from " VCOM_ENV_SID_BIT - "! sid bit value %d (0x%x)", getpid (), - sb, vcom->sid_bit_val, vcom->sid_bit_val); - } - } - - clib_time_init (&vcom->clib_time); - clib_warning ("LDP<%d>: VCOM initialization: done!", getpid ()); - } - else - { - fprintf (stderr, "\nLDP<%d>: ERROR: vcom_init: vppcom_app_create()" - " failed! rv = %d (%s)\n", - getpid (), rv, vppcom_retval_str (rv)); - vcom->init = 0; - } - } - return rv; -} - -int -close (int fd) -{ - int rv; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - int epfd; - - func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; - epfd = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); - if (epfd > 0) - { - func_str = "libc_close"; - - if (VCOM_DEBUG > 0) - clib_warning - ("LDP<%d>: fd %d (0x%x): calling %s(): epfd %u (0x%x)", - getpid (), fd, fd, func_str, epfd, epfd); - - rv = libc_close (epfd); - if (rv < 0) - { - u32 size = sizeof (epfd); - epfd = 0; - - (void) vppcom_session_attr (sid, VPPCOM_ATTR_SET_LIBC_EPFD, - &epfd, &size); - } - } - else if (PREDICT_FALSE (epfd < 0)) - { - errno = -epfd; - rv = -1; - goto done; - } - - func_str = "vppcom_session_close"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - - rv = vppcom_session_close (sid); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_close"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s()", - getpid (), fd, fd, func_str); - - rv = libc_close (fd); - } - -done: - if (VCOM_DEBUG > 0) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -ssize_t -read (int fd, void *buf, size_t nbytes) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_read"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), buf %p, nbytes %u", getpid (), - fd, fd, func_str, sid, sid, buf, nbytes); - - size = vppcom_session_read (sid, buf, nbytes); - if (size < 0) - { - errno = -size; - size = -1; - } - } - else - { - func_str = "libc_read"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "buf %p, nbytes %u", getpid (), - fd, fd, func_str, buf, nbytes); - - size = libc_read (fd, buf, nbytes); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -readv (int fd, const struct iovec * iov, int iovcnt) -{ - const char *func_str; - ssize_t size = 0; - u32 sid = vcom_sid_from_fd (fd); - int rv = 0, i, total = 0; - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_read"; - do - { - for (i = 0; i < iovcnt; ++i) - { - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s() [%d]: " - "sid %u (0x%x), iov %p, iovcnt %d, total %d", - getpid (), fd, fd, func_str, i, sid, sid, - iov, iovcnt, total); - - rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len); - if (rv < 0) - break; - else - { - total += rv; - if (rv < iov[i].iov_len) - { - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): " - "rv (%d) < iov[%d].iov_len (%d)", - getpid (), fd, fd, rv, i, - iov[i].iov_len); - break; - } - } - } - } - while ((rv >= 0) && (total == 0)); - - if (rv < 0) - { - errno = -rv; - size = -1; - } - else - size = total; - } - else - { - func_str = "libc_readv"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "iov %p, iovcnt %d", getpid (), fd, fd, iov, iovcnt); - - size = libc_readv (fd, iov, iovcnt); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -write (int fd, const void *buf, size_t nbytes) -{ - const char *func_str; - ssize_t size = 0; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_write"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), buf %p, nbytes %u", getpid (), - fd, fd, func_str, sid, sid, buf, nbytes); - - size = vppcom_session_write (sid, (void *) buf, nbytes); - if (size < 0) - { - errno = -size; - size = -1; - } - } - else - { - func_str = "libc_write"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "buf %p, nbytes %u", getpid (), - fd, fd, func_str, buf, nbytes); - - size = libc_write (fd, buf, nbytes); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -writev (int fd, const struct iovec * iov, int iovcnt) -{ - const char *func_str; - ssize_t size = 0, total = 0; - u32 sid = vcom_sid_from_fd (fd); - int i, rv = 0; - - /* - * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV. - */ - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_write"; - do - { - for (i = 0; i < iovcnt; ++i) - { - if (VCOM_DEBUG > 4) - printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s() [%d]: " - "sid %u (0x%x), buf %p, nbytes %ld, total %ld", - __func__, __LINE__, getpid (), fd, fd, func_str, - i, sid, sid, iov[i].iov_base, iov[i].iov_len, total); - - rv = vppcom_session_write (sid, iov[i].iov_base, - iov[i].iov_len); - if (rv < 0) - break; - else - { - total += rv; - if (rv < iov[i].iov_len) - { - if (VCOM_DEBUG > 4) - printf ("%s:%d: LDP<%d>: fd %d (0x%x): " - "rv (%d) < iov[%d].iov_len (%ld)", - __func__, __LINE__, getpid (), fd, fd, - rv, i, iov[i].iov_len); - break; - } - } - } - } - while ((rv >= 0) && (total == 0)); - - if (rv < 0) - { - errno = -rv; - size = -1; - } - else - size = total; - } - else - { - func_str = "libc_writev"; - - if (VCOM_DEBUG > 4) - printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s(): " - "iov %p, iovcnt %d\n", __func__, __LINE__, getpid (), - fd, fd, func_str, iov, iovcnt); - - size = libc_writev (fd, iov, iovcnt); - } - - if (VCOM_DEBUG > 4) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - fprintf (stderr, - "%s:%d: LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %ld, errno = %d\n", __func__, __LINE__, getpid (), fd, - fd, func_str, size, errno_val); - errno = errno_val; - } - else - printf ("%s:%d: LDP<%d>: fd %d (0x%x): returning %ld\n", - __func__, __LINE__, getpid (), fd, fd, size); - } - return size; -} - -int -fcntl (int fd, int cmd, ...) -{ - const char *func_str = __func__; - int rv = 0; - va_list ap; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - va_start (ap, cmd); - if (sid != INVALID_SESSION_ID) - { - int flags = va_arg (ap, int); - u32 size; - - size = sizeof (flags); - rv = -EOPNOTSUPP; - switch (cmd) - { - case F_SETFL: - func_str = "vppcom_session_attr[SET_FLAGS]"; - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x) flags %d (0x%x), size %d", - getpid (), fd, fd, func_str, sid, sid, - flags, flags, size); - - rv = - vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size); - break; - - case F_GETFL: - func_str = "vppcom_session_attr[GET_FLAGS]"; - if (VCOM_DEBUG > 2) - clib_warning - ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " - "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid, - sid, flags, flags, size); - - rv = - vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size); - if (rv == VPPCOM_OK) - { - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x), cmd %d (F_GETFL): " - "%s() returned flags %d (0x%x)", - getpid (), fd, fd, cmd, func_str, flags, flags); - rv = flags; - } - break; - - default: - rv = -EOPNOTSUPP; - break; - } - if (rv < 0) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_vfcntl"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d", - getpid (), fd, fd, func_str, cmd); - - rv = libc_vfcntl (fd, cmd, ap); - } - - va_end (ap); - - if (VCOM_DEBUG > 2) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -int -ioctl (int fd, unsigned long int cmd, ...) -{ - const char *func_str; - int rv; - va_list ap; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - va_start (ap, cmd); - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_attr[GET_NREAD]"; - - switch (cmd) - { - case FIONREAD: - if (VCOM_DEBUG > 2) - clib_warning - ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0); - break; - - case FIONBIO: - { - u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0; - u32 size = sizeof (flags); - - /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than - * non-blocking, the flags should be read here and merged - * with O_NONBLOCK. - */ - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), flags %d (0x%x), size %d", - getpid (), fd, fd, func_str, sid, sid, - flags, flags, size); - - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, - &size); - } - break; - - default: - rv = -EOPNOTSUPP; - break; - } - if (rv < 0) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_vioctl"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d", - getpid (), fd, fd, func_str, cmd); - - rv = libc_vioctl (fd, cmd, ap); - } - - if (VCOM_DEBUG > 2) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - va_end (ap); - return rv; -} - -int -vcom_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) -{ - int rv; - char *func_str = "##"; - f64 time_out; - int fd; - uword sid_bits, sid_bits_set, libc_bits, libc_bits_set; - u32 minbits = clib_max (nfds, BITS (uword)); - u32 sid; - - if (nfds < 0) - { - errno = EINVAL; - return -1; - } - - if (nfds <= vcom->sid_bit_val) - { - func_str = "libc_pselect"; - - if (VCOM_DEBUG > 3) - clib_warning - ("LDP<%d>: calling %s(): nfds %d, readfds %p, writefds %p, " - "exceptfds %p, timeout %p, sigmask %p", getpid (), func_str, nfds, - readfds, writefds, exceptfds, timeout, sigmask); - - rv = libc_pselect (nfds, readfds, writefds, exceptfds, - timeout, sigmask); - goto done; - } - - if (PREDICT_FALSE (vcom->sid_bit_val > FD_SETSIZE / 2)) - { - clib_warning ("LDP<%d>: ERROR: VCOM sid bit value %d (0x%x) > " - "FD_SETSIZE/2 %d (0x%x)!", getpid (), - vcom->sid_bit_val, vcom->sid_bit_val, - FD_SETSIZE / 2, FD_SETSIZE / 2); - errno = EOVERFLOW; - return -1; - } - - if (timeout) - { - time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ? - (f64) 0 : (f64) timeout->tv_sec + - (f64) timeout->tv_nsec / (f64) 1000000000 + - (f64) (timeout->tv_nsec % 1000000000) / (f64) 1000000000; - - /* select as fine grained sleep */ - if (!nfds) - { - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: sleeping for %f seconds", - getpid (), time_out); - - time_out += clib_time_now (&vcom->clib_time); - while (clib_time_now (&vcom->clib_time) < time_out) - ; - return 0; - } - } - else if (!nfds) - { - errno = EINVAL; - return -1; - } - else - time_out = -1; - - sid_bits = libc_bits = 0; - if (readfds) - { - clib_bitmap_validate (vcom->sid_rd_bitmap, minbits); - clib_bitmap_validate (vcom->libc_rd_bitmap, minbits); - clib_bitmap_validate (vcom->rd_bitmap, minbits); - clib_memcpy (vcom->rd_bitmap, readfds, - vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t)); - FD_ZERO (readfds); - - /* *INDENT-OFF* */ - clib_bitmap_foreach (fd, vcom->rd_bitmap, - ({ - sid = vcom_sid_from_fd (fd); - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: readfds: fd %d (0x%x), sid %u (0x%x)", - getpid (), fd, fd, sid, sid); - if (sid == INVALID_SESSION_ID) - clib_bitmap_set_no_check (vcom->libc_rd_bitmap, fd, 1); - else - clib_bitmap_set_no_check (vcom->sid_rd_bitmap, sid, 1); - })); - /* *INDENT-ON* */ - - sid_bits_set = clib_bitmap_last_set (vcom->sid_rd_bitmap) + 1; - sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; - - libc_bits_set = clib_bitmap_last_set (vcom->libc_rd_bitmap) + 1; - libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: readfds: sid_bits_set %d, sid_bits %d, " - "libc_bits_set %d, libc_bits %d", getpid (), - sid_bits_set, sid_bits, libc_bits_set, libc_bits); - } - if (writefds) - { - clib_bitmap_validate (vcom->sid_wr_bitmap, minbits); - clib_bitmap_validate (vcom->libc_wr_bitmap, minbits); - clib_bitmap_validate (vcom->wr_bitmap, minbits); - clib_memcpy (vcom->wr_bitmap, writefds, - vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t)); - FD_ZERO (writefds); - - /* *INDENT-OFF* */ - clib_bitmap_foreach (fd, vcom->wr_bitmap, - ({ - sid = vcom_sid_from_fd (fd); - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: writefds: fd %d (0x%x), sid %u (0x%x)", - getpid (), fd, fd, sid, sid); - if (sid == INVALID_SESSION_ID) - clib_bitmap_set_no_check (vcom->libc_wr_bitmap, fd, 1); - else - clib_bitmap_set_no_check (vcom->sid_wr_bitmap, sid, 1); - })); - /* *INDENT-ON* */ - - sid_bits_set = clib_bitmap_last_set (vcom->sid_wr_bitmap) + 1; - sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; - - libc_bits_set = clib_bitmap_last_set (vcom->libc_wr_bitmap) + 1; - libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: writefds: sid_bits_set %d, sid_bits %d, " - "libc_bits_set %d, libc_bits %d", getpid (), - sid_bits_set, sid_bits, libc_bits_set, libc_bits); - } - if (exceptfds) - { - clib_bitmap_validate (vcom->sid_ex_bitmap, minbits); - clib_bitmap_validate (vcom->libc_ex_bitmap, minbits); - clib_bitmap_validate (vcom->ex_bitmap, minbits); - clib_memcpy (vcom->ex_bitmap, exceptfds, - vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t)); - FD_ZERO (exceptfds); - - /* *INDENT-OFF* */ - clib_bitmap_foreach (fd, vcom->ex_bitmap, - ({ - sid = vcom_sid_from_fd (fd); - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: exceptfds: fd %d (0x%x), sid %u (0x%x)", - getpid (), fd, fd, sid, sid); - if (sid == INVALID_SESSION_ID) - clib_bitmap_set_no_check (vcom->libc_ex_bitmap, fd, 1); - else - clib_bitmap_set_no_check (vcom->sid_ex_bitmap, sid, 1); - })); - /* *INDENT-ON* */ - - sid_bits_set = clib_bitmap_last_set (vcom->sid_ex_bitmap) + 1; - sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; - - libc_bits_set = clib_bitmap_last_set (vcom->libc_ex_bitmap) + 1; - libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: exceptfds: sid_bits_set %d, sid_bits %d, " - "libc_bits_set %d, libc_bits %d", getpid (), - sid_bits_set, sid_bits, libc_bits_set, libc_bits); - } - - if (PREDICT_FALSE (!sid_bits && !libc_bits)) - { - errno = EINVAL; - rv = -1; - goto done; - } - - do - { - if (sid_bits) - { - if (!vcom->select_vcl) - { - func_str = "vppcom_select"; - - if (readfds) - clib_memcpy (vcom->rd_bitmap, vcom->sid_rd_bitmap, - vec_len (vcom->rd_bitmap) * - sizeof (clib_bitmap_t)); - if (writefds) - clib_memcpy (vcom->wr_bitmap, vcom->sid_wr_bitmap, - vec_len (vcom->wr_bitmap) * - sizeof (clib_bitmap_t)); - if (exceptfds) - clib_memcpy (vcom->ex_bitmap, vcom->sid_ex_bitmap, - vec_len (vcom->ex_bitmap) * - sizeof (clib_bitmap_t)); - - rv = vppcom_select (sid_bits, - readfds ? vcom->rd_bitmap : NULL, - writefds ? vcom->wr_bitmap : NULL, - exceptfds ? vcom->ex_bitmap : NULL, 0); - if (rv < 0) - { - errno = -rv; - rv = -1; - } - else if (rv > 0) - { - if (readfds) - { - /* *INDENT-OFF* */ - clib_bitmap_foreach (sid, vcom->rd_bitmap, - ({ - fd = vcom_fd_from_sid (sid); - if (PREDICT_FALSE (fd < 0)) - { - errno = EBADFD; - rv = -1; - goto done; - } - FD_SET (fd, readfds); - })); - /* *INDENT-ON* */ - } - if (writefds) - { - /* *INDENT-OFF* */ - clib_bitmap_foreach (sid, vcom->wr_bitmap, - ({ - fd = vcom_fd_from_sid (sid); - if (PREDICT_FALSE (fd < 0)) - { - errno = EBADFD; - rv = -1; - goto done; - } - FD_SET (fd, writefds); - })); - /* *INDENT-ON* */ - } - if (exceptfds) - { - /* *INDENT-OFF* */ - clib_bitmap_foreach (sid, vcom->ex_bitmap, - ({ - fd = vcom_fd_from_sid (sid); - if (PREDICT_FALSE (fd < 0)) - { - errno = EBADFD; - rv = -1; - goto done; - } - FD_SET (fd, exceptfds); - })); - /* *INDENT-ON* */ - } - vcom->select_vcl = 1; - goto done; - } - } - else - vcom->select_vcl = 0; - } - if (libc_bits) - { - struct timespec tspec; - - func_str = "libc_pselect"; - - if (readfds) - clib_memcpy (readfds, vcom->libc_rd_bitmap, - vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t)); - if (writefds) - clib_memcpy (writefds, vcom->libc_wr_bitmap, - vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t)); - if (exceptfds) - clib_memcpy (exceptfds, vcom->libc_ex_bitmap, - vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t)); - tspec.tv_sec = tspec.tv_nsec = 0; - rv = libc_pselect (libc_bits, - readfds ? readfds : NULL, - writefds ? writefds : NULL, - exceptfds ? exceptfds : NULL, &tspec, sigmask); - if (rv != 0) - goto done; - } - } - while ((time_out == -1) || (clib_time_now (&vcom->clib_time) < time_out)); - rv = 0; - -done: - /* TBD: set timeout to amount of time left */ - vec_reset_length (vcom->rd_bitmap); - vec_reset_length (vcom->sid_rd_bitmap); - vec_reset_length (vcom->libc_rd_bitmap); - vec_reset_length (vcom->wr_bitmap); - vec_reset_length (vcom->sid_wr_bitmap); - vec_reset_length (vcom->libc_wr_bitmap); - vec_reset_length (vcom->ex_bitmap); - vec_reset_length (vcom->sid_ex_bitmap); - vec_reset_length (vcom->libc_ex_bitmap); - - if (VCOM_DEBUG > 3) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: %s() failed! " - "rv %d, errno = %d", getpid (), - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv); - } - return rv; -} - -int -select (int nfds, fd_set * __restrict readfds, - fd_set * __restrict writefds, - fd_set * __restrict exceptfds, struct timeval *__restrict timeout) -{ - struct timespec tspec; - - if (timeout) - { - tspec.tv_sec = timeout->tv_sec; - tspec.tv_nsec = timeout->tv_usec * 1000; - } - return vcom_pselect (nfds, readfds, writefds, exceptfds, - timeout ? &tspec : NULL, NULL); -} - -#ifdef __USE_XOPEN2K -int -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) -{ - return vcom_pselect (nfds, readfds, writefds, exceptfds, timeout, 0); -} -#endif - -int -socket (int domain, int type, int protocol) -{ - const char *func_str; - int rv; - u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0; - int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); - - if ((errno = -vcom_init ())) - return -1; - - if (((domain == AF_INET) || (domain == AF_INET6)) && - ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM))) - { - int sid; - u8 proto = ((sock_type == SOCK_DGRAM) ? - VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP); - - func_str = "vppcom_session_create"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: : calling %s(): " - "proto %u (%s), is_nonblocking %u", - getpid (), func_str, proto, - vppcom_proto_str (proto), is_nonblocking); - - sid = vppcom_session_create (proto, is_nonblocking); - if (sid < 0) - { - errno = -sid; - rv = -1; - } - else - { - func_str = "vcom_fd_from_sid"; - rv = vcom_fd_from_sid (sid); - if (rv < 0) - { - (void) vppcom_session_close (sid); - errno = -rv; - rv = -1; - } - } - } - else - { - func_str = "libc_socket"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); - - rv = libc_socket (domain, type, protocol); - } - - if (VCOM_DEBUG > 0) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: %s() failed! " - "rv %d, errno = %d", - getpid (), func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv); - } - return rv; -} - -/* - * Create two new sockets, of type TYPE in domain DOMAIN and using - * protocol PROTOCOL, which are connected to each other, and put file - * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, - * one will be chosen automatically. - * Returns 0 on success, -1 for errors. - * */ -int -socketpair (int domain, int type, int protocol, int fds[2]) -{ - const char *func_str; - int rv; - int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); - - if ((errno = -vcom_init ())) - return -1; - - if (((domain == AF_INET) || (domain == AF_INET6)) && - ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM))) - { - func_str = __func__; - - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - rv = -1; - } - else - { - func_str = "libc_socket"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); - - rv = libc_socket (domain, type, protocol); - } - - if (VCOM_DEBUG > 1) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: %s() failed! " - "rv %d, errno = %d", - getpid (), func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv); - } - return rv; -} - -int -bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) -{ - int rv; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - vppcom_endpt_t ep; - - func_str = "vppcom_session_bind"; - - switch (addr->sa_family) - { - case AF_INET: - if (len != sizeof (struct sockaddr_in)) - { - clib_warning - ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid " - "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len); - errno = EINVAL; - rv = -1; - goto done; - } - ep.is_ip4 = VPPCOM_IS_IP4; - ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr; - ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port; - break; - - case AF_INET6: - if (len != sizeof (struct sockaddr_in6)) - { - clib_warning - ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid " - "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len); - errno = EINVAL; - rv = -1; - goto done; - } - ep.is_ip4 = VPPCOM_IS_IP6; - ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; - ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port; - break; - - default: - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): " - "Unsupported address family %u!", - getpid (), fd, fd, sid, sid, addr->sa_family); - errno = EAFNOSUPPORT; - rv = -1; - goto done; - } - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " - "addr %p, len %u", - getpid (), fd, fd, func_str, sid, sid, addr, len); - - rv = vppcom_session_bind (sid, &ep); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_bind"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "addr %p, len %u", - getpid (), fd, fd, func_str, addr, len); - - rv = libc_bind (fd, addr, len); - } - -done: - if (VCOM_DEBUG > 0) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -static inline int -vcom_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len, - vppcom_endpt_t * ep) -{ - int rv = 0; - int sa_len, copy_len; - - if ((errno = -vcom_init ())) - return -1; - - if (addr && len && ep) - { - addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6; - switch (addr->sa_family) - { - case AF_INET: - ((struct sockaddr_in *) addr)->sin_port = ep->port; - if (*len > sizeof (struct sockaddr_in)) - *len = sizeof (struct sockaddr_in); - sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr); - copy_len = *len - sa_len; - if (copy_len > 0) - memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip, - copy_len); - break; - - case AF_INET6: - ((struct sockaddr_in6 *) addr)->sin6_port = ep->port; - if (*len > sizeof (struct sockaddr_in6)) - *len = sizeof (struct sockaddr_in6); - sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr); - copy_len = *len - sa_len; - if (copy_len > 0) - memcpy (((struct sockaddr_in6 *) addr)->sin6_addr. - __in6_u.__u6_addr8, ep->ip, copy_len); - break; - - default: - /* Not possible */ - rv = -EAFNOSUPPORT; - break; - } - } - return rv; -} - -int -getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len) -{ - int rv; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - vppcom_endpt_t ep; - u8 addr_buf[sizeof (struct in6_addr)]; - u32 size = sizeof (ep); - - ep.ip = addr_buf; - func_str = "vppcom_session_attr[GET_LCL_ADDR]"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " - "addr %p, len %u", - getpid (), fd, fd, func_str, sid, sid, addr, len); - - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - else - { - rv = vcom_copy_ep_to_sockaddr (addr, len, &ep); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - } - else - { - func_str = "libc_getsockname"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "addr %p, len %u", - getpid (), fd, fd, func_str, addr, len); - - rv = libc_getsockname (fd, addr, len); - } - - if (VCOM_DEBUG > 2) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -int -connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) -{ - int rv; - const char *func_str = __func__; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (!addr) - { - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u", - getpid (), fd, fd, len); - errno = EINVAL; - rv = -1; - goto done; - } - - if (sid != INVALID_SESSION_ID) - { - vppcom_endpt_t ep; - - func_str = "vppcom_session_connect"; - - switch (addr->sa_family) - { - case AF_INET: - if (len != sizeof (struct sockaddr_in)) - { - clib_warning - ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid " - "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len); - errno = EINVAL; - rv = -1; - goto done; - } - ep.is_ip4 = VPPCOM_IS_IP4; - ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr; - ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port; - break; - - case AF_INET6: - if (len != sizeof (struct sockaddr_in6)) - { - clib_warning - ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid " - "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len); - errno = EINVAL; - rv = -1; - goto done; - } - ep.is_ip4 = VPPCOM_IS_IP6; - ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; - ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port; - break; - - default: - clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): " - "Unsupported address family %u!", - getpid (), fd, fd, sid, sid, addr->sa_family); - errno = EAFNOSUPPORT; - rv = -1; - goto done; - } - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) " - "addr %p len %u", - getpid (), fd, fd, func_str, sid, sid, addr, len); - - rv = vppcom_session_connect (sid, &ep); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_connect"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "addr %p, len %u", - getpid (), fd, fd, func_str, addr, len); - - rv = libc_connect (fd, addr, len); - } - -done: - if (VCOM_DEBUG > 0) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -int -getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len) -{ - int rv; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - vppcom_endpt_t ep; - u8 addr_buf[sizeof (struct in6_addr)]; - u32 size = sizeof (ep); - - ep.ip = addr_buf; - func_str = "vppcom_session_attr[GET_PEER_ADDR]"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " - "addr %p, len %u", - getpid (), fd, fd, func_str, sid, sid, addr, len); - - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - else - { - rv = vcom_copy_ep_to_sockaddr (addr, len, &ep); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - } - else - { - func_str = "libc_getpeername"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "addr %p, len %u", - getpid (), fd, fd, func_str, addr, len); - - rv = libc_getpeername (fd, addr, len); - } - - if (VCOM_DEBUG > 2) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -ssize_t -send (int fd, const void *buf, size_t n, int flags) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - - func_str = "vppcom_session_sendto"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " - "buf %p, n %u, flags 0x%x", - getpid (), fd, fd, func_str, sid, sid, buf, n, flags); - - size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL); - if (size != VPPCOM_OK) - { - errno = -size; - size = -1; - } - } - else - { - func_str = "libc_send"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "buf %p, n %u, flags 0x%x", - getpid (), fd, fd, func_str, buf, n, flags); - - size = libc_send (fd, buf, n, flags); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -sendfile (int out_fd, int in_fd, off_t * offset, size_t len) -{ - ssize_t size = 0; - const char *func_str; - u32 sid = vcom_sid_from_fd (out_fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - int rv; - ssize_t results = 0; - size_t n_bytes_left = len; - size_t bytes_to_read; - int nbytes; - int errno_val; - u8 eagain = 0; - u32 flags, flags_len = sizeof (flags); - - func_str = "vppcom_session_attr[GET_FLAGS]"; - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, - &flags_len); - if (PREDICT_FALSE (rv != VPPCOM_OK)) - { - clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): " - "sid %u (0x%x), returned %d (%s)!", getpid (), - out_fd, out_fd, func_str, sid, sid, rv, - vppcom_retval_str (rv)); - - vec_reset_length (vcom->io_buffer); - errno = -rv; - size = -1; - goto done; - } - - if (offset) - { - off_t off = lseek (in_fd, *offset, SEEK_SET); - if (PREDICT_FALSE (off == -1)) - { - func_str = "lseek"; - errno_val = errno; - clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): " - "SEEK_SET failed: in_fd %d, offset %p, " - "*offset %ld, rv %ld, errno %d", getpid (), - out_fd, out_fd, in_fd, offset, *offset, off, - errno_val); - errno = errno_val; - size = -1; - goto done; - } - - ASSERT (off == *offset); - } - - do - { - func_str = "vppcom_session_attr[GET_NWRITE]"; - size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0); - if (size < 0) - { - clib_warning - ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), " - "returned %d (%s)!", getpid (), out_fd, out_fd, func_str, - sid, sid, size, vppcom_retval_str (size)); - vec_reset_length (vcom->io_buffer); - errno = -size; - size = -1; - goto done; - } - - bytes_to_read = size; - if (VCOM_DEBUG > 2) - clib_warning - ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), " - "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (), - out_fd, out_fd, func_str, sid, sid, results, n_bytes_left, - bytes_to_read); - - if (bytes_to_read == 0) - { - if (flags & O_NONBLOCK) - { - if (!results) - { - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): " - "EAGAIN", - getpid (), out_fd, out_fd, sid, sid); - eagain = 1; - } - goto update_offset; - } - else - continue; - } - bytes_to_read = clib_min (n_bytes_left, bytes_to_read); - vec_validate (vcom->io_buffer, bytes_to_read); - nbytes = libc_read (in_fd, vcom->io_buffer, bytes_to_read); - if (nbytes < 0) - { - func_str = "libc_read"; - errno_val = errno; - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), " - "io_buffer %p, bytes_to_read %lu, rv %d, " - "errno %d", getpid (), out_fd, out_fd, func_str, - in_fd, vcom->io_buffer, bytes_to_read, nbytes, - errno_val); - errno = errno_val; - - if (results == 0) - { - vec_reset_length (vcom->io_buffer); - size = -1; - goto done; - } - goto update_offset; - } - func_str = "vppcom_session_write"; - if (VCOM_DEBUG > 2) - clib_warning - ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " - "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (), - out_fd, out_fd, func_str, sid, sid, vcom->io_buffer, nbytes, - results, n_bytes_left); - - size = vppcom_session_write (sid, vcom->io_buffer, nbytes); - if (size < 0) - { - if (size == VPPCOM_EAGAIN) - { - if (flags & O_NONBLOCK) - { - if (!results) - { - if (VCOM_DEBUG > 2) - clib_warning - ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): " - "EAGAIN", getpid (), out_fd, out_fd, sid, sid); - eagain = 1; - } - goto update_offset; - } - else - continue; - } - else - { - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():" - "sid %u, io_buffer %p, nbytes %u " - "returned %d (%s)", - getpid (), out_fd, out_fd, func_str, - sid, vcom->io_buffer, nbytes, - size, vppcom_retval_str (size)); - } - if (results == 0) - { - vec_reset_length (vcom->io_buffer); - errno = -size; - size = -1; - goto done; - } - goto update_offset; - } - - results += nbytes; - ASSERT (n_bytes_left >= nbytes); - n_bytes_left = n_bytes_left - nbytes; - } - while (n_bytes_left > 0); - - update_offset: - vec_reset_length (vcom->io_buffer); - if (offset) - { - off_t off = lseek (in_fd, *offset, SEEK_SET); - if (PREDICT_FALSE (off == -1)) - { - func_str = "lseek"; - errno_val = errno; - clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: " - "in_fd %d, offset %p, *offset %ld, " - "rv %ld, errno %d", getpid (), in_fd, - offset, *offset, off, errno_val); - errno = errno_val; - size = -1; - goto done; - } - - ASSERT (off == *offset); - *offset += results + 1; - } - if (eagain) - { - errno = EAGAIN; - size = -1; - } - else - size = results; - } - else - { - func_str = "libc_send"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "in_fd %d, offset %p, len %u", - getpid (), out_fd, out_fd, func_str, - in_fd, offset, len); - - size = libc_sendfile (out_fd, in_fd, offset, len); - } - -done: - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), out_fd, out_fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), out_fd, out_fd, size, size); - } - return size; -} - -ssize_t -sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len) -{ - return sendfile (out_fd, in_fd, offset, len); -} - -ssize_t -recv (int fd, void *buf, size_t n, int flags) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_recvfrom"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (), - fd, fd, func_str, sid, sid, buf, n, flags); - - size = vppcom_session_recvfrom (sid, buf, n, flags, NULL); - if (size < 0) - { - errno = -size; - size = -1; - } - } - else - { - func_str = "libc_recv"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "buf %p, n %u, flags 0x%x", getpid (), - fd, fd, func_str, buf, n, flags); - - size = libc_recv (fd, buf, n, flags); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -sendto (int fd, const void *buf, size_t n, int flags, - __CONST_SOCKADDR_ARG addr, socklen_t addr_len) -{ - ssize_t size; - const char *func_str = __func__; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - vppcom_endpt_t *ep = 0; - vppcom_endpt_t _ep; - - if (addr) - { - ep = &_ep; - switch (addr->sa_family) - { - case AF_INET: - ep->is_ip4 = VPPCOM_IS_IP4; - ep->ip = - (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr; - ep->port = - (uint16_t) ((const struct sockaddr_in *) addr)->sin_port; - break; - - case AF_INET6: - ep->is_ip4 = VPPCOM_IS_IP6; - ep->ip = - (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; - ep->port = - (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port; - break; - - default: - errno = EAFNOSUPPORT; - size = -1; - goto done; - } - } - - func_str = "vppcom_session_sendto"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p", - getpid (), fd, fd, func_str, sid, sid, buf, n, - flags, ep); - - size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep); - if (size < 0) - { - errno = -size; - size = -1; - } - } - else - { - func_str = "libc_sendto"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "buf %p, n %u, flags 0x%x, addr %p, addr_len %d", - getpid (), fd, fd, func_str, buf, n, flags, - addr, addr_len); - - size = libc_sendto (fd, buf, n, flags, addr, addr_len); - } - -done: - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -recvfrom (int fd, void *__restrict buf, size_t n, int flags, - __SOCKADDR_ARG addr, socklen_t * __restrict addr_len) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - vppcom_endpt_t ep; - u8 src_addr[sizeof (struct sockaddr_in6)]; - - func_str = "vppcom_session_recvfrom"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p", - getpid (), fd, fd, func_str, sid, sid, buf, n, - flags, &ep); - if (addr) - { - ep.ip = src_addr; - size = vppcom_session_recvfrom (sid, buf, n, flags, &ep); - - if (size > 0) - size = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep); - } - else - size = vppcom_session_recvfrom (sid, buf, n, flags, NULL); - - if (size < 0) - { - errno = -size; - size = -1; - } - } - else - { - func_str = "libc_recvfrom"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "buf %p, n %u, flags 0x%x, addr %p, addr_len %d", - getpid (), fd, fd, func_str, buf, n, flags, - addr, addr_len); - - size = libc_recvfrom (fd, buf, n, flags, addr, addr_len); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -ssize_t -sendmsg (int fd, const struct msghdr * message, int flags) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = __func__; - - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - size = -1; - } - else - { - func_str = "libc_sendmsg"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "message %p, flags 0x%x", - getpid (), fd, fd, func_str, message, flags); - - size = libc_sendmsg (fd, message, flags); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -#ifdef USE_GNU -int -sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - size = -1; - } - else - { - func_str = "libc_sendmmsg"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "vmessages %p, vlen %u, flags 0x%x", - getpid (), fd, fd, func_str, vmessages, vlen, flags); - - size = libc_sendmmsg (fd, vmessages, vlen, flags); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} -#endif - -ssize_t -recvmsg (int fd, struct msghdr * message, int flags) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = __func__; - - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - size = -1; - } - else - { - func_str = "libc_recvmsg"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "message %p, flags 0x%x", - getpid (), fd, fd, func_str, message, flags); - - size = libc_recvmsg (fd, message, flags); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} - -#ifdef USE_GNU -int -recvmmsg (int fd, struct mmsghdr *vmessages, - unsigned int vlen, int flags, struct timespec *tmo) -{ - ssize_t size; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - size = -1; - } - else - { - func_str = "libc_recvmmsg"; - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "vmessages %p, vlen %u, flags 0x%x, tmo %p", - getpid (), fd, fd, func_str, vmessages, vlen, - flags, tmo); - - size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo); - } - - if (VCOM_DEBUG > 2) - { - if (size < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, size, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, size, size); - } - return size; -} -#endif - -int -getsockopt (int fd, int level, int optname, - void *__restrict optval, socklen_t * __restrict optlen) -{ - int rv; - const char *func_str = __func__; - u32 sid = vcom_sid_from_fd (fd); - u32 buflen = optlen ? (u32) * optlen : 0; - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - rv = -EOPNOTSUPP; - - switch (level) - { - case SOL_TCP: - switch (optname) - { - case TCP_NODELAY: - func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY, - optval, optlen); - break; - case TCP_MAXSEG: - func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS, - optval, optlen); - break; - case TCP_KEEPIDLE: - func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE, - optval, optlen); - break; - case TCP_KEEPINTVL: - func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), SOL_TCP", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL, - optval, optlen); - break; - case TCP_INFO: - if (optval && optlen && (*optlen == sizeof (struct tcp_info))) - { - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), " - "SOL_TCP, TCP_INFO, optval %p, " - "optlen %d: #LDP-NOP#", - getpid (), fd, fd, sid, sid, - optval, *optlen); - memset (optval, 0, *optlen); - rv = VPPCOM_OK; - } - else - rv = -EFAULT; - break; - default: - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " - "sid %u (0x%x), SOL_TCP, " - "optname %d unsupported!", - getpid (), fd, fd, func_str, sid, sid, optname); - break; - } - break; - case SOL_IPV6: - switch (optname) - { - case IPV6_V6ONLY: - func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY, - optval, optlen); - break; - default: - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " - "sid %u (0x%x), SOL_IPV6, " - "optname %d unsupported!", - getpid (), fd, fd, func_str, sid, sid, optname); - break; - } - break; - case SOL_SOCKET: - switch (optname) - { - case SO_ACCEPTCONN: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN, - optval, optlen); - break; - case SO_KEEPALIVE: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE, - optval, optlen); - break; - case SO_PROTOCOL: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL, - optval, optlen); - *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM; - break; - case SO_SNDBUF: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), optlen %d", - getpid (), fd, fd, func_str, sid, sid, buflen); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN, - optval, optlen); - break; - case SO_RCVBUF: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), optlen %d", - getpid (), fd, fd, func_str, sid, sid, buflen); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN, - optval, optlen); - break; - case SO_REUSEADDR: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR, - optval, optlen); - break; - case SO_BROADCAST: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST, - optval, optlen); - break; - case SO_ERROR: - func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR, - optval, optlen); - break; - default: - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " - "sid %u (0x%x), SOL_SOCKET, " - "optname %d unsupported!", - getpid (), fd, fd, func_str, sid, sid, optname); - break; - } - break; - default: - break; - } - - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_getsockopt"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, " - "optname %d, optval %p, optlen %d", - getpid (), fd, fd, func_str, level, optname, - optval, optlen); - - rv = libc_getsockopt (fd, level, optname, optval, optlen); - } - - if (VCOM_DEBUG > 1) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -int -setsockopt (int fd, int level, int optname, - const void *optval, socklen_t optlen) -{ - int rv; - const char *func_str = __func__; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - rv = -EOPNOTSUPP; - - switch (level) - { - case SOL_TCP: - switch (optname) - { - case TCP_NODELAY: - func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY, - (void *) optval, &optlen); - break; - case TCP_MAXSEG: - func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS, - (void *) optval, &optlen); - break; - case TCP_KEEPIDLE: - func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, - (void *) optval, &optlen); - break; - case TCP_KEEPINTVL: - func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x), SOL_TCP", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, - (void *) optval, &optlen); - break; - default: - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " - "sid %u (0x%x), SOL_TCP, " - "optname %d unsupported!", - getpid (), fd, fd, func_str, sid, sid, optname); - break; - } - break; - case SOL_IPV6: - switch (optname) - { - case IPV6_V6ONLY: - func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY, - (void *) optval, &optlen); - break; - default: - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " - "sid %u (0x%x), SOL_IPV6, " - "optname %d unsupported!", - getpid (), fd, fd, func_str, sid, sid, optname); - break; - } - break; - case SOL_SOCKET: - switch (optname) - { - case SO_KEEPALIVE: - func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE, - (void *) optval, &optlen); - break; - case SO_REUSEADDR: - func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR, - (void *) optval, &optlen); - break; - case SO_BROADCAST: - func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]"; - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " - "sid %u (0x%x)", - getpid (), fd, fd, func_str, sid, sid); - rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST, - (void *) optval, &optlen); - break; - default: - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " - "sid %u (0x%x), SOL_SOCKET, " - "optname %d unsupported!", - getpid (), fd, fd, func_str, sid, sid, optname); - break; - } - break; - default: - break; - } - - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_setsockopt"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, " - "optname %d, optval %p, optlen %d", - getpid (), fd, fd, func_str, level, optname, - optval, optlen); - - rv = libc_setsockopt (fd, level, optname, optval, optlen); - } - - if (VCOM_DEBUG > 1) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -int -listen (int fd, int n) -{ - int rv; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_session_listen"; - - if (VCOM_DEBUG > 0) - clib_warning - ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d", - getpid (), fd, fd, func_str, sid, sid, n); - - rv = vppcom_session_listen (sid, n); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - func_str = "libc_listen"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d", - getpid (), fd, fd, func_str, n); - - rv = libc_listen (fd, n); - } - - if (VCOM_DEBUG > 0) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -static inline int -vcom_accept4 (int listen_fd, __SOCKADDR_ARG addr, - socklen_t * __restrict addr_len, int flags) -{ - int rv; - const char *func_str; - u32 listen_sid = vcom_sid_from_fd (listen_fd); - int accept_sid; - - if ((errno = -vcom_init ())) - return -1; - - if (listen_sid != INVALID_SESSION_ID) - { - vppcom_endpt_t ep; - u8 src_addr[sizeof (struct sockaddr_in6)]; - memset (&ep, 0, sizeof (ep)); - ep.ip = src_addr; - - func_str = "vppcom_session_accept"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " - "listen sid %u (0x%x), ep %p, flags 0x%x", - getpid (), listen_fd, listen_fd, func_str, - listen_sid, listen_sid, ep, flags); - - accept_sid = vppcom_session_accept (listen_sid, &ep, flags); - if (accept_sid < 0) - { - errno = -accept_sid; - rv = -1; - } - else - { - rv = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep); - if (rv != VPPCOM_OK) - { - (void) vppcom_session_close ((u32) accept_sid); - errno = -rv; - rv = -1; - } - else - { - func_str = "vcom_fd_from_sid"; - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " - "accept sid %u (0x%x), ep %p, flags 0x%x", - getpid (), listen_fd, listen_fd, - func_str, accept_sid, accept_sid, ep, flags); - rv = vcom_fd_from_sid ((u32) accept_sid); - if (rv < 0) - { - (void) vppcom_session_close ((u32) accept_sid); - errno = -rv; - rv = -1; - } - } - } - } - else - { - func_str = "libc_accept4"; - - if (VCOM_DEBUG > 0) - clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " - "addr %p, addr_len %p, flags 0x%x", - getpid (), listen_fd, listen_fd, func_str, - addr, addr_len, flags); - - rv = libc_accept4 (listen_fd, addr, addr_len, flags); - } - - if (VCOM_DEBUG > 0) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), listen_fd, - listen_fd, func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)", - getpid (), listen_fd, listen_fd, rv, rv); - } - return rv; -} - -int -accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len, - int flags) -{ - return vcom_accept4 (fd, addr, addr_len, flags); -} - -int -accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len) -{ - return vcom_accept4 (fd, addr, addr_len, 0); -} - -int -shutdown (int fd, int how) -{ - int rv; - const char *func_str; - u32 sid = vcom_sid_from_fd (fd); - - if ((errno = -vcom_init ())) - return -1; - - if (sid != INVALID_SESSION_ID) - { - func_str = __func__; - - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - rv = -1; - } - else - { - func_str = "libc_shutdown"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d", - getpid (), fd, fd, func_str, how); - - rv = libc_shutdown (fd, how); - } - - if (VCOM_DEBUG > 1) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -int -epoll_create1 (int flags) -{ - const char *func_str; - int rv; - - if ((errno = -vcom_init ())) - return -1; - - func_str = "vppcom_epoll_create"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: calling %s()", getpid (), func_str); - - rv = vppcom_epoll_create (); - - if (PREDICT_FALSE (rv < 0)) - { - errno = -rv; - rv = -1; - } - else - rv = vcom_fd_from_sid ((u32) rv); - - if (VCOM_DEBUG > 1) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: %s() failed! " - "rv %d, errno = %d", - getpid (), func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv); - } - return rv; -} - -int -epoll_create (int size) -{ - return epoll_create1 (0); -} - -int -epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) -{ - int rv; - const char *func_str; - u32 vep_idx = vcom_sid_from_fd (epfd); - - if ((errno = -vcom_init ())) - return -1; - - if (vep_idx != INVALID_SESSION_ID) - { - u32 sid = vcom_sid_from_fd (fd); - - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_epoll_create"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p", - getpid (), epfd, epfd, func_str, vep_idx, vep_idx, - sid, sid, event); - - rv = vppcom_epoll_ctl (vep_idx, op, sid, event); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } - } - else - { - int epfd; - u32 size = sizeof (epfd); - - func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; - epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, - 0, 0); - if (!epfd) - { - func_str = "libc_epoll_create1"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: calling %s(): EPOLL_CLOEXEC", - getpid (), func_str); - - epfd = libc_epoll_create1 (EPOLL_CLOEXEC); - if (epfd < 0) - { - rv = epfd; - goto done; - } - - func_str = "vppcom_session_attr[SET_LIBC_EPFD]"; - rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD, - &epfd, &size); - if (rv < 0) - { - errno = -rv; - rv = -1; - goto done; - } - } - else if (PREDICT_FALSE (epfd < 0)) - { - errno = -epfd; - rv = -1; - goto done; - } - - rv = libc_epoll_ctl (epfd, op, fd, event); - } - } - else - { - func_str = "libc_epoll_ctl"; - - if (VCOM_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "op %d, fd %d (0x%x), event %p", - getpid (), epfd, epfd, func_str, op, fd, fd, event); - - rv = libc_epoll_ctl (epfd, op, fd, event); - } - -done: - if (VCOM_DEBUG > 1) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), fd, fd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", - getpid (), fd, fd, rv, rv); - } - return rv; -} - -static inline int -vcom_epoll_pwait (int epfd, struct epoll_event *events, - int maxevents, int timeout, const sigset_t * sigmask) -{ - const char *func_str; - int rv = 0; - double time_to_wait = (double) 0; - double time_out, now = 0; - u32 vep_idx = vcom_sid_from_fd (epfd); - int libc_epfd; - - if ((errno = -vcom_init ())) - return -1; - - if (PREDICT_FALSE (!events || (timeout < -1))) - { - errno = EFAULT; - return -1; - } - - if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID)) - { - clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!", - getpid (), epfd, epfd, vep_idx, vep_idx); - errno = EBADFD; - return -1; - } - - time_to_wait = ((timeout >= 0) ? (double) timeout / (double) 1000 : 0); - time_out = clib_time_now (&vcom->clib_time) + time_to_wait; - - func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; - libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); - if (PREDICT_FALSE (libc_epfd < 0)) - { - errno = -libc_epfd; - rv = -1; - goto done; - } - - if (VCOM_DEBUG > 2) - clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), " - "libc_epfd %d (0x%x), events %p, maxevents %d, " - "timeout %d, sigmask %p", getpid (), epfd, epfd, - vep_idx, vep_idx, libc_epfd, libc_epfd, events, - maxevents, timeout, sigmask); - do - { - if (!vcom->epoll_wait_vcl) - { - func_str = "vppcom_epoll_wait"; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "vep_idx %d (0x%x), events %p, maxevents %d", - getpid (), epfd, epfd, func_str, - vep_idx, vep_idx, events, maxevents); - - rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0); - if (rv > 0) - { - vcom->epoll_wait_vcl = 1; - goto done; - } - else if (rv < 0) - { - errno = -rv; - rv = -1; - goto done; - } - } - else - vcom->epoll_wait_vcl = 0; - - if (libc_epfd > 0) - { - func_str = "libc_epoll_pwait"; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "libc_epfd %d (0x%x), events %p, " - "maxevents %d, sigmask %p", - getpid (), epfd, epfd, func_str, - libc_epfd, libc_epfd, events, maxevents, sigmask); - - rv = libc_epoll_pwait (libc_epfd, events, maxevents, 1, sigmask); - if (rv != 0) - goto done; - } - - if (timeout != -1) - now = clib_time_now (&vcom->clib_time); - } - while (now < time_out); - -done: - if (VCOM_DEBUG > 3) - { - if (libc_epfd > 0) - epfd = libc_epfd; - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! " - "rv %d, errno = %d", getpid (), epfd, epfd, - func_str, rv, errno_val); - errno = errno_val; - } - else - clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)", - getpid (), epfd, epfd, rv, rv); - } - return rv; -} - -int -epoll_pwait (int epfd, struct epoll_event *events, - int maxevents, int timeout, const sigset_t * sigmask) -{ - return vcom_epoll_pwait (epfd, events, maxevents, timeout, sigmask); -} - -int -epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout) -{ - return vcom_epoll_pwait (epfd, events, maxevents, timeout, NULL); -} - -int -poll (struct pollfd *fds, nfds_t nfds, int timeout) -{ - const char *func_str = __func__; - int rv, i, n_libc_fds, n_revents; - u32 sid; - vcl_poll_t *vp; - double wait_for_time; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: fds %p, nfds %d, timeout %d", - getpid (), fds, nfds, timeout); - - if (timeout >= 0) - wait_for_time = (f64) timeout / 1000; - else - wait_for_time = -1; - - n_libc_fds = 0; - for (i = 0; i < nfds; i++) - { - if (fds[i].fd >= 0) - { - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), .events = 0x%x, " - ".revents = 0x%x", getpid (), i, fds[i].fd, - fds[i].fd, fds[i].events, fds[i].revents); - - sid = vcom_sid_from_fd (fds[i].fd); - if (sid != INVALID_SESSION_ID) - { - fds[i].fd = -fds[i].fd; - vec_add2 (vcom->vcl_poll, vp, 1); - vp->fds_ndx = i; - vp->sid = sid; - vp->events = fds[i].events; -#ifdef __USE_XOPEN2K - if (fds[i].events & POLLRDNORM) - vp->events |= POLLIN; - if (fds[i].events & POLLWRNORM) - vp->events |= POLLOUT; -#endif - vp->revents = &fds[i].revents; - } - else - n_libc_fds++; - } - } - - n_revents = 0; - do - { - if (vec_len (vcom->vcl_poll)) - { - func_str = "vppcom_poll"; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: calling %s(): " - "vcl_poll %p, n_sids %u (0x%x): " - "n_libc_fds %u", - getpid (), func_str, vcom->vcl_poll, - vec_len (vcom->vcl_poll), vec_len (vcom->vcl_poll), - n_libc_fds); - - rv = vppcom_poll (vcom->vcl_poll, vec_len (vcom->vcl_poll), 0); - if (rv < 0) - { - errno = -rv; - rv = -1; - goto done; - } - else - n_revents += rv; - } - - if (n_libc_fds) - { - func_str = "libc_poll"; - - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u", - getpid (), fds, nfds, vec_len (vcom->vcl_poll)); - - rv = libc_poll (fds, nfds, 0); - if (rv < 0) - goto done; - else - n_revents += rv; - } - - if (n_revents) - { - rv = n_revents; - goto done; - } - } - while ((wait_for_time == -1) || - (clib_time_now (&vcom->clib_time) < wait_for_time)); - rv = 0; - -done: - vec_foreach (vp, vcom->vcl_poll) - { - fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd; -#ifdef __USE_XOPEN2K - if ((fds[vp->fds_ndx].revents & POLLIN) && - (fds[vp->fds_ndx].events & POLLRDNORM)) - fds[vp->fds_ndx].revents |= POLLRDNORM; - if ((fds[vp->fds_ndx].revents & POLLOUT) && - (fds[vp->fds_ndx].events & POLLWRNORM)) - fds[vp->fds_ndx].revents |= POLLWRNORM; -#endif - } - vec_reset_length (vcom->vcl_poll); - - if (VCOM_DEBUG > 3) - { - if (rv < 0) - { - int errno_val = errno; - perror (func_str); - clib_warning ("LDP<%d>: ERROR: %s() failed! " - "rv %d, errno = %d", getpid (), - func_str, rv, errno_val); - errno = errno_val; - } - else - { - clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, " - "n_libc_fds %d", getpid (), rv, rv, - vec_len (vcom->vcl_poll), n_libc_fds); - - for (i = 0; i < nfds; i++) - { - if (fds[i].fd >= 0) - { - if (VCOM_DEBUG > 3) - clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), " - ".events = 0x%x, .revents = 0x%x", - getpid (), i, fds[i].fd, fds[i].fd, - fds[i].events, fds[i].revents); - } - } - } - } - - return rv; -} - -#ifdef USE_GNU -int -ppoll (struct pollfd *fds, nfds_t nfds, - const struct timespec *timeout, const sigset_t * sigmask) -{ - if ((errno = -vcom_init ())) - return -1; - - clib_warning ("LDP<%d>: LDP-TBD", getpid ()); - errno = ENOSYS; - - - return -1; -} -#endif - -void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void); - -void DESTRUCTOR_ATTRIBUTE vcom_destructor (void); - -/* - * This function is called when the library is loaded - */ -void -vcom_constructor (void) -{ - swrap_constructor (); - if (vcom_init () != 0) - fprintf (stderr, "\nLDP<%d>: ERROR: vcom_constructor: failed!\n", - getpid ()); - else - clib_warning ("LDP<%d>: VCOM constructor: done!\n", getpid ()); -} - -/* - * This function is called when the library is unloaded - */ -void -vcom_destructor (void) -{ - swrap_destructor (); - if (vcom->init) - { - vppcom_app_destroy (); - vcom->init = 0; - } - - /* Don't use clib_warning() here because that calls writev() - * which will call vcom_init(). - */ - printf ("%s:%d: LDP<%d>: VCOM destructor: done!\n", - __func__, __LINE__, getpid ()); -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcom.h b/src/vcl/vcom.h deleted file mode 100644 index 0dd86c1c000..00000000000 --- a/src/vcl/vcom.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017 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. - */ - -#ifndef included_vcom_h -#define included_vcom_h - -#if (CLIB_DEBUG > 0) -/* Set VCOM_DEBUG 2 for connection debug, 3 for read/write debug output */ -#define VCOM_DEBUG_INIT 1 -#else -#define VCOM_DEBUG_INIT 0 -#endif - -#include -#include -#include - -#define VCOM_ENV_DEBUG "VCOM_DEBUG" -#define VCOM_ENV_APP_NAME "VCOM_APP_NAME" -#define VCOM_ENV_SID_BIT "VCOM_SID_BIT" - -#define VCOM_SID_BIT_MIN 9 -#define VCOM_SID_BIT_MAX 30 - -#define VCOM_APP_NAME_MAX 256 - -#endif /* included_vcom_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcom_glibc_socket.h b/src/vcl/vcom_glibc_socket.h deleted file mode 100644 index bf18473de85..00000000000 --- a/src/vcl/vcom_glibc_socket.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2017 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. - */ - -#ifndef included_vcom_glibc_socket_h -#define included_vcom_glibc_socket_h - -#include -#include -#include -#include -#include - -#include - -#include -#include - -/* - * - * Generic glibc fd api - * - */ -/* - * glibc APIs from - */ - -/* Close the file descriptor FD. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int close (int __fd); - -/* Read NBYTES into BUF from FD. Return the - number read, -1 for errors or 0 for EOF. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t __wur read (int __fd, void *__buf, size_t __nbytes); - -/* Write N bytes of BUF to FD. Return the number written, or -1. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t __wur write (int __fd, const void *__buf, size_t __n); - - -/* - * glibc APIs from - */ - -/* Do the file control operation described by CMD on FD. - The remaining arguments are interpreted depending on CMD. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int fcntl (int __fd, int __cmd, ...); - - -/* - * glibc APIs from - */ - -/* Check the first NFDS descriptors each in READFDS (if not NULL) for read - readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS - (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out - after waiting the interval specified therein. Returns the number of ready - descriptors, or -1 for errors. - - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __timeout); - -#ifdef __USE_XOPEN2K -/* Same as above only that the TIMEOUT value is given with higher - resolution and a sigmask which is been set temporarily. This version - should be used. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -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 - - -/* - * - * Socket specific glibc api - * - */ - -/* - * glibc APIs from - */ - -/* Create a new socket of type TYPE in domain DOMAIN, using - protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. - Returns a file descriptor for the new socket, or -1 for errors. */ -extern int __THROW socket (int __domain, int __type, int __protocol); - -/* Create two new sockets, of type TYPE in domain DOMAIN and using - protocol PROTOCOL, which are connected to each other, and put file - descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, - one will be chosen automatically. Returns 0 on success, -1 for errors. */ -extern int __THROW -socketpair (int __domain, int __type, int __protocol, int __fds[2]); - -/* Give the socket FD the local address ADDR (which is LEN bytes long). */ -extern int __THROW -bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); - -/* Put the local address of FD into *ADDR and its length in *LEN. */ -extern int __THROW -getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len); - -/* Open a connection on socket FD to peer at ADDR (which LEN bytes long). - For connectionless socket types, just set the default address to send to - and the only address from which to accept transmissions. - Return 0 on success, -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); - -/* Put the address of the peer connected to socket FD into *ADDR - (which is *LEN bytes long), and its actual length into *LEN. */ -extern int __THROW -getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len); - -/* Send N bytes of BUF to socket FD. Returns the number sent or -1. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); - -extern ssize_t sendfile (int __out_fd, int __in_fd, off_t * __offset, - size_t __len); - -/* Read N bytes into BUF from socket FD. - Returns the number read or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); - -/* Send N bytes of BUF on socket FD to peer at address ADDR (which is - ADDR_LEN bytes long). Returns the number sent, or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t -sendto (int __fd, const void *__buf, size_t __n, - int __flags, __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len); - -/* Read N bytes into BUF through socket FD. - If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of - the sender, and store the actual size of the address in *ADDR_LEN. - Returns the number of bytes read or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t -recvfrom (int __fd, void *__restrict __buf, - size_t __n, int __flags, - __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len); - -/* Send a message described MESSAGE on socket FD. - Returns the number of bytes sent, or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t -sendmsg (int __fd, const struct msghdr *__message, int __flags); - -#ifdef __USE_GNU -/* Send a VLEN messages as described by VMESSAGES to socket FD. - Returns the number of datagrams successfully written or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags); -#endif - -/* Receive a message as described by MESSAGE from socket FD. - Returns the number of bytes read or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); - -#ifdef __USE_GNU -/* Receive up to VLEN messages as described by VMESSAGES from socket FD. - Returns the number of messages received or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, struct timespec *__tmo); -#endif - - -/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL - into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's - actual length. Returns 0 on success, -1 for errors. */ -extern int __THROW -getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, socklen_t * __restrict __optlen); - -/* Set socket FD's option OPTNAME at protocol level LEVEL - to *OPTVAL (which is OPTLEN bytes long). - Returns 0 on success, -1 for errors. */ -extern int __THROW -setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen); - -/* Prepare to accept connections on socket FD. - N connection requests will be queued before further requests are refused. - Returns 0 on success, -1 for errors. */ -extern int __THROW listen (int __fd, int __n); - -/* Await a connection on socket FD. - When a connection arrives, open a new socket to communicate with it, - set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting - peer and *ADDR_LEN to the address's actual length, and return the - new socket's descriptor, or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len); - -/* Similar to 'accept' but takes an additional parameter to specify flags. - - This function is a cancellation point and therefore not marked with - __THROW. */ - /* TBD: implemented later */ -extern int -accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags); - -/* Shut down all or part of the connection open on socket FD. - HOW determines what to shut down: - SHUT_RD = No more receptions; - SHUT_WR = No more transmissions; - SHUT_RDWR = No more receptions or transmissions. - Returns 0 on success, -1 for errors. */ -extern int __THROW shutdown (int __fd, int __how); - - -/* - * glibc APIs from - */ - -/* Creates an epoll instance. Returns an fd for the new instance. - The "size" parameter is a hint specifying the number of file - descriptors to be associated with the new instance. The fd - returned by epoll_create() should be closed with close(). */ -extern int __THROW epoll_create (int __size); - -/* Same as epoll_create but with an FLAGS parameter. The unused SIZE - parameter has been dropped. */ -extern int __THROW epoll_create1 (int __flags); - -/* Manipulate an epoll instance "epfd". Returns 0 in case of success, - -1 in case of error ( the "errno" variable will contain the - specific error code ) The "op" parameter is one of the EPOLL_CTL_* - constants defined above. The "fd" parameter is the target of the - operation. The "event" parameter describes which events the caller - is interested in and any associated user data. */ -extern int __THROW -epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event); - -#define EP_INT_MAX ((int)(~0U>>1)) -#define EP_MAX_EVENTS (EP_INT_MAX / sizeof(struct epoll_event)) - -/* Wait for events on an epoll instance "epfd". Returns the number of - triggered events returned in "events" buffer. Or -1 in case of - error with the "errno" variable set to the specific error code. The - "events" parameter is a buffer that will contain triggered - events. The "maxevents" is the maximum number of events to be - returned ( usually size of "events" ). The "timeout" parameter - specifies the maximum wait time in milliseconds (-1 == infinite). - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -epoll_wait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout); - -/* Same as epoll_wait, but the thread's signal mask is temporarily - and atomically replaced with the one provided as parameter. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int -epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, const __sigset_t * __ss); - -/* Poll the file descriptors described by the NFDS structures starting at - FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for - an event to occur; if TIMEOUT is -1, block until an event occurs. - Returns the number of file descriptors with events, zero if timed out, - or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); - -#ifdef __USE_GNU -/* Like poll, but before waiting the threads signal mask is replaced - with that specified in the fourth parameter. For better usability, - the timeout value is specified using a TIMESPEC object. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss); -#endif - - -#endif /* included_vcom_glibc_socket_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcom_socket_wrapper.c b/src/vcl/vcom_socket_wrapper.c deleted file mode 100644 index de633d1cc7b..00000000000 --- a/src/vcl/vcom_socket_wrapper.c +++ /dev/null @@ -1,909 +0,0 @@ -/* - * 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: - */ diff --git a/src/vcl/vcom_socket_wrapper.h b/src/vcl/vcom_socket_wrapper.h deleted file mode 100644 index ce03ebe83da..00000000000 --- a/src/vcl/vcom_socket_wrapper.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2017 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. -*/ - -#ifndef included_vcom_socket_wrapper_h -#define included_vcom_socket_wrapper_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* GCC have printf type attribute check. */ -#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT -#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) -#else -#define PRINTF_ATTRIBUTE(a,b) -#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */ - -#define HAVE_CONSTRUCTOR_ATTRIBUTE -#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE -#define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor)) -#else -#define CONSTRUCTOR_ATTRIBUTE -#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ - -#define HAVE_DESTRUCTOR_ATTRIBUTE -#ifdef HAVE_DESTRUCTOR_ATTRIBUTE -#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) -#else -#define DESTRUCTOR_ATTRIBUTE -#endif - -#define HAVE_ADDRESS_SANITIZER_ATTRIBUTE -#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE -#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address)) -#else -#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE -#endif - -/* - * 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); - -int libc_accept (int sockfd, struct sockaddr *addr, socklen_t * addrlen); - -int libc_bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen); - -int libc_close (int fd); - -int libc_connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen); - -#if 0 -/* TBD: dup and dup2 to be implemented later */ -int libc_dup (int fd); - -int libc_dup2 (int oldfd, int newfd); -#endif - -#ifdef HAVE_EVENTFD -int libc_eventfd (int count, int flags); -#endif - -DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int -libc_vfcntl (int fd, int cmd, va_list ap); - -DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int -libc_vioctl (int fd, int cmd, va_list ap); - -int libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen); - -int libc_getsockname (int sockfd, struct sockaddr *addr, socklen_t * addrlen); - -int -libc_getsockopt (int sockfd, - int level, int optname, void *optval, socklen_t * optlen); - -int libc_listen (int sockfd, int backlog); - -int libc_read (int fd, void *buf, size_t count); - -ssize_t libc_readv (int fd, const struct iovec *iov, int iovcnt); - -int libc_recv (int sockfd, void *buf, size_t len, int flags); - -int -libc_recvfrom (int sockfd, - void *buf, - size_t len, - int flags, struct sockaddr *src_addr, socklen_t * addrlen); - -int libc_recvmsg (int sockfd, struct msghdr *msg, int flags); - -int libc_send (int sockfd, const void *buf, size_t len, int flags); - -ssize_t libc_sendfile (int out_fd, int in_fd, off_t * offset, size_t len); - -int libc_sendmsg (int sockfd, const struct msghdr *msg, int flags); - -int -libc_sendto (int sockfd, - const void *buf, - size_t len, - int flags, const struct sockaddr *dst_addr, socklen_t addrlen); - -int -libc_setsockopt (int sockfd, - int level, int optname, const void *optval, - socklen_t optlen); - -int libc_socket (int domain, int type, int protocol); - -int libc_socketpair (int domain, int type, int protocol, int sv[2]); - -ssize_t libc_write (int fd, const void *buf, size_t count); - -ssize_t libc_writev (int fd, const struct iovec *iov, int iovcnt); - -int libc_shutdown (int fd, int how); - -int -libc_select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __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); -#endif - -int libc_epoll_create (int __size); - -int libc_epoll_create1 (int __flags); - -int libc_epoll_ctl (int __epfd, int __op, int __fd, - struct epoll_event *__event); - -int libc_epoll_wait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout); - -int libc_epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, - const __sigset_t * __ss); - -int libc_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); - -#ifdef __USE_GNU -int libc_ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss); -#endif - -void swrap_constructor (void); - -void swrap_destructor (void); - -#endif /* included_vcom_socket_wrapper_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ -- cgit 1.2.3-korg