text: /*
   * Copyright (c) 2011-2018 Mellanox Technologies Ltd.
   * 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 Mellanox Technologies Ltd 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 ``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 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.
   */
  
  #ifndef VMA_REDIRECT_H
  #define VMA_REDIRECT_H
  
  #include <fcntl.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <signal.h>
  #include <sys/poll.h>
  #include <sched.h>
  #include <sys/ioctl.h>
  
  #ifdef __FreeBSD__
  #include <netinet/in.h>
  #include <stdio.h>
  #else
  #include <resolv.h>
  #include <sys/epoll.h>
  #endif
  
  // -------------------------------------------------------------------
  //
  /**
   * Expected order of operations:
   * ==============================
   * 1. N x vma_setenv()
   * 2. vma_log_set_cb_func();
   * 3. vma_set_func_pointers();
   *
   * all functions return 'true' on success; 'false' - otherwise
   *
   * NOTE: including this header will redirect all relevant API calls to pointers
   * to functions. Hence, you you are allowed to call any of the relevant APIs,
   * only after successfully completing vma_set_func_pointers()!
   *
   */
  
  //------------------------------------------------------------------------------
  // The  vma_setenv()  function adds the variable 'name' to the environment with
  // the value 'value', only if 'name' does not already exist.  If 'name' does exist
  // in the environment, then the value of 'name' is not changed.
  static inline bool vma_setenv(const char *name, const char *value) {
      return setenv(name, value, 0) == 0;
  }
  
  //
  //------------------------------------------------------------------------------
  // NOTE: int log_level is equivalent to VMA_TRACELEVEL (see VMA README.txt)
  typedef void (*vma_log_cb_t)(int log_level, const char *str);
  //
  // NOTE: log_cb will run in context of vma; hence, it must not block the thread
  bool vma_log_set_cb_func(vma_log_cb_t log_cb);
  
  //
  //------------------------------------------------------------------------------
  // loads libvma.so only in case 'loadVma' is set.  In any case sets
  // global pointer variables for ALL vma related function pointers.
  bool vma_set_func_pointers(bool loadVma);
  
  //------------------------------------------------------------------------------
  // loads libvma according to the given 'loadVmaPath',  then set
  // global pointer variables for ALL vma related function pointers.
  bool vma_set_func_pointers(const char *LibVmaPath);
  
  /**
   *-----------------------------------------------------------------------------
   *  typedef for variables that will hold the function-pointers
   *-----------------------------------------------------------------------------
   */
  
  typedef int (*socket_fptr_t)(int __domain, int __type, int __protocol);
  typedef int (*close_fptr_t)(int __fd);
  typedef int (*shutdown_fptr_t)(int __fd, int __how);
  
  typedef int (*accept_fptr_t)(int __fd, struct sockaddr *__addr, socklen_t *__addrlen);
  typedef int (*bind_fptr_t)(int __fd, const struct sockaddr *__addr, socklen_t __addrlen);
  typedef int (*connect_fptr_t)(int __fd, const struct sockaddr *__to, socklen_t __tolen);
  typedef int (*listen_fptr_t)(int __fd, int __backlog);
  
  typedef int (*setsockopt_fptr_t)(int __fd, int __level, int __optname, __const void *__optval,
                                   socklen_t __optlen);
  typedef int (*getsockopt_fptr_t)(int __fd, int __level, int __optname, void *__optval,
                                   socklen_t *__optlen);
  typedef int (*fcntl_fptr_t)(int __fd, int __cmd, ...);
  typedef int (*ioctl_fptr_t)(int __fd, int __request, ...);
  typedef int (*getsockname_fptr_t)(int __fd, struct sockaddr *__name, socklen_t *__namelen);
  typedef int (*getpeername_fptr_t)(int __fd, struct sockaddr *__name, socklen_t *__namelen);
  
  typedef ssize_t (*read_fptr_t)(int __fd, void *__buf, size_t __nbytes);
  typedef ssize_t (*readv_fptr_t)(int __fd, const struct iovec *iov, int iovcnt);
  typedef ssize_t (*recv_fptr_t)(int __fd, void *__buf, size_t __n, int __flags);
  typedef ssize_t (*recvmsg_fptr_t)(int __fd, struct msghdr *__message, int __flags);
  typedef ssize_t (*recvmmsg_fptr_t)(int __fd, struct mmsghdr *__mmsghdr, unsigned int __vlen,
                                     int __flags, const struct timespec *__timeout);
  typedef ssize_t (*recvfrom_fptr_t)(int __fd, void *__restrict __buf, size_t __n, int __flags,
                                     struct sockaddr *__from, socklen_t *__fromlen);
  
  typedef ssize_t (*write_fptr_t)(int __fd, __const void *__buf, size_t __n);
  typedef ssize_t (*writev_fptr_t)(int __fd, const struct iovec *iov, int iovcnt);
  typedef ssize_t (*send_fptr_t)(int __fd, __const void *__buf, size_t __n, int __flags);
  typedef ssize_t (*sendmsg_fptr_t)(int __fd, __const struct msghdr *__message, int __flags);
  typedef ssize_t (*sendmmsg_fptr_t)(int __fd, struct mmsghdr *__mmsghdr, unsigned int __vlen,
                                     int __flags);
  typedef ssize_t (*sendto_fptr_t)(int __fd, __const void *__buf, size_t __n, int __flags,
                                   const struct sockaddr *__to, socklen_t __tolen);
  
  typedef int (*select_fptr_t)(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds,
                               struct timeval *__timeout);
  typedef int (*pselect_fptr_t)(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__errorfds,
                                const struct timespec *__timeout, const sigset_t *__sigmask);
  
  typedef int (*poll_fptr_t)(struct pollfd *__fds, nfds_t __nfds, int __timeout);
  typedef int (*ppoll_fptr_t)(struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout,
                              const sigset_t *__sigmask);
  typedef int (*epoll_create_fptr_t)(int __size);
  typedef int (*epoll_create1_fptr_t)(int __flags);
  typedef int (*epoll_ctl_fptr_t)(int __epfd, int __op, int __fd, struct epoll_event *__event);
  typedef int (*epoll_wait_fptr_t)(int __epfd, struct epoll_event *__events, int __maxevents,
                                   int __timeout);
  typedef int (*epoll_pwait_fptr_t)(int __epfd, struct epoll_event *__events, int __maxevents,
                                    int __timeout, const sigset_t *sigmask);
  
  typedef int (*socketpair_fptr_t)(int __domain, int __type, int __protocol, int __sv[2]);
  typedef int (*pipe_fptr_t)(int __filedes[2]);
  typedef int (*open_fptr_t)(__const char *__file, int __oflag, ...);
  typedef int (*creat_fptr_t)(const char *__pathname, mode_t __mode);
  typedef int (*dup_fptr_t)(int fildes);
  typedef int (*dup2_fptr_t)(int fildes, int fildes2);
  
  typedef int (*clone_fptr_t)(int (*__fn)(void *), void *__child_stack, int __flags, void *__arg);
  typedef pid_t (*fork_fptr_t)(void);
  typedef pid_t (*vfork_fptr_t)(void);
  typedef int (*daemon_fptr_t)(int __nochdir, int __noclose);
  typedef int (*sigaction_fptr_t)(int signum, const struct sigaction *act, struct sigaction *oldact);
  
  /**
   *-----------------------------------------------------------------------------
   *  variables to hold the function-pointers
   *-----------------------------------------------------------------------------
   */
  extern socket_fptr_t fn_socket;
  extern close_fptr_t fn_close;
  extern shutdown_fptr_t fn_shutdown;
  extern accept_fptr_t fn_accept;
  extern bind_fptr_t fn_bind;
  extern connect_fptr_t fn_connect;
  extern listen_fptr_t fn_listen;
  
  extern setsockopt_fptr_t fn_setsockopt;
  extern getsockopt_fptr_t fn_getsockopt;
  extern fcntl_fptr_t fn_fcntl;
  extern ioctl_fptr_t fn_ioctl;
  extern getsockname_fptr_t fn_getsockname;
  extern getpeername_fptr_t fn_getpeername;
  extern read_fptr_t fn_read;
  extern readv_fptr_t fn_readv;
  extern recv_fptr_t fn_recv;
  extern recvmsg_fptr_t fn_recvmsg;
  extern recvmmsg_fptr_t fn_recvmmsg;
  extern recvfrom_fptr_t fn_recvfrom;
  extern write_fptr_t fn_write;
  extern writev_fptr_t fn_writev;
  extern send_fptr_t fn_send;
  extern sendmsg_fptr_t fn_sendmsg;
  extern sendmmsg_fptr_t fn_sendmmsg;
  extern sendto_fptr_t fn_sendto;
  extern select_fptr_t fn_select;
  extern pselect_fptr_t fn_pselect;
  extern poll_fptr_t fn_poll;
  extern ppoll_fptr_t fn_ppoll;
  extern epoll_create_fptr_t fn_epoll_create;
  extern epoll_create1_fptr_t fn_epoll_create1;
  extern epoll_ctl_fptr_t fn_epoll_ctl;
  extern epoll_wait_fptr_t fn_epoll_wait;
  extern epoll_pwait_fptr_t fn_epoll_pwait;
  extern socketpair_fptr_t fn_socketpair;
  extern pipe_fptr_t fn_pipe;
  extern open_fptr_t fn_open;
  extern creat_fptr_t fn_creat;
  extern dup_fptr_t fn_dup;
  extern dup2_fptr_t fn_dup2;
  extern clone_fptr_t fn_clone;
  extern fork_fptr_t fn_fork;
  extern vfork_fptr_t fn_vfork;
  extern daemon_fptr_t fn_daemon;
  extern sigaction_fptr_t fn_sigaction;
  
  #ifndef VMA_NO_FUNCTIONS_DEFINES
  // The following definitions will replace ALL relevant API calls with calls to our function
  // pointers.
  // NOTE: before any relevant API call, you MUST set our function pointers thru successful call to
  // 'vma_set_func_pointers'
  // (note: these definitions will not catch function prototypes neither combinations like 'struct
  // sigaction')
  #define socket(...) fn_socket(__VA_ARGS__)
  #define close(...) fn_close(__VA_ARGS__)
  #define shutdown(...) fn_shutdown(__VA_ARGS__)
  
  #define accept(...) fn_accept(__VA_ARGS__)
  #define bind(...) fn_bind(__VA_ARGS__)
  #define connect(...) fn_connect(__VA_ARGS__)
  #define listen(...) fn_listen(__VA_ARGS__)
  
  #define setsockopt(...) fn_setsockopt(__VA_ARGS__)
  #define getsockopt(...) fn_getsockopt(__VA_ARGS__)
  #define fcntl(...) fn_fcntl(__VA_ARGS__)
  #define ioctl(...) fn_ioctl(__VA_ARGS__)
  #define getsockname(...) fn_getsockname(__VA_ARGS__)
  #define getpeername(...) fn_getpeername(__VA_ARGS__)
  
  #define read(...) fn_read(__VA_ARGS__)
  #define readv(...) fn_readv(__VA_ARGS__)
  #define recv(...) fn_recv(__VA_ARGS__)
  #define recvmsg(...) fn_recvmsg(__VA_ARGS__)
  #define recvmmsg(...) fn_recvmmsg(__VA_ARGS__)
  #define recvfrom(...) fn_recvfrom(__VA_ARGS__)
  
  #define write(...) fn_write(__VA_ARGS__)
  #define writev(...) fn_writev(__VA_ARGS__)
  #define send(...) fn_send(__VA_ARGS__)
  #define sendmsg(...) fn_sendmsg(__VA_ARGS__)
  #define sendmmsg(...) fn_sendmmsg(__VA_ARGS__)
  #define sendto(...) fn_sendto(__VA_ARGS__)
  
  #define select(...) fn_select(__VA_ARGS__)
  #define pselect(...) fn_pselect(__VA_ARGS__)
  #define poll(...) fn_poll(__VA_ARGS__)
  #define ppoll(...) fn_ppoll(__VA_ARGS__)
  #define epoll_create(...) fn_epoll_create(__VA_ARGS__)
  #define epoll_create1(...) fn_epoll_create1(__VA_ARGS__)
  #define epoll_ctl(...) fn_epoll_ctl(__VA_ARGS__)
  #define epoll_wait(...) fn_epoll_wait(__VA_ARGS__)
  #define epoll_pwait(...) fn_epoll_pwait(__VA_ARGS__)
  
  #define socketpair(...) fn_socketpair(__VA_ARGS__)
  #define pipe(...) fn_pipe(__VA_ARGS__)
  #define open(...) fn_open(__VA_ARGS__)
  #define creat(...) fn_creat(__VA_ARGS__)
  #define dup(...) fn_dup(__VA_ARGS__)
  #define dup2(...) fn_dup2(__VA_ARGS__)
  
  #define clone(...) fn_clone(__VA_ARGS__)
  #define fork(...) fn_fork(__VA_ARGS__)
  #define vfork(...) fn_vfork(__VA_ARGS__)
  #define daemon(...) fn_daemon(__VA_ARGS__)
  #define sigaction(...) fn_sigaction(__VA_ARGS__)
  
  #endif // VMA_NO_FUNCTIONS_DEFINES
  
  #endif // VMA_REDIRECT_H
  