LCOV - code coverage report
Current view: top level - vcl - ldp.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 510 1326 38.5 %
Date: 2023-10-26 01:39:38 Functions: 18 28 64.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016-2019 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #ifdef HAVE_GNU_SOURCE
      17             : #define _GNU_SOURCE
      18             : #endif
      19             : 
      20             : #include <unistd.h>
      21             : #include <stdio.h>
      22             : #include <signal.h>
      23             : #include <dlfcn.h>
      24             : #include <pthread.h>
      25             : #include <time.h>
      26             : #include <stdarg.h>
      27             : #include <sys/resource.h>
      28             : #include <netinet/tcp.h>
      29             : #include <netinet/udp.h>
      30             : 
      31             : #include <vcl/ldp_socket_wrapper.h>
      32             : #include <vcl/ldp.h>
      33             : #include <sys/time.h>
      34             : 
      35             : #include <vcl/vcl_locked.h>
      36             : #include <vppinfra/time.h>
      37             : #include <vppinfra/bitmap.h>
      38             : #include <vppinfra/lock.h>
      39             : #include <vppinfra/pool.h>
      40             : #include <vppinfra/hash.h>
      41             : 
      42             : #define HAVE_CONSTRUCTOR_ATTRIBUTE
      43             : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
      44             : #define CONSTRUCTOR_ATTRIBUTE                       \
      45             :     __attribute__ ((constructor))
      46             : #else
      47             : #define CONSTRUCTOR_ATTRIBUTE
      48             : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
      49             : 
      50             : #define HAVE_DESTRUCTOR_ATTRIBUTE
      51             : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
      52             : #define DESTRUCTOR_ATTRIBUTE                        \
      53             :     __attribute__ ((destructor))
      54             : #else
      55             : #define DESTRUCTOR_ATTRIBUTE
      56             : #endif
      57             : 
      58             : #define LDP_MAX_NWORKERS 32
      59             : 
      60             : #ifdef HAVE_GNU_SOURCE
      61             : #define SOCKADDR_GET_SA(__addr) __addr.__sockaddr__;
      62             : #else
      63             : #define SOCKADDR_GET_SA(__addr) _addr;
      64             : #endif
      65             : 
      66             : #ifndef UDP_SEGMENT
      67             : #define UDP_SEGMENT 103
      68             : #endif
      69             : 
      70             : #ifndef SO_ORIGINAL_DST
      71             : /* from <linux/netfilter_ipv4.h> */
      72             : #define SO_ORIGINAL_DST 80
      73             : #endif
      74             : typedef struct ldp_worker_ctx_
      75             : {
      76             :   u8 *io_buffer;
      77             :   clib_time_t clib_time;
      78             : 
      79             :   /*
      80             :    * Select state
      81             :    */
      82             :   clib_bitmap_t *rd_bitmap;
      83             :   clib_bitmap_t *wr_bitmap;
      84             :   clib_bitmap_t *ex_bitmap;
      85             :   clib_bitmap_t *si_rd_bitmap;
      86             :   clib_bitmap_t *si_wr_bitmap;
      87             :   clib_bitmap_t *si_ex_bitmap;
      88             :   clib_bitmap_t *libc_rd_bitmap;
      89             :   clib_bitmap_t *libc_wr_bitmap;
      90             :   clib_bitmap_t *libc_ex_bitmap;
      91             : 
      92             :   /*
      93             :    * Poll state
      94             :    */
      95             :   vcl_poll_t *vcl_poll;
      96             :   struct pollfd *libc_poll;
      97             :   u16 *libc_poll_idxs;
      98             : 
      99             :   /*
     100             :    * Epoll state
     101             :    */
     102             :   u8 epoll_wait_vcl;
     103             :   u8 mq_epfd_added;
     104             :   int vcl_mq_epfd;
     105             : 
     106             : } ldp_worker_ctx_t;
     107             : 
     108             : /* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
     109             :  * they are the same size */
     110             : STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
     111             :                "ldp bitmap size mismatch");
     112             : STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
     113             :                "ldp bitmap size mismatch");
     114             : 
     115             : typedef struct
     116             : {
     117             :   ldp_worker_ctx_t *workers;
     118             :   int init;
     119             :   char app_name[LDP_APP_NAME_MAX];
     120             :   u32 vlsh_bit_val;
     121             :   u32 vlsh_bit_mask;
     122             :   u32 debug;
     123             : 
     124             :   /** vcl needs next epoll_create to go to libc_epoll */
     125             :   u8 vcl_needs_real_epoll;
     126             : 
     127             :   /**
     128             :    * crypto state used only for testing
     129             :    */
     130             :   u8 transparent_tls;
     131             :   u32 ckpair_index;
     132             : } ldp_main_t;
     133             : 
     134             : #define LDP_DEBUG ldp->debug
     135             : 
     136             : #define LDBG(_lvl, _fmt, _args...)                                      \
     137             :   if (ldp->debug > _lvl)                                          \
     138             :     {                                                                   \
     139             :       int errno_saved = errno;                                          \
     140             :       fprintf (stderr, "ldp<%d>: " _fmt "\n", getpid(), ##_args);     \
     141             :       errno = errno_saved;                                              \
     142             :     }
     143             : 
     144             : static ldp_main_t ldp_main = {
     145             :   .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
     146             :   .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
     147             :   .debug = LDP_DEBUG_INIT,
     148             :   .transparent_tls = 0,
     149             :   .ckpair_index = ~0,
     150             : };
     151             : 
     152             : static ldp_main_t *ldp = &ldp_main;
     153             : 
     154             : static inline ldp_worker_ctx_t *
     155      470265 : ldp_worker_get_current (void)
     156             : {
     157      470265 :   return (ldp->workers + vppcom_worker_index ());
     158             : }
     159             : 
     160             : /*
     161             :  * RETURN:  0 on success or -1 on error.
     162             :  * */
     163             : static inline void
     164          13 : ldp_set_app_name (char *app_name)
     165             : {
     166          13 :   snprintf (ldp->app_name, LDP_APP_NAME_MAX, "%s-ldp-%d", app_name, getpid ());
     167          13 : }
     168             : 
     169             : static inline char *
     170          13 : ldp_get_app_name ()
     171             : {
     172          13 :   if (ldp->app_name[0] == '\0')
     173          13 :     ldp_set_app_name (program_invocation_short_name);
     174             : 
     175          13 :   return ldp->app_name;
     176             : }
     177             : 
     178             : static inline int
     179      472590 : ldp_vlsh_to_fd (vls_handle_t vlsh)
     180             : {
     181      472590 :   return (vlsh + ldp->vlsh_bit_val);
     182             : }
     183             : 
     184             : static inline vls_handle_t
     185     3285520 : ldp_fd_to_vlsh (int fd)
     186             : {
     187     3285520 :   if (fd < ldp->vlsh_bit_val)
     188      108967 :     return VLS_INVALID_HANDLE;
     189             : 
     190     3176560 :   return (fd - ldp->vlsh_bit_val);
     191             : }
     192             : 
     193             : static void
     194          13 : ldp_alloc_workers (void)
     195             : {
     196          13 :   if (ldp->workers)
     197           0 :     return;
     198          13 :   pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
     199             : }
     200             : 
     201             : static void
     202          13 : ldp_init_cfg (void)
     203             : {
     204          13 :   char *env_var_str = getenv (LDP_ENV_DEBUG);
     205          13 :   if (env_var_str)
     206             :     {
     207             :       u32 tmp;
     208           0 :       if (sscanf (env_var_str, "%u", &tmp) != 1)
     209           0 :         clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
     210             :                       " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
     211             :                       env_var_str);
     212             :       else
     213             :         {
     214           0 :           ldp->debug = tmp;
     215           0 :           LDBG (0, "configured LDP debug level (%u) from env var "
     216             :                 LDP_ENV_DEBUG "!", ldp->debug);
     217             :         }
     218             :     }
     219             : 
     220          13 :   env_var_str = getenv (LDP_ENV_APP_NAME);
     221          13 :   if (env_var_str)
     222             :     {
     223           0 :       ldp_set_app_name (env_var_str);
     224           0 :       LDBG (0, "configured LDP app name (%s) from the env var "
     225             :             LDP_ENV_APP_NAME "!", ldp->app_name);
     226             :     }
     227             : 
     228          13 :   env_var_str = getenv (LDP_ENV_SID_BIT);
     229          13 :   if (env_var_str)
     230             :     {
     231             :       u32 sb;
     232           0 :       if (sscanf (env_var_str, "%u", &sb) != 1)
     233             :         {
     234           0 :           LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
     235             :                 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
     236             :                 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     237             :         }
     238           0 :       else if (sb < LDP_SID_BIT_MIN)
     239             :         {
     240           0 :           ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
     241           0 :           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
     242             : 
     243           0 :           LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
     244             :                 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
     245             :                 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
     246             :                 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     247             :         }
     248           0 :       else if (sb > LDP_SID_BIT_MAX)
     249             :         {
     250           0 :           ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
     251           0 :           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
     252             : 
     253           0 :           LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
     254             :                 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
     255             :                 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
     256             :                 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     257             :         }
     258             :       else
     259             :         {
     260           0 :           ldp->vlsh_bit_val = (1 << sb);
     261           0 :           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
     262             : 
     263           0 :           LDBG (0, "configured LDP sid bit (%u) from "
     264             :                 LDP_ENV_SID_BIT "!  sid bit value %d (0x%x)", sb,
     265             :                 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     266             :         }
     267             : 
     268             :       /* Make sure there are enough bits in the fd set for vcl sessions */
     269           0 :       if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
     270             :         {
     271             :           /* Only valid for select/pselect, so just WARNING and not exit */
     272           0 :           LDBG (0,
     273             :                 "WARNING: LDP vlsh bit value %d > FD_SETSIZE/2 %d, "
     274             :                 "select/pselect not supported now!",
     275             :                 ldp->vlsh_bit_val, FD_SETSIZE / 2);
     276             :         }
     277             :     }
     278          13 :   env_var_str = getenv (LDP_ENV_TLS_TRANS);
     279          13 :   if (env_var_str)
     280             :     {
     281           0 :       ldp->transparent_tls = 1;
     282             :     }
     283          13 : }
     284             : 
     285             : static int
     286          13 : ldp_init (void)
     287             : {
     288             :   ldp_worker_ctx_t *ldpw;
     289             :   int rv;
     290             : 
     291          13 :   if (ldp->init)
     292             :     {
     293           0 :       LDBG (0, "LDP is initialized already");
     294           0 :       return 0;
     295             :     }
     296             : 
     297          13 :   ldp_init_cfg ();
     298          13 :   ldp->init = 1;
     299          13 :   ldp->vcl_needs_real_epoll = 1;
     300          13 :   rv = vls_app_create (ldp_get_app_name ());
     301          13 :   if (rv != VPPCOM_OK)
     302             :     {
     303           0 :       ldp->vcl_needs_real_epoll = 0;
     304           0 :       if (rv == VPPCOM_EEXIST)
     305           0 :         return 0;
     306           0 :       LDBG (2,
     307             :             "\nERROR: ldp_init: vppcom_app_create()"
     308             :             " failed!  rv = %d (%s)\n",
     309             :             rv, vppcom_retval_str (rv));
     310           0 :       ldp->init = 0;
     311           0 :       return rv;
     312             :     }
     313          13 :   ldp->vcl_needs_real_epoll = 0;
     314          13 :   ldp_alloc_workers ();
     315          13 :   ldpw = ldp_worker_get_current ();
     316             : 
     317          13 :   pool_foreach (ldpw, ldp->workers)  {
     318           0 :     clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
     319             :   }
     320             : 
     321          13 :   LDBG (0, "LDP initialization: done!");
     322             : 
     323          13 :   return 0;
     324             : }
     325             : 
     326             : #define ldp_init_check()                                                      \
     327             :   if (PREDICT_FALSE (!ldp->init))                                             \
     328             :     {                                                                         \
     329             :       if ((errno = -ldp_init ()))                                             \
     330             :         return -1;                                                            \
     331             :     }
     332             : 
     333             : int
     334             : close (int fd)
     335             : {
     336             :   vls_handle_t vlsh;
     337             :   int rv, epfd;
     338             : 
     339          61 :   ldp_init_check ();
     340             : 
     341          61 :   vlsh = ldp_fd_to_vlsh (fd);
     342          61 :   if (vlsh != VLS_INVALID_HANDLE)
     343             :     {
     344          35 :       epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
     345          35 :       if (epfd > 0)
     346             :         {
     347           0 :           ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
     348           0 :           u32 size = sizeof (epfd);
     349             : 
     350           0 :           LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
     351             : 
     352           0 :           libc_close (epfd);
     353           0 :           ldpw->mq_epfd_added = 0;
     354             : 
     355           0 :           epfd = 0;
     356           0 :           (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
     357             :         }
     358          35 :       else if (PREDICT_FALSE (epfd < 0))
     359             :         {
     360           0 :           errno = -epfd;
     361           0 :           rv = -1;
     362           0 :           goto done;
     363             :         }
     364             : 
     365          35 :       LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
     366             : 
     367          35 :       rv = vls_close (vlsh);
     368          35 :       if (rv != VPPCOM_OK)
     369             :         {
     370           0 :           errno = -rv;
     371           0 :           rv = -1;
     372             :         }
     373             :     }
     374             :   else
     375             :     {
     376          26 :       LDBG (0, "fd %d: calling libc_close", fd);
     377          26 :       rv = libc_close (fd);
     378             :     }
     379             : 
     380          61 : done:
     381          61 :   return rv;
     382             : }
     383             : 
     384             : ssize_t
     385             : read (int fd, void *buf, size_t nbytes)
     386             : {
     387             :   vls_handle_t vlsh;
     388             :   ssize_t size;
     389             : 
     390      831362 :   ldp_init_check ();
     391             : 
     392      831362 :   vlsh = ldp_fd_to_vlsh (fd);
     393      831362 :   if (vlsh != VLS_INVALID_HANDLE)
     394             :     {
     395      726053 :       size = vls_read (vlsh, buf, nbytes);
     396      726053 :       if (size < 0)
     397             :         {
     398      267865 :           errno = -size;
     399      267865 :           size = -1;
     400             :         }
     401             :     }
     402             :   else
     403             :     {
     404      105309 :       size = libc_read (fd, buf, nbytes);
     405             :     }
     406             : 
     407      831362 :   return size;
     408             : }
     409             : 
     410             : ssize_t
     411             : readv (int fd, const struct iovec * iov, int iovcnt)
     412             : {
     413           0 :   int rv = 0, i, total = 0;
     414             :   vls_handle_t vlsh;
     415           0 :   ssize_t size = 0;
     416             : 
     417           0 :   ldp_init_check ();
     418             : 
     419           0 :   vlsh = ldp_fd_to_vlsh (fd);
     420           0 :   if (vlsh != VLS_INVALID_HANDLE)
     421             :     {
     422           0 :       for (i = 0; i < iovcnt; ++i)
     423             :         {
     424           0 :           rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
     425           0 :           if (rv <= 0)
     426           0 :             break;
     427             :           else
     428             :             {
     429           0 :               total += rv;
     430           0 :               if (rv < iov[i].iov_len)
     431           0 :                 break;
     432             :             }
     433             :         }
     434           0 :       if (rv < 0 && total == 0)
     435             :         {
     436           0 :           errno = -rv;
     437           0 :           size = -1;
     438             :         }
     439             :       else
     440           0 :         size = total;
     441             :     }
     442             :   else
     443             :     {
     444           0 :       size = libc_readv (fd, iov, iovcnt);
     445             :     }
     446             : 
     447           0 :   return size;
     448             : }
     449             : 
     450             : ssize_t
     451             : write (int fd, const void *buf, size_t nbytes)
     452             : {
     453             :   vls_handle_t vlsh;
     454     1109820 :   ssize_t size = 0;
     455             : 
     456     1109820 :   ldp_init_check ();
     457             : 
     458     1109820 :   vlsh = ldp_fd_to_vlsh (fd);
     459     1109820 :   if (vlsh != VLS_INVALID_HANDLE)
     460             :     {
     461     1109770 :       size = vls_write_msg (vlsh, (void *) buf, nbytes);
     462     1109770 :       if (size < 0)
     463             :         {
     464      948944 :           errno = -size;
     465      948944 :           size = -1;
     466             :         }
     467             :     }
     468             :   else
     469             :     {
     470          44 :       size = libc_write (fd, buf, nbytes);
     471             :     }
     472             : 
     473     1109820 :   return size;
     474             : }
     475             : 
     476             : ssize_t
     477             : writev (int fd, const struct iovec * iov, int iovcnt)
     478             : {
     479         219 :   ssize_t size = 0, total = 0;
     480             :   vls_handle_t vlsh;
     481         219 :   int i, rv = 0;
     482             : 
     483         219 :   ldp_init_check ();
     484             : 
     485         219 :   vlsh = ldp_fd_to_vlsh (fd);
     486         219 :   if (vlsh != VLS_INVALID_HANDLE)
     487             :     {
     488           0 :       for (i = 0; i < iovcnt; ++i)
     489             :         {
     490           0 :           rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
     491           0 :           if (rv < 0)
     492           0 :             break;
     493             :           else
     494             :             {
     495           0 :               total += rv;
     496           0 :               if (rv < iov[i].iov_len)
     497           0 :                 break;
     498             :             }
     499             :         }
     500             : 
     501           0 :       if (rv < 0 && total == 0)
     502             :         {
     503           0 :           errno = -rv;
     504           0 :           size = -1;
     505             :         }
     506             :       else
     507           0 :         size = total;
     508             :     }
     509             :   else
     510             :     {
     511         219 :       size = libc_writev (fd, iov, iovcnt);
     512             :     }
     513             : 
     514         219 :   return size;
     515             : }
     516             : 
     517             : static int
     518          64 : fcntl_internal (int fd, int cmd, va_list ap)
     519             : {
     520             :   vls_handle_t vlsh;
     521          64 :   int rv = 0;
     522             : 
     523          64 :   vlsh = ldp_fd_to_vlsh (fd);
     524          64 :   LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
     525          64 :   if (vlsh != VLS_INVALID_HANDLE)
     526             :     {
     527          37 :       int flags = va_arg (ap, int);
     528             :       u32 size;
     529             : 
     530          37 :       size = sizeof (flags);
     531          37 :       rv = -EOPNOTSUPP;
     532          37 :       switch (cmd)
     533             :         {
     534          23 :         case F_SETFL:
     535          23 :           rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
     536          23 :           break;
     537             : 
     538          14 :         case F_GETFL:
     539          14 :           rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
     540          14 :           if (rv == VPPCOM_OK)
     541          14 :             rv = flags;
     542          14 :           break;
     543           0 :         case F_SETFD:
     544             :           /* TODO handle this */
     545           0 :           LDBG (0, "F_SETFD ignored flags %u", flags);
     546           0 :           rv = 0;
     547           0 :           break;
     548           0 :         default:
     549           0 :           rv = -EOPNOTSUPP;
     550           0 :           break;
     551             :         }
     552          37 :       if (rv < 0)
     553             :         {
     554           0 :           errno = -rv;
     555           0 :           rv = -1;
     556             :         }
     557             :     }
     558             :   else
     559             :     {
     560             : #ifdef HAVE_FCNTL64
     561          27 :       rv = libc_vfcntl64 (fd, cmd, ap);
     562             : #else
     563             :       rv = libc_vfcntl (fd, cmd, ap);
     564             : #endif
     565             :     }
     566             : 
     567          64 :   return rv;
     568             : }
     569             : 
     570             : int
     571             : fcntl (int fd, int cmd, ...)
     572             : {
     573             :   va_list ap;
     574             :   int rv;
     575             : 
     576          64 :   ldp_init_check ();
     577             : 
     578          64 :   va_start (ap, cmd);
     579          64 :   rv = fcntl_internal (fd, cmd, ap);
     580          64 :   va_end (ap);
     581             : 
     582          64 :   return rv;
     583             : }
     584             : 
     585             : int
     586             : fcntl64 (int fd, int cmd, ...)
     587             : {
     588             :   va_list ap;
     589             :   int rv;
     590             : 
     591           0 :   ldp_init_check ();
     592             : 
     593           0 :   va_start (ap, cmd);
     594           0 :   rv = fcntl_internal (fd, cmd, ap);
     595           0 :   va_end (ap);
     596           0 :   return rv;
     597             : }
     598             : 
     599             : int
     600             : ioctl (int fd, unsigned long int cmd, ...)
     601             : {
     602             :   vls_handle_t vlsh;
     603             :   va_list ap;
     604             :   int rv;
     605             : 
     606         241 :   ldp_init_check ();
     607             : 
     608         241 :   va_start (ap, cmd);
     609             : 
     610         241 :   vlsh = ldp_fd_to_vlsh (fd);
     611         241 :   if (vlsh != VLS_INVALID_HANDLE)
     612             :     {
     613         241 :       switch (cmd)
     614             :         {
     615         241 :         case FIONREAD:
     616         241 :           rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
     617         241 :           break;
     618             : 
     619           0 :         case FIONBIO:
     620             :           {
     621           0 :             u32 flags = *(va_arg (ap, int *)) ? O_NONBLOCK : 0;
     622           0 :             u32 size = sizeof (flags);
     623             : 
     624             :             /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
     625             :              *      non-blocking, the flags should be read here and merged
     626             :              *      with O_NONBLOCK.
     627             :              */
     628           0 :             rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
     629             :           }
     630           0 :           break;
     631             : 
     632           0 :         default:
     633           0 :           rv = -EOPNOTSUPP;
     634           0 :           break;
     635             :         }
     636         241 :       if (rv < 0)
     637             :         {
     638           0 :           errno = -rv;
     639           0 :           rv = -1;
     640             :         }
     641             :     }
     642             :   else
     643             :     {
     644           0 :       rv = libc_vioctl (fd, cmd, ap);
     645             :     }
     646             : 
     647         241 :   va_end (ap);
     648         241 :   return rv;
     649             : }
     650             : 
     651             : always_inline void
     652      939000 : ldp_select_init_maps (fd_set * __restrict original,
     653             :                       clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
     654             :                       clib_bitmap_t ** vclb, int nfds, u32 minbits,
     655             :                       u32 n_bytes, uword * si_bits, uword * libc_bits)
     656             : {
     657             :   uword si_bits_set, libc_bits_set;
     658             :   vls_handle_t vlsh;
     659             :   int fd;
     660             : 
     661      939000 :   clib_bitmap_validate (*vclb, minbits);
     662      939000 :   clib_bitmap_validate (*libcb, minbits);
     663      939000 :   clib_bitmap_validate (*resultb, minbits);
     664      939000 :   clib_memcpy_fast (*resultb, original, n_bytes);
     665      939000 :   memset (original, 0, n_bytes);
     666             : 
     667             :   /* *INDENT-OFF* */
     668     2278970 :   clib_bitmap_foreach (fd, *resultb)  {
     669     1339970 :     if (fd > nfds)
     670           0 :       break;
     671     1339970 :     vlsh = ldp_fd_to_vlsh (fd);
     672     1339970 :     if (vlsh == VLS_INVALID_HANDLE)
     673           0 :       clib_bitmap_set_no_check (*libcb, fd, 1);
     674             :     else
     675     1339970 :       *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
     676             :   }
     677             :   /* *INDENT-ON* */
     678             : 
     679      939000 :   si_bits_set = clib_bitmap_last_set (*vclb) + 1;
     680      939000 :   *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
     681      939000 :   clib_bitmap_validate (*resultb, *si_bits);
     682             : 
     683      939000 :   libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
     684      939000 :   *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
     685      939000 : }
     686             : 
     687             : always_inline int
     688     1403960 : ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
     689             : {
     690             :   vls_handle_t vlsh;
     691             :   uword si;
     692             :   int fd;
     693             : 
     694     1403960 :   if (!libcb)
     695      468985 :     return 0;
     696             : 
     697             :   /* *INDENT-OFF* */
     698     1407510 :   clib_bitmap_foreach (si, vclb)  {
     699      472543 :     vlsh = vls_session_index_to_vlsh (si);
     700      472543 :     ASSERT (vlsh != VLS_INVALID_HANDLE);
     701      472543 :     fd = ldp_vlsh_to_fd (vlsh);
     702      472543 :     if (PREDICT_FALSE (fd < 0))
     703             :       {
     704           0 :         errno = EBADFD;
     705           0 :         return -1;
     706             :       }
     707      472543 :     FD_SET (fd, libcb);
     708             :   }
     709             :   /* *INDENT-ON* */
     710             : 
     711      934970 :   return 0;
     712             : }
     713             : 
     714             : always_inline void
     715           0 : ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
     716             : {
     717             :   uword fd;
     718             : 
     719           0 :   if (!libcb)
     720           0 :     return;
     721             : 
     722             :   /* *INDENT-OFF* */
     723           0 :   clib_bitmap_foreach (fd, result)
     724           0 :     FD_SET ((int)fd, libcb);
     725             :   /* *INDENT-ON* */
     726             : }
     727             : 
     728             : int
     729      470003 : ldp_pselect (int nfds, fd_set * __restrict readfds,
     730             :              fd_set * __restrict writefds,
     731             :              fd_set * __restrict exceptfds,
     732             :              const struct timespec *__restrict timeout,
     733             :              const __sigset_t * __restrict sigmask)
     734             : {
     735      470003 :   u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
     736      470003 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
     737      470003 :   struct timespec libc_tspec = { 0 };
     738      470003 :   f64 time_out, vcl_timeout = 0;
     739             :   uword si_bits, libc_bits;
     740      470003 :   int rv, bits_set = 0;
     741             : 
     742      470003 :   if (nfds < 0)
     743             :     {
     744           0 :       errno = EINVAL;
     745           0 :       return -1;
     746             :     }
     747             : 
     748      470003 :   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
     749          12 :     clib_time_init (&ldpw->clib_time);
     750             : 
     751      470003 :   if (timeout)
     752             :     {
     753      469864 :       time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
     754      939729 :         (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
     755             : 
     756      469865 :       time_out += clib_time_now (&ldpw->clib_time);
     757             : 
     758             :       /* select as fine grained sleep */
     759      469865 :       if (!nfds)
     760             :         {
     761           0 :           while (clib_time_now (&ldpw->clib_time) < time_out)
     762             :             ;
     763           0 :           return 0;
     764             :         }
     765             :     }
     766         138 :   else if (!nfds)
     767             :     {
     768           0 :       errno = EINVAL;
     769           0 :       return -1;
     770             :     }
     771             :   else
     772         138 :     time_out = -1;
     773             : 
     774      470003 :   if (nfds <= ldp->vlsh_bit_val)
     775             :     {
     776           0 :       rv = libc_pselect (nfds, readfds, writefds, exceptfds,
     777             :                          timeout, sigmask);
     778           0 :       goto done;
     779             :     }
     780             : 
     781      470003 :   si_bits = libc_bits = 0;
     782      470003 :   n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
     783             : 
     784      470003 :   if (readfds)
     785      469003 :     ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
     786             :                           &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
     787             :                           &si_bits, &libc_bits);
     788      470003 :   if (writefds)
     789      469997 :     ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
     790             :                           &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
     791             :                           minbits, n_bytes, &si_bits, &libc_bits);
     792      470003 :   if (exceptfds)
     793           0 :     ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
     794             :                           &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
     795             :                           minbits, n_bytes, &si_bits, &libc_bits);
     796             : 
     797      470003 :   if (PREDICT_FALSE (!si_bits && !libc_bits))
     798             :     {
     799           0 :       errno = EINVAL;
     800           0 :       rv = -1;
     801           0 :       goto done;
     802             :     }
     803             : 
     804      470003 :   if (!si_bits)
     805           0 :     libc_tspec = timeout ? *timeout : libc_tspec;
     806             : 
     807             :   do
     808             :     {
     809    26331000 :       if (si_bits)
     810             :         {
     811    26331000 :           if (readfds)
     812    26330000 :             clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
     813    26330000 :                               vec_len (ldpw->si_rd_bitmap) *
     814             :                               sizeof (clib_bitmap_t));
     815    26331000 :           if (writefds)
     816    26331000 :             clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
     817    26331000 :                               vec_len (ldpw->si_wr_bitmap) *
     818             :                               sizeof (clib_bitmap_t));
     819    26331000 :           if (exceptfds)
     820           0 :             clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
     821           0 :                               vec_len (ldpw->si_ex_bitmap) *
     822             :                               sizeof (clib_bitmap_t));
     823             : 
     824    26331000 :           rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
     825             :                            writefds ? ldpw->wr_bitmap : NULL,
     826             :                            exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
     827    26331000 :           if (rv < 0)
     828             :             {
     829           0 :               errno = -rv;
     830           0 :               rv = -1;
     831           0 :               goto done;
     832             :             }
     833    26331000 :           else if (rv > 0)
     834             :             {
     835      467985 :               if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
     836             :                 {
     837           0 :                   rv = -1;
     838           0 :                   goto done;
     839             :                 }
     840             : 
     841      467985 :               if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
     842             :                 {
     843           0 :                   rv = -1;
     844           0 :                   goto done;
     845             :                 }
     846             : 
     847      467985 :               if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
     848             :                 {
     849           0 :                   rv = -1;
     850           0 :                   goto done;
     851             :                 }
     852      467985 :               bits_set = rv;
     853             :             }
     854             :         }
     855    26331000 :       if (libc_bits)
     856             :         {
     857           0 :           if (readfds)
     858           0 :             clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
     859           0 :                               vec_len (ldpw->libc_rd_bitmap) *
     860             :                               sizeof (clib_bitmap_t));
     861           0 :           if (writefds)
     862           0 :             clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
     863           0 :                               vec_len (ldpw->libc_wr_bitmap) *
     864             :                               sizeof (clib_bitmap_t));
     865           0 :           if (exceptfds)
     866           0 :             clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
     867           0 :                               vec_len (ldpw->libc_ex_bitmap) *
     868             :                               sizeof (clib_bitmap_t));
     869             : 
     870           0 :           rv = libc_pselect (libc_bits,
     871             :                              readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
     872             :                              writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
     873             :                              exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
     874             :                              &libc_tspec, sigmask);
     875           0 :           if (rv > 0)
     876             :             {
     877           0 :               ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
     878           0 :               ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
     879           0 :               ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
     880           0 :               bits_set += rv;
     881             :             }
     882             :         }
     883             : 
     884    26331000 :       if (bits_set)
     885             :         {
     886      467985 :           rv = bits_set;
     887      467985 :           goto done;
     888             :         }
     889             :     }
     890    25863000 :   while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
     891        2013 :   rv = 0;
     892             : 
     893      469998 : done:
     894             :   /* TBD: set timeout to amount of time left */
     895      469998 :   clib_bitmap_zero (ldpw->rd_bitmap);
     896      469998 :   clib_bitmap_zero (ldpw->si_rd_bitmap);
     897      469998 :   clib_bitmap_zero (ldpw->libc_rd_bitmap);
     898      469998 :   clib_bitmap_zero (ldpw->wr_bitmap);
     899      469998 :   clib_bitmap_zero (ldpw->si_wr_bitmap);
     900      469998 :   clib_bitmap_zero (ldpw->libc_wr_bitmap);
     901      469998 :   clib_bitmap_zero (ldpw->ex_bitmap);
     902      469998 :   clib_bitmap_zero (ldpw->si_ex_bitmap);
     903      469998 :   clib_bitmap_zero (ldpw->libc_ex_bitmap);
     904             : 
     905      469998 :   return rv;
     906             : }
     907             : 
     908             : int
     909             : select (int nfds, fd_set * __restrict readfds,
     910             :         fd_set * __restrict writefds,
     911             :         fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
     912             : {
     913             :   struct timespec tspec;
     914             : 
     915      470003 :   if (timeout)
     916             :     {
     917      469865 :       tspec.tv_sec = timeout->tv_sec;
     918      469865 :       tspec.tv_nsec = timeout->tv_usec * 1000;
     919             :     }
     920      470003 :   return ldp_pselect (nfds, readfds, writefds, exceptfds,
     921             :                       timeout ? &tspec : NULL, NULL);
     922             : }
     923             : 
     924             : #ifdef __USE_XOPEN2K
     925             : int
     926             : pselect (int nfds, fd_set * __restrict readfds,
     927             :          fd_set * __restrict writefds,
     928             :          fd_set * __restrict exceptfds,
     929             :          const struct timespec *__restrict timeout,
     930             :          const __sigset_t * __restrict sigmask)
     931             : {
     932           0 :   return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
     933             : }
     934             : #endif
     935             : 
     936             : /* If transparent TLS mode is turned on, then ldp will load key and cert.
     937             :  */
     938             : static int
     939           0 : load_cert_key_pair (void)
     940             : {
     941           0 :   char *cert_str = getenv (LDP_ENV_TLS_CERT);
     942           0 :   char *key_str = getenv (LDP_ENV_TLS_KEY);
     943             :   char cert_buf[4096], key_buf[4096];
     944             :   int cert_size, key_size;
     945             :   vppcom_cert_key_pair_t crypto;
     946             :   int ckp_index;
     947             :   FILE *fp;
     948             : 
     949           0 :   if (!cert_str || !key_str)
     950             :     {
     951           0 :       LDBG (0, "ERROR: failed to read LDP environment %s\n",
     952             :             LDP_ENV_TLS_CERT);
     953           0 :       return -1;
     954             :     }
     955             : 
     956           0 :   fp = fopen (cert_str, "r");
     957           0 :   if (fp == NULL)
     958             :     {
     959           0 :       LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
     960           0 :       return -1;
     961             :     }
     962           0 :   cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
     963           0 :   fclose (fp);
     964             : 
     965           0 :   fp = fopen (key_str, "r");
     966           0 :   if (fp == NULL)
     967             :     {
     968           0 :       LDBG (0, "ERROR: failed to open key file %s \n", key_str);
     969           0 :       return -1;
     970             :     }
     971           0 :   key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
     972           0 :   fclose (fp);
     973             : 
     974           0 :   crypto.cert = cert_buf;
     975           0 :   crypto.key = key_buf;
     976           0 :   crypto.cert_len = cert_size;
     977           0 :   crypto.key_len = key_size;
     978           0 :   ckp_index = vppcom_add_cert_key_pair (&crypto);
     979           0 :   if (ckp_index < 0)
     980             :     {
     981           0 :       LDBG (0, "ERROR: failed to add cert key pair\n");
     982           0 :       return -1;
     983             :     }
     984             : 
     985           0 :   ldp->ckpair_index = ckp_index;
     986             : 
     987           0 :   return 0;
     988             : }
     989             : 
     990             : static int
     991           0 : assign_cert_key_pair (vls_handle_t vlsh)
     992             : {
     993             :   uint32_t ckp_len;
     994             : 
     995           0 :   if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
     996           0 :     return -1;
     997             : 
     998           0 :   ckp_len = sizeof (ldp->ckpair_index);
     999           0 :   return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
    1000             : }
    1001             : 
    1002             : int
    1003             : socket (int domain, int type, int protocol)
    1004             : {
    1005          49 :   int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
    1006          49 :   u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
    1007             :   vls_handle_t vlsh;
    1008             : 
    1009          49 :   ldp_init_check ();
    1010             : 
    1011          49 :   if (((domain == AF_INET) || (domain == AF_INET6)) &&
    1012           5 :       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
    1013          35 :     {
    1014             :       u8 proto;
    1015          35 :       if (ldp->transparent_tls)
    1016             :         {
    1017           0 :           proto = VPPCOM_PROTO_TLS;
    1018             :         }
    1019             :       else
    1020          35 :         proto = ((sock_type == SOCK_DGRAM) ?
    1021          35 :                  VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
    1022             : 
    1023          35 :       LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
    1024             :             proto, vppcom_proto_str (proto), is_nonblocking);
    1025             : 
    1026          35 :       vlsh = vls_create (proto, is_nonblocking);
    1027          35 :       if (vlsh < 0)
    1028             :         {
    1029           0 :           errno = -vlsh;
    1030           0 :           rv = -1;
    1031             :         }
    1032             :       else
    1033             :         {
    1034          35 :           if (ldp->transparent_tls)
    1035             :             {
    1036           0 :               if (assign_cert_key_pair (vlsh) < 0)
    1037           0 :                 return -1;
    1038             :             }
    1039          35 :           rv = ldp_vlsh_to_fd (vlsh);
    1040             :         }
    1041             :     }
    1042             :   else
    1043             :     {
    1044          14 :       LDBG (0, "calling libc_socket");
    1045          14 :       rv = libc_socket (domain, type, protocol);
    1046             :     }
    1047             : 
    1048          49 :   return rv;
    1049             : }
    1050             : 
    1051             : /*
    1052             :  * Create two new sockets, of type TYPE in domain DOMAIN and using
    1053             :  * protocol PROTOCOL, which are connected to each other, and put file
    1054             :  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
    1055             :  * one will be chosen automatically.
    1056             :  * Returns 0 on success, -1 for errors.
    1057             :  * */
    1058             : int
    1059             : socketpair (int domain, int type, int protocol, int fds[2])
    1060             : {
    1061           0 :   int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
    1062             : 
    1063           0 :   ldp_init_check ();
    1064             : 
    1065           0 :   if (((domain == AF_INET) || (domain == AF_INET6)) &&
    1066           0 :       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
    1067             :     {
    1068           0 :       LDBG (0, "LDP-TBD");
    1069           0 :       errno = ENOSYS;
    1070           0 :       rv = -1;
    1071             :     }
    1072             :   else
    1073             :     {
    1074           0 :       LDBG (1, "calling libc_socketpair");
    1075           0 :       rv = libc_socketpair (domain, type, protocol, fds);
    1076             :     }
    1077             : 
    1078           0 :   return rv;
    1079             : }
    1080             : 
    1081             : int
    1082             : bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
    1083             : {
    1084          17 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1085             :   vls_handle_t vlsh;
    1086             :   int rv;
    1087             : 
    1088          17 :   ldp_init_check ();
    1089             : 
    1090          17 :   vlsh = ldp_fd_to_vlsh (fd);
    1091          17 :   if (vlsh != VLS_INVALID_HANDLE)
    1092             :     {
    1093             :       vppcom_endpt_t ep;
    1094             : 
    1095          16 :       switch (addr->sa_family)
    1096             :         {
    1097          14 :         case AF_INET:
    1098          14 :           if (len != sizeof (struct sockaddr_in))
    1099             :             {
    1100           0 :               LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
    1101             :                     fd, vlsh, len);
    1102           0 :               errno = EINVAL;
    1103           0 :               rv = -1;
    1104           0 :               goto done;
    1105             :             }
    1106          14 :           ep.is_ip4 = VPPCOM_IS_IP4;
    1107          14 :           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
    1108          14 :           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
    1109          14 :           break;
    1110             : 
    1111           2 :         case AF_INET6:
    1112           2 :           if (len != sizeof (struct sockaddr_in6))
    1113             :             {
    1114           0 :               LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
    1115             :                     fd, vlsh, len);
    1116           0 :               errno = EINVAL;
    1117           0 :               rv = -1;
    1118           0 :               goto done;
    1119             :             }
    1120           2 :           ep.is_ip4 = VPPCOM_IS_IP6;
    1121           2 :           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
    1122           2 :           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
    1123           2 :           break;
    1124             : 
    1125           0 :         default:
    1126           0 :           LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
    1127             :                 fd, vlsh, addr->sa_family);
    1128           0 :           errno = EAFNOSUPPORT;
    1129           0 :           rv = -1;
    1130           0 :           goto done;
    1131             :         }
    1132          16 :       LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
    1133             :             addr, len);
    1134             : 
    1135          16 :       rv = vls_bind (vlsh, &ep);
    1136          16 :       if (rv != VPPCOM_OK)
    1137             :         {
    1138           0 :           errno = -rv;
    1139           0 :           rv = -1;
    1140             :         }
    1141             :     }
    1142             :   else
    1143             :     {
    1144           1 :       LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
    1145           1 :       rv = libc_bind (fd, addr, len);
    1146             :     }
    1147             : 
    1148          17 : done:
    1149          17 :   LDBG (1, "fd %d: returning %d", fd, rv);
    1150             : 
    1151          17 :   return rv;
    1152             : }
    1153             : 
    1154             : static inline int
    1155          59 : ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
    1156             :                          vppcom_endpt_t *ep)
    1157             : {
    1158          59 :   int rv = 0, sa_len, copy_len;
    1159             : 
    1160          59 :   ldp_init_check ();
    1161             : 
    1162          59 :   if (addr && len && ep)
    1163             :     {
    1164          57 :       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
    1165          57 :       switch (addr->sa_family)
    1166             :         {
    1167          47 :         case AF_INET:
    1168          47 :           ((struct sockaddr_in *) addr)->sin_port = ep->port;
    1169          47 :           if (*len > sizeof (struct sockaddr_in))
    1170          47 :             *len = sizeof (struct sockaddr_in);
    1171          47 :           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
    1172          47 :           copy_len = *len - sa_len;
    1173          47 :           if (copy_len > 0)
    1174          47 :             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
    1175             :                     copy_len);
    1176          47 :           break;
    1177             : 
    1178          10 :         case AF_INET6:
    1179          10 :           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
    1180          10 :           if (*len > sizeof (struct sockaddr_in6))
    1181          10 :             *len = sizeof (struct sockaddr_in6);
    1182          10 :           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
    1183          10 :           copy_len = *len - sa_len;
    1184          10 :           if (copy_len > 0)
    1185          10 :             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
    1186          10 :                     __in6_u.__u6_addr8, ep->ip, copy_len);
    1187          10 :           break;
    1188             : 
    1189           0 :         default:
    1190             :           /* Not possible */
    1191           0 :           rv = -EAFNOSUPPORT;
    1192           0 :           break;
    1193             :         }
    1194           2 :     }
    1195          59 :   return rv;
    1196             : }
    1197             : 
    1198             : int
    1199             : getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
    1200             : {
    1201          29 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1202             :   vls_handle_t vlsh;
    1203             :   int rv;
    1204             : 
    1205          29 :   ldp_init_check ();
    1206             : 
    1207          29 :   vlsh = ldp_fd_to_vlsh (fd);
    1208          29 :   if (vlsh != VLS_INVALID_HANDLE)
    1209             :     {
    1210             :       vppcom_endpt_t ep;
    1211             :       u8 addr_buf[sizeof (struct in6_addr)];
    1212          29 :       u32 size = sizeof (ep);
    1213             : 
    1214          29 :       ep.ip = addr_buf;
    1215             : 
    1216          29 :       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
    1217          29 :       if (rv != VPPCOM_OK)
    1218             :         {
    1219           0 :           errno = -rv;
    1220           0 :           rv = -1;
    1221             :         }
    1222             :       else
    1223             :         {
    1224          29 :           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
    1225          29 :           if (rv != VPPCOM_OK)
    1226             :             {
    1227           0 :               errno = -rv;
    1228           0 :               rv = -1;
    1229             :             }
    1230             :         }
    1231             :     }
    1232             :   else
    1233             :     {
    1234           0 :       rv = libc_getsockname (fd, _addr, len);
    1235             :     }
    1236             : 
    1237          29 :   return rv;
    1238             : }
    1239             : 
    1240             : int
    1241             : connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
    1242             : {
    1243          34 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1244             :   vls_handle_t vlsh;
    1245             :   int rv;
    1246             : 
    1247          34 :   ldp_init_check ();
    1248             : 
    1249          34 :   if (!addr)
    1250             :     {
    1251           0 :       LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
    1252           0 :       errno = EINVAL;
    1253           0 :       rv = -1;
    1254           0 :       goto done;
    1255             :     }
    1256             : 
    1257          34 :   vlsh = ldp_fd_to_vlsh (fd);
    1258          34 :   if (vlsh != VLS_INVALID_HANDLE)
    1259             :     {
    1260             :       vppcom_endpt_t ep;
    1261             : 
    1262          21 :       switch (addr->sa_family)
    1263             :         {
    1264          19 :         case AF_INET:
    1265          19 :           if (len != sizeof (struct sockaddr_in))
    1266             :             {
    1267           0 :               LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
    1268             :                     fd, vlsh, len);
    1269           0 :               errno = EINVAL;
    1270           0 :               rv = -1;
    1271           0 :               goto done;
    1272             :             }
    1273          19 :           ep.is_ip4 = VPPCOM_IS_IP4;
    1274          19 :           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
    1275          19 :           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
    1276          19 :           break;
    1277             : 
    1278           2 :         case AF_INET6:
    1279           2 :           if (len != sizeof (struct sockaddr_in6))
    1280             :             {
    1281           0 :               LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
    1282             :                     fd, vlsh, len);
    1283           0 :               errno = EINVAL;
    1284           0 :               rv = -1;
    1285           0 :               goto done;
    1286             :             }
    1287           2 :           ep.is_ip4 = VPPCOM_IS_IP6;
    1288           2 :           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
    1289           2 :           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
    1290           2 :           break;
    1291             : 
    1292           0 :         default:
    1293           0 :           LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
    1294             :                 fd, vlsh, addr->sa_family);
    1295           0 :           errno = EAFNOSUPPORT;
    1296           0 :           rv = -1;
    1297           0 :           goto done;
    1298             :         }
    1299          21 :       LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
    1300             :             vlsh, addr, len);
    1301             : 
    1302          21 :       rv = vls_connect (vlsh, &ep);
    1303          21 :       if (rv != VPPCOM_OK)
    1304             :         {
    1305           0 :           errno = -rv;
    1306           0 :           rv = -1;
    1307             :         }
    1308             :     }
    1309             :   else
    1310             :     {
    1311          13 :       LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
    1312             :             fd, addr, len);
    1313             : 
    1314          13 :       rv = libc_connect (fd, addr, len);
    1315             :     }
    1316             : 
    1317          34 : done:
    1318          34 :   LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
    1319          34 :   return rv;
    1320             : }
    1321             : 
    1322             : int
    1323             : getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
    1324             : {
    1325          17 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1326             :   vls_handle_t vlsh;
    1327             :   int rv;
    1328             : 
    1329          17 :   ldp_init_check ();
    1330             : 
    1331          17 :   vlsh = ldp_fd_to_vlsh (fd);
    1332          17 :   if (vlsh != VLS_INVALID_HANDLE)
    1333             :     {
    1334             :       vppcom_endpt_t ep;
    1335             :       u8 addr_buf[sizeof (struct in6_addr)];
    1336          17 :       u32 size = sizeof (ep);
    1337             : 
    1338          17 :       ep.ip = addr_buf;
    1339          17 :       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
    1340          17 :       if (rv != VPPCOM_OK)
    1341             :         {
    1342           0 :           errno = -rv;
    1343           0 :           rv = -1;
    1344             :         }
    1345             :       else
    1346             :         {
    1347          17 :           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
    1348          17 :           if (rv != VPPCOM_OK)
    1349             :             {
    1350           0 :               errno = -rv;
    1351           0 :               rv = -1;
    1352             :             }
    1353             :         }
    1354             :     }
    1355             :   else
    1356             :     {
    1357           0 :       rv = libc_getpeername (fd, addr, len);
    1358             :     }
    1359             : 
    1360          17 :   return rv;
    1361             : }
    1362             : 
    1363             : ssize_t
    1364             : send (int fd, const void *buf, size_t n, int flags)
    1365             : {
    1366           0 :   vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
    1367             :   ssize_t size;
    1368             : 
    1369           0 :   ldp_init_check ();
    1370             : 
    1371           0 :   if (vlsh != VLS_INVALID_HANDLE)
    1372             :     {
    1373           0 :       size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
    1374           0 :       if (size < VPPCOM_OK)
    1375             :         {
    1376           0 :           errno = -size;
    1377           0 :           size = -1;
    1378             :         }
    1379             :     }
    1380             :   else
    1381             :     {
    1382           0 :       size = libc_send (fd, buf, n, flags);
    1383             :     }
    1384             : 
    1385           0 :   return size;
    1386             : }
    1387             : 
    1388             : ssize_t
    1389           0 : sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
    1390             : {
    1391           0 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    1392             :   vls_handle_t vlsh;
    1393           0 :   ssize_t size = 0;
    1394             : 
    1395           0 :   ldp_init_check ();
    1396             : 
    1397           0 :   vlsh = ldp_fd_to_vlsh (out_fd);
    1398           0 :   if (vlsh != VLS_INVALID_HANDLE)
    1399             :     {
    1400             :       int rv;
    1401           0 :       ssize_t results = 0;
    1402           0 :       size_t n_bytes_left = len;
    1403             :       size_t bytes_to_read;
    1404             :       int nbytes;
    1405           0 :       u8 eagain = 0;
    1406           0 :       u32 flags, flags_len = sizeof (flags);
    1407             : 
    1408           0 :       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
    1409           0 :       if (PREDICT_FALSE (rv != VPPCOM_OK))
    1410             :         {
    1411           0 :           LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
    1412             :                 out_fd, vlsh, rv, vppcom_retval_str (rv));
    1413             : 
    1414           0 :           vec_reset_length (ldpw->io_buffer);
    1415           0 :           errno = -rv;
    1416           0 :           size = -1;
    1417           0 :           goto done;
    1418             :         }
    1419             : 
    1420           0 :       if (offset)
    1421             :         {
    1422           0 :           off_t off = lseek (in_fd, *offset, SEEK_SET);
    1423           0 :           if (PREDICT_FALSE (off == -1))
    1424             :             {
    1425           0 :               size = -1;
    1426           0 :               goto done;
    1427             :             }
    1428             : 
    1429           0 :           ASSERT (off == *offset);
    1430             :         }
    1431             : 
    1432             :       do
    1433             :         {
    1434           0 :           size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
    1435           0 :           if (size < 0)
    1436             :             {
    1437           0 :               LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
    1438             :                     out_fd, vlsh, size, vppcom_retval_str (size));
    1439           0 :               vec_reset_length (ldpw->io_buffer);
    1440           0 :               errno = -size;
    1441           0 :               size = -1;
    1442           0 :               goto done;
    1443             :             }
    1444             : 
    1445           0 :           bytes_to_read = size;
    1446           0 :           if (bytes_to_read == 0)
    1447             :             {
    1448           0 :               if (flags & O_NONBLOCK)
    1449             :                 {
    1450           0 :                   if (!results)
    1451           0 :                     eagain = 1;
    1452           0 :                   goto update_offset;
    1453             :                 }
    1454             :               else
    1455           0 :                 continue;
    1456             :             }
    1457           0 :           bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
    1458           0 :           vec_validate (ldpw->io_buffer, bytes_to_read);
    1459           0 :           nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
    1460           0 :           if (nbytes < 0)
    1461             :             {
    1462           0 :               if (results == 0)
    1463             :                 {
    1464           0 :                   vec_reset_length (ldpw->io_buffer);
    1465           0 :                   size = -1;
    1466           0 :                   goto done;
    1467             :                 }
    1468           0 :               goto update_offset;
    1469             :             }
    1470             : 
    1471           0 :           size = vls_write (vlsh, ldpw->io_buffer, nbytes);
    1472           0 :           if (size < 0)
    1473             :             {
    1474           0 :               if (size == VPPCOM_EAGAIN)
    1475             :                 {
    1476           0 :                   if (flags & O_NONBLOCK)
    1477             :                     {
    1478           0 :                       if (!results)
    1479           0 :                         eagain = 1;
    1480           0 :                       goto update_offset;
    1481             :                     }
    1482             :                   else
    1483           0 :                     continue;
    1484             :                 }
    1485           0 :               if (results == 0)
    1486             :                 {
    1487           0 :                   vec_reset_length (ldpw->io_buffer);
    1488           0 :                   errno = -size;
    1489           0 :                   size = -1;
    1490           0 :                   goto done;
    1491             :                 }
    1492           0 :               goto update_offset;
    1493             :             }
    1494             : 
    1495           0 :           results += nbytes;
    1496           0 :           ASSERT (n_bytes_left >= nbytes);
    1497           0 :           n_bytes_left = n_bytes_left - nbytes;
    1498             :         }
    1499           0 :       while (n_bytes_left > 0);
    1500             : 
    1501           0 :     update_offset:
    1502           0 :       vec_reset_length (ldpw->io_buffer);
    1503           0 :       if (offset)
    1504             :         {
    1505           0 :           off_t off = lseek (in_fd, *offset, SEEK_SET);
    1506           0 :           if (PREDICT_FALSE (off == -1))
    1507             :             {
    1508           0 :               size = -1;
    1509           0 :               goto done;
    1510             :             }
    1511             : 
    1512           0 :           ASSERT (off == *offset);
    1513           0 :           *offset += results + 1;
    1514             :         }
    1515           0 :       if (eagain)
    1516             :         {
    1517           0 :           errno = EAGAIN;
    1518           0 :           size = -1;
    1519             :         }
    1520             :       else
    1521           0 :         size = results;
    1522             :     }
    1523             :   else
    1524             :     {
    1525           0 :       size = libc_sendfile (out_fd, in_fd, offset, len);
    1526             :     }
    1527             : 
    1528           0 : done:
    1529           0 :   return size;
    1530             : }
    1531             : 
    1532             : ssize_t
    1533           0 : sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
    1534             : {
    1535           0 :   return sendfile (out_fd, in_fd, offset, len);
    1536             : }
    1537             : 
    1538             : ssize_t
    1539             : recv (int fd, void *buf, size_t n, int flags)
    1540             : {
    1541             :   vls_handle_t vlsh;
    1542             :   ssize_t size;
    1543             : 
    1544           2 :   ldp_init_check ();
    1545             : 
    1546           2 :   vlsh = ldp_fd_to_vlsh (fd);
    1547           2 :   if (vlsh != VLS_INVALID_HANDLE)
    1548             :     {
    1549           2 :       size = vls_recvfrom (vlsh, buf, n, flags, NULL);
    1550           2 :       if (size < 0)
    1551             :         {
    1552           0 :           errno = -size;
    1553           0 :           size = -1;
    1554             :         }
    1555             :     }
    1556             :   else
    1557             :     {
    1558           0 :       size = libc_recv (fd, buf, n, flags);
    1559             :     }
    1560             : 
    1561           2 :   return size;
    1562             : }
    1563             : 
    1564             : ssize_t
    1565           0 : __recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
    1566             : {
    1567           0 :   if (n > buflen)
    1568           0 :     return -1;
    1569             : 
    1570           0 :   return recv (fd, buf, n, flags);
    1571             : }
    1572             : 
    1573             : static inline int
    1574           0 : ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
    1575             :                vppcom_endpt_tlv_t *app_tlvs, int flags,
    1576             :                __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
    1577             : {
    1578           0 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1579           0 :   vppcom_endpt_t *ep = 0;
    1580             :   vppcom_endpt_t _ep;
    1581             : 
    1582           0 :   _ep.app_tlvs = app_tlvs;
    1583             : 
    1584           0 :   if (addr)
    1585             :     {
    1586           0 :       ep = &_ep;
    1587           0 :       switch (addr->sa_family)
    1588             :         {
    1589           0 :         case AF_INET:
    1590           0 :           ep->is_ip4 = VPPCOM_IS_IP4;
    1591           0 :           ep->ip =
    1592           0 :             (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
    1593           0 :           ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
    1594           0 :           break;
    1595             : 
    1596           0 :         case AF_INET6:
    1597           0 :           ep->is_ip4 = VPPCOM_IS_IP6;
    1598           0 :           ep->ip =
    1599           0 :             (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
    1600           0 :           ep->port =
    1601           0 :             (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
    1602           0 :           break;
    1603             : 
    1604           0 :         default:
    1605           0 :           return EAFNOSUPPORT;
    1606             :         }
    1607           0 :     }
    1608             : 
    1609           0 :   return vls_sendto (vlsh, (void *) buf, n, flags, ep);
    1610             : }
    1611             : 
    1612             : static int
    1613           2 : ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
    1614             :                   __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
    1615             : {
    1616             :   u8 src_addr[sizeof (struct sockaddr_in6)];
    1617           2 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1618             :   vppcom_endpt_t ep;
    1619             :   ssize_t size;
    1620             :   int rv;
    1621             : 
    1622           2 :   if (addr)
    1623             :     {
    1624           2 :       ep.ip = src_addr;
    1625           2 :       size = vls_recvfrom (vlsh, buf, n, flags, &ep);
    1626             : 
    1627           2 :       if (size > 0)
    1628             :         {
    1629           2 :           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
    1630           2 :           if (rv < 0)
    1631           0 :             size = rv;
    1632             :         }
    1633             :     }
    1634             :   else
    1635           0 :     size = vls_recvfrom (vlsh, buf, n, flags, NULL);
    1636             : 
    1637           2 :   return size;
    1638             : }
    1639             : 
    1640             : ssize_t
    1641             : sendto (int fd, const void *buf, size_t n, int flags,
    1642             :         __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
    1643             : {
    1644           0 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1645             :   vls_handle_t vlsh;
    1646             :   ssize_t size;
    1647             : 
    1648           0 :   ldp_init_check ();
    1649             : 
    1650           0 :   vlsh = ldp_fd_to_vlsh (fd);
    1651           0 :   if (vlsh != VLS_INVALID_HANDLE)
    1652             :     {
    1653           0 :       size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
    1654           0 :       if (size < 0)
    1655             :         {
    1656           0 :           errno = -size;
    1657           0 :           size = -1;
    1658             :         }
    1659             :     }
    1660             :   else
    1661             :     {
    1662           0 :       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
    1663             :     }
    1664             : 
    1665           0 :   return size;
    1666             : }
    1667             : 
    1668             : ssize_t
    1669             : recvfrom (int fd, void *__restrict buf, size_t n, int flags,
    1670             :           __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
    1671             : {
    1672             :   vls_handle_t vlsh;
    1673             :   ssize_t size;
    1674             : 
    1675           2 :   ldp_init_check ();
    1676             : 
    1677           2 :   vlsh = ldp_fd_to_vlsh (fd);
    1678           2 :   if (vlsh != VLS_INVALID_HANDLE)
    1679             :     {
    1680           2 :       size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
    1681           2 :       if (size < 0)
    1682             :         {
    1683           0 :           errno = -size;
    1684           0 :           size = -1;
    1685             :         }
    1686             :     }
    1687             :   else
    1688             :     {
    1689           0 :       size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
    1690             :     }
    1691             : 
    1692           2 :   return size;
    1693             : }
    1694             : 
    1695             : static int
    1696           0 : ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
    1697             :                 vppcom_endpt_tlv_t **app_tlvs)
    1698             : {
    1699           0 :   uint8_t *ad, *at = (uint8_t *) *app_tlvs;
    1700             :   vppcom_endpt_tlv_t *adh;
    1701             :   struct in_pktinfo *pi;
    1702             :   struct cmsghdr *cmsg;
    1703             : 
    1704           0 :   cmsg = CMSG_FIRSTHDR (msg);
    1705             : 
    1706           0 :   while (cmsg != NULL)
    1707             :     {
    1708           0 :       switch (cmsg->cmsg_level)
    1709             :         {
    1710           0 :         case SOL_UDP:
    1711           0 :           switch (cmsg->cmsg_type)
    1712             :             {
    1713           0 :             case UDP_SEGMENT:
    1714           0 :               vec_add2 (at, adh, sizeof (*adh));
    1715           0 :               adh->data_type = VCL_UDP_SEGMENT;
    1716           0 :               adh->data_len = sizeof (uint16_t);
    1717           0 :               vec_add2 (at, ad, sizeof (uint16_t));
    1718           0 :               *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
    1719           0 :               break;
    1720           0 :             default:
    1721           0 :               LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
    1722           0 :               break;
    1723             :             }
    1724           0 :           break;
    1725           0 :         case SOL_IP:
    1726           0 :           switch (cmsg->cmsg_type)
    1727             :             {
    1728           0 :             case IP_PKTINFO:
    1729           0 :               vec_add2 (at, adh, sizeof (*adh));
    1730           0 :               adh->data_type = VCL_IP_PKTINFO;
    1731           0 :               adh->data_len = sizeof (struct in_addr);
    1732           0 :               vec_add2 (at, ad, sizeof (struct in_addr));
    1733           0 :               pi = (void *) CMSG_DATA (cmsg);
    1734           0 :               clib_memcpy_fast (ad, &pi->ipi_spec_dst,
    1735             :                                 sizeof (struct in_addr));
    1736           0 :               break;
    1737           0 :             default:
    1738           0 :               LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
    1739           0 :               break;
    1740             :             }
    1741           0 :           break;
    1742           0 :         default:
    1743           0 :           LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
    1744           0 :           break;
    1745             :         }
    1746           0 :       cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
    1747             :     }
    1748           0 :   *app_tlvs = (vppcom_endpt_tlv_t *) at;
    1749           0 :   return 0;
    1750             : }
    1751             : 
    1752             : static int
    1753           0 : ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
    1754             : {
    1755           0 :   u32 optval, optlen = sizeof (optval);
    1756             :   struct cmsghdr *cmsg;
    1757             : 
    1758           0 :   cmsg = CMSG_FIRSTHDR (msg);
    1759           0 :   memset (cmsg, 0, sizeof (*cmsg));
    1760             : 
    1761           0 :   if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
    1762           0 :     return 0;
    1763             : 
    1764           0 :   if (optval)
    1765             :     {
    1766             :       vppcom_endpt_t ep;
    1767             :       u8 addr_buf[sizeof (struct in_addr)];
    1768           0 :       u32 size = sizeof (ep);
    1769             : 
    1770           0 :       ep.ip = addr_buf;
    1771             : 
    1772           0 :       if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
    1773             :         {
    1774           0 :           struct in_pktinfo pi = {};
    1775             : 
    1776           0 :           clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
    1777           0 :           cmsg->cmsg_level = SOL_IP;
    1778           0 :           cmsg->cmsg_type = IP_PKTINFO;
    1779           0 :           cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
    1780           0 :           clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
    1781             :         }
    1782             :     }
    1783             : 
    1784           0 :   return 0;
    1785             : }
    1786             : 
    1787             : ssize_t
    1788             : sendmsg (int fd, const struct msghdr * msg, int flags)
    1789             : {
    1790             :   vls_handle_t vlsh;
    1791             :   ssize_t size;
    1792             : 
    1793           2 :   ldp_init_check ();
    1794             : 
    1795           2 :   vlsh = ldp_fd_to_vlsh (fd);
    1796           2 :   if (vlsh != VLS_INVALID_HANDLE)
    1797             :     {
    1798           0 :       vppcom_endpt_tlv_t *app_tlvs = 0;
    1799           0 :       struct iovec *iov = msg->msg_iov;
    1800           0 :       ssize_t total = 0;
    1801           0 :       int i, rv = 0;
    1802             : 
    1803           0 :       ldp_parse_cmsg (vlsh, msg, &app_tlvs);
    1804             : 
    1805           0 :       for (i = 0; i < msg->msg_iovlen; ++i)
    1806             :         {
    1807           0 :           rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
    1808           0 :                               flags, msg->msg_name, msg->msg_namelen);
    1809           0 :           if (rv < 0)
    1810           0 :             break;
    1811             :           else
    1812             :             {
    1813           0 :               total += rv;
    1814           0 :               if (rv < iov[i].iov_len)
    1815           0 :                 break;
    1816             :             }
    1817             :         }
    1818             : 
    1819           0 :       vec_free (app_tlvs);
    1820             : 
    1821           0 :       if (rv < 0 && total == 0)
    1822             :         {
    1823           0 :           errno = -rv;
    1824           0 :           size = -1;
    1825             :         }
    1826             :       else
    1827           0 :         size = total;
    1828             :     }
    1829             :   else
    1830             :     {
    1831           2 :       size = libc_sendmsg (fd, msg, flags);
    1832             :     }
    1833             : 
    1834           2 :   return size;
    1835             : }
    1836             : 
    1837             : #ifdef _GNU_SOURCE
    1838             : int
    1839             : sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
    1840             : {
    1841             :   ssize_t size;
    1842             :   const char *func_str;
    1843           0 :   u32 sh = ldp_fd_to_vlsh (fd);
    1844             : 
    1845           0 :   ldp_init_check ();
    1846             : 
    1847           0 :   if (sh != VLS_INVALID_HANDLE)
    1848             :     {
    1849           0 :       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
    1850           0 :       errno = ENOSYS;
    1851           0 :       size = -1;
    1852             :     }
    1853             :   else
    1854             :     {
    1855           0 :       func_str = "libc_sendmmsg";
    1856             : 
    1857           0 :       if (LDP_DEBUG > 2)
    1858           0 :         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
    1859             :                       "vmessages %p, vlen %u, flags 0x%x",
    1860             :                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
    1861             : 
    1862           0 :       size = libc_sendmmsg (fd, vmessages, vlen, flags);
    1863             :     }
    1864             : 
    1865           0 :   if (LDP_DEBUG > 2)
    1866             :     {
    1867           0 :       if (size < 0)
    1868             :         {
    1869           0 :           int errno_val = errno;
    1870           0 :           perror (func_str);
    1871           0 :           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
    1872             :                         "rv %d, errno = %d", getpid (), fd, fd,
    1873             :                         func_str, size, errno_val);
    1874           0 :           errno = errno_val;
    1875             :         }
    1876             :       else
    1877           0 :         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
    1878             :                       getpid (), fd, fd, size, size);
    1879             :     }
    1880           0 :   return size;
    1881             : }
    1882             : #endif
    1883             : 
    1884             : ssize_t
    1885             : recvmsg (int fd, struct msghdr * msg, int flags)
    1886             : {
    1887             :   vls_handle_t vlsh;
    1888             :   ssize_t size;
    1889             : 
    1890        3324 :   ldp_init_check ();
    1891             : 
    1892        3324 :   vlsh = ldp_fd_to_vlsh (fd);
    1893        3324 :   if (vlsh != VLS_INVALID_HANDLE)
    1894             :     {
    1895           0 :       struct iovec *iov = msg->msg_iov;
    1896           0 :       ssize_t max_deq, total = 0;
    1897             :       int i, rv;
    1898             : 
    1899           0 :       max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
    1900           0 :       if (!max_deq)
    1901           0 :         return 0;
    1902             : 
    1903           0 :       for (i = 0; i < msg->msg_iovlen; i++)
    1904             :         {
    1905           0 :           rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
    1906           0 :                                  (i == 0 ? msg->msg_name : NULL),
    1907             :                                  (i == 0 ? &msg->msg_namelen : NULL));
    1908           0 :           if (rv <= 0)
    1909           0 :             break;
    1910             :           else
    1911             :             {
    1912           0 :               total += rv;
    1913           0 :               if (rv < iov[i].iov_len)
    1914           0 :                 break;
    1915             :             }
    1916           0 :           if (total >= max_deq)
    1917           0 :             break;
    1918             :         }
    1919             : 
    1920           0 :       if (rv < 0 && total == 0)
    1921             :         {
    1922           0 :           errno = -rv;
    1923           0 :           size = -1;
    1924             :         }
    1925             :       else
    1926             :         {
    1927           0 :           if (msg->msg_controllen)
    1928           0 :             ldp_make_cmsg (vlsh, msg);
    1929           0 :           size = total;
    1930             :         }
    1931             :     }
    1932             :   else
    1933             :     {
    1934        3324 :       size = libc_recvmsg (fd, msg, flags);
    1935             :     }
    1936             : 
    1937        3324 :   return size;
    1938             : }
    1939             : 
    1940             : #ifdef _GNU_SOURCE
    1941             : int
    1942             : recvmmsg (int fd, struct mmsghdr *vmessages,
    1943             :           unsigned int vlen, int flags, struct timespec *tmo)
    1944             : {
    1945           0 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    1946             :   u32 sh;
    1947             : 
    1948           0 :   ldp_init_check ();
    1949             : 
    1950           0 :   sh = ldp_fd_to_vlsh (fd);
    1951             : 
    1952           0 :   if (sh != VLS_INVALID_HANDLE)
    1953             :     {
    1954             :       struct mmsghdr *mh;
    1955           0 :       ssize_t rv = 0;
    1956           0 :       u32 nvecs = 0;
    1957             :       f64 time_out;
    1958             : 
    1959           0 :       if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
    1960           0 :         clib_time_init (&ldpw->clib_time);
    1961           0 :       if (tmo)
    1962             :         {
    1963           0 :           time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
    1964           0 :           time_out += clib_time_now (&ldpw->clib_time);
    1965             :         }
    1966             :       else
    1967             :         {
    1968           0 :           time_out = (f64) ~0;
    1969             :         }
    1970             : 
    1971           0 :       while (nvecs < vlen)
    1972             :         {
    1973           0 :           mh = &vmessages[nvecs];
    1974           0 :           rv = recvmsg (fd, &mh->msg_hdr, flags);
    1975           0 :           if (rv > 0)
    1976             :             {
    1977           0 :               mh->msg_len = rv;
    1978           0 :               nvecs += 1;
    1979           0 :               continue;
    1980             :             }
    1981             : 
    1982           0 :           if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
    1983             :             break;
    1984             : 
    1985           0 :           usleep (1);
    1986             :         }
    1987             : 
    1988           0 :       return nvecs > 0 ? nvecs : rv;
    1989             :     }
    1990             :   else
    1991             :     {
    1992           0 :       return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
    1993             :     }
    1994             : }
    1995             : #endif
    1996             : 
    1997             : int
    1998             : getsockopt (int fd, int level, int optname,
    1999             :             void *__restrict optval, socklen_t * __restrict optlen)
    2000             : {
    2001             :   vls_handle_t vlsh;
    2002             :   int rv;
    2003             : 
    2004          57 :   ldp_init_check ();
    2005             : 
    2006          57 :   vlsh = ldp_fd_to_vlsh (fd);
    2007          57 :   if (vlsh != VLS_INVALID_HANDLE)
    2008             :     {
    2009          57 :       rv = -EOPNOTSUPP;
    2010             : 
    2011          57 :       switch (level)
    2012             :         {
    2013          33 :         case SOL_TCP:
    2014             :           switch (optname)
    2015             :             {
    2016           0 :             case TCP_NODELAY:
    2017           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
    2018             :                              optval, optlen);
    2019           0 :               break;
    2020           5 :             case TCP_MAXSEG:
    2021           5 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
    2022             :                              optval, optlen);
    2023           5 :               break;
    2024           0 :             case TCP_KEEPIDLE:
    2025           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
    2026             :                              optval, optlen);
    2027           0 :               break;
    2028           0 :             case TCP_KEEPINTVL:
    2029           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
    2030             :                              optval, optlen);
    2031           0 :               break;
    2032          20 :             case TCP_INFO:
    2033          20 :               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
    2034             :                 {
    2035          20 :                   LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
    2036             :                         "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
    2037          20 :                   memset (optval, 0, *optlen);
    2038          20 :                   rv = VPPCOM_OK;
    2039             :                 }
    2040             :               else
    2041           0 :                 rv = -EFAULT;
    2042          20 :               break;
    2043           8 :             case TCP_CONGESTION:
    2044           8 :               *optlen = strlen ("cubic");
    2045           8 :               strncpy (optval, "cubic", *optlen + 1);
    2046           8 :               rv = 0;
    2047           8 :               break;
    2048           0 :             default:
    2049           0 :               LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
    2050             :                     "optname %d unsupported!", fd, vlsh, optname);
    2051           0 :               break;
    2052             :             }
    2053          33 :           break;
    2054           0 :         case SOL_IP:
    2055             :           switch (optname)
    2056             :             {
    2057           0 :             case SO_ORIGINAL_DST:
    2058             :               rv =
    2059           0 :                 vls_attr (vlsh, VPPCOM_ATTR_GET_ORIGINAL_DST, optval, optlen);
    2060           0 :               break;
    2061           0 :             default:
    2062           0 :               LDBG (0,
    2063             :                     "ERROR: fd %d: getsockopt SOL_IP: vlsh %u "
    2064             :                     "optname %d unsupported!",
    2065             :                     fd, vlsh, optname);
    2066           0 :               break;
    2067             :             }
    2068           0 :           break;
    2069           0 :         case SOL_IPV6:
    2070             :           switch (optname)
    2071             :             {
    2072           0 :             case IPV6_V6ONLY:
    2073           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
    2074           0 :               break;
    2075           0 :             default:
    2076           0 :               LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
    2077             :                     "optname %d unsupported!", fd, vlsh, optname);
    2078           0 :               break;
    2079             :             }
    2080           0 :           break;
    2081          24 :         case SOL_SOCKET:
    2082             :           switch (optname)
    2083             :             {
    2084           0 :             case SO_ACCEPTCONN:
    2085           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
    2086           0 :               break;
    2087           0 :             case SO_KEEPALIVE:
    2088           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
    2089           0 :               break;
    2090           0 :             case SO_PROTOCOL:
    2091           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
    2092           0 :               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
    2093           0 :               break;
    2094          12 :             case SO_SNDBUF:
    2095          12 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
    2096             :                              optval, optlen);
    2097          12 :               break;
    2098          12 :             case SO_RCVBUF:
    2099          12 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
    2100             :                              optval, optlen);
    2101          12 :               break;
    2102           0 :             case SO_REUSEADDR:
    2103           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
    2104           0 :               break;
    2105           0 :             case SO_REUSEPORT:
    2106           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
    2107           0 :               break;
    2108           0 :             case SO_BROADCAST:
    2109           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
    2110           0 :               break;
    2111           0 :             case SO_DOMAIN:
    2112           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
    2113           0 :               break;
    2114           0 :             case SO_ERROR:
    2115           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
    2116           0 :               break;
    2117           0 :             case SO_BINDTODEVICE:
    2118           0 :               rv = 0;
    2119           0 :               break;
    2120           0 :             default:
    2121           0 :               LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
    2122             :                     "optname %d unsupported!", fd, vlsh, optname);
    2123           0 :               break;
    2124             :             }
    2125          24 :           break;
    2126           0 :         default:
    2127           0 :           break;
    2128             :         }
    2129             : 
    2130          57 :       if (rv != VPPCOM_OK)
    2131             :         {
    2132           2 :           errno = -rv;
    2133           2 :           rv = -1;
    2134             :         }
    2135             :     }
    2136             :   else
    2137             :     {
    2138           0 :       rv = libc_getsockopt (fd, level, optname, optval, optlen);
    2139             :     }
    2140             : 
    2141          57 :   return rv;
    2142             : }
    2143             : 
    2144             : int
    2145             : setsockopt (int fd, int level, int optname,
    2146             :             const void *optval, socklen_t optlen)
    2147             : {
    2148             :   vls_handle_t vlsh;
    2149             :   int rv;
    2150             : 
    2151          21 :   ldp_init_check ();
    2152             : 
    2153          21 :   vlsh = ldp_fd_to_vlsh (fd);
    2154          21 :   if (vlsh != VLS_INVALID_HANDLE)
    2155             :     {
    2156          21 :       rv = -EOPNOTSUPP;
    2157             : 
    2158          21 :       switch (level)
    2159             :         {
    2160           2 :         case SOL_TCP:
    2161             :           switch (optname)
    2162             :             {
    2163           0 :             case TCP_NODELAY:
    2164           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
    2165             :                              (void *) optval, &optlen);
    2166           0 :               break;
    2167           2 :             case TCP_MAXSEG:
    2168           2 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
    2169             :                              (void *) optval, &optlen);
    2170           2 :               break;
    2171           0 :             case TCP_KEEPIDLE:
    2172           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
    2173             :                              (void *) optval, &optlen);
    2174           0 :               break;
    2175           0 :             case TCP_KEEPINTVL:
    2176           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
    2177             :                              (void *) optval, &optlen);
    2178           0 :               break;
    2179           0 :             case TCP_CONGESTION:
    2180             :             case TCP_CORK:
    2181             :               /* Ignore */
    2182           0 :               rv = 0;
    2183           0 :               break;
    2184           0 :             default:
    2185           0 :               LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
    2186             :                     "optname %d unsupported!", fd, vlsh, optname);
    2187           0 :               break;
    2188             :             }
    2189           2 :           break;
    2190           2 :         case SOL_IPV6:
    2191             :           switch (optname)
    2192             :             {
    2193           2 :             case IPV6_V6ONLY:
    2194           2 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
    2195             :                              (void *) optval, &optlen);
    2196           2 :               break;
    2197           0 :             default:
    2198           0 :               LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
    2199             :                     "optname %d unsupported!", fd, vlsh, optname);
    2200           0 :               break;
    2201             :             }
    2202           2 :           break;
    2203          17 :         case SOL_SOCKET:
    2204             :           switch (optname)
    2205             :             {
    2206           0 :             case SO_KEEPALIVE:
    2207           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
    2208             :                              (void *) optval, &optlen);
    2209           0 :               break;
    2210          15 :             case SO_REUSEADDR:
    2211          15 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
    2212             :                              (void *) optval, &optlen);
    2213          15 :               break;
    2214           0 :             case SO_REUSEPORT:
    2215           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
    2216             :                              &optlen);
    2217           0 :               break;
    2218           0 :             case SO_BROADCAST:
    2219           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
    2220             :                              (void *) optval, &optlen);
    2221           0 :               break;
    2222           0 :             case SO_LINGER:
    2223           0 :               rv = 0;
    2224           0 :               break;
    2225           2 :             default:
    2226           2 :               LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
    2227             :                     "optname %d unsupported!", fd, vlsh, optname);
    2228           2 :               break;
    2229             :             }
    2230          17 :           break;
    2231           0 :         case SOL_IP:
    2232             :           switch (optname)
    2233             :             {
    2234           0 :             case IP_PKTINFO:
    2235           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
    2236             :                              &optlen);
    2237           0 :               break;
    2238           0 :             default:
    2239           0 :               LDBG (0,
    2240             :                     "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
    2241             :                     "unsupported!",
    2242             :                     fd, vlsh, optname);
    2243           0 :               break;
    2244             :             }
    2245           0 :           break;
    2246           0 :         default:
    2247           0 :           break;
    2248             :         }
    2249             : 
    2250          21 :       if (rv != VPPCOM_OK)
    2251             :         {
    2252           2 :           errno = -rv;
    2253           2 :           rv = -1;
    2254             :         }
    2255             :     }
    2256             :   else
    2257             :     {
    2258           0 :       rv = libc_setsockopt (fd, level, optname, optval, optlen);
    2259             :     }
    2260             : 
    2261          21 :   return rv;
    2262             : }
    2263             : 
    2264             : int
    2265             : listen (int fd, int n)
    2266             : {
    2267             :   vls_handle_t vlsh;
    2268             :   int rv;
    2269             : 
    2270          14 :   ldp_init_check ();
    2271             : 
    2272          14 :   vlsh = ldp_fd_to_vlsh (fd);
    2273          14 :   if (vlsh != VLS_INVALID_HANDLE)
    2274             :     {
    2275          13 :       LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
    2276             : 
    2277          13 :       rv = vls_listen (vlsh, n);
    2278          13 :       if (rv != VPPCOM_OK)
    2279             :         {
    2280           0 :           errno = -rv;
    2281           0 :           rv = -1;
    2282             :         }
    2283             :     }
    2284             :   else
    2285             :     {
    2286           1 :       LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
    2287           1 :       rv = libc_listen (fd, n);
    2288             :     }
    2289             : 
    2290          14 :   LDBG (1, "fd %d: returning %d", fd, rv);
    2291          14 :   return rv;
    2292             : }
    2293             : 
    2294             : static inline int
    2295          11 : ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
    2296             :              socklen_t *__restrict addr_len, int flags)
    2297             : {
    2298          11 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    2299             :   vls_handle_t listen_vlsh, accept_vlsh;
    2300             :   int rv;
    2301             : 
    2302          11 :   ldp_init_check ();
    2303             : 
    2304          11 :   listen_vlsh = ldp_fd_to_vlsh (listen_fd);
    2305          11 :   if (listen_vlsh != VLS_INVALID_HANDLE)
    2306             :     {
    2307             :       vppcom_endpt_t ep;
    2308             :       u8 src_addr[sizeof (struct sockaddr_in6)];
    2309          11 :       memset (&ep, 0, sizeof (ep));
    2310          11 :       ep.ip = src_addr;
    2311             : 
    2312          11 :       LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
    2313             :             " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
    2314             : 
    2315          11 :       accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
    2316          11 :       if (accept_vlsh < 0)
    2317             :         {
    2318           0 :           errno = -accept_vlsh;
    2319           0 :           rv = -1;
    2320             :         }
    2321             :       else
    2322             :         {
    2323          11 :           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
    2324          11 :           if (rv != VPPCOM_OK)
    2325             :             {
    2326           0 :               (void) vls_close (accept_vlsh);
    2327           0 :               errno = -rv;
    2328           0 :               rv = -1;
    2329             :             }
    2330             :           else
    2331             :             {
    2332          11 :               rv = ldp_vlsh_to_fd (accept_vlsh);
    2333             :             }
    2334             :         }
    2335             :     }
    2336             :   else
    2337             :     {
    2338           0 :       LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
    2339             :             " flags 0x%x", listen_fd, addr, addr_len, flags);
    2340             : 
    2341           0 :       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
    2342             :     }
    2343             : 
    2344          11 :   LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
    2345             : 
    2346          11 :   return rv;
    2347             : }
    2348             : 
    2349             : int
    2350             : accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
    2351             :          int flags)
    2352             : {
    2353           0 :   return ldp_accept4 (fd, addr, addr_len, flags);
    2354             : }
    2355             : 
    2356             : int
    2357             : accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
    2358             : {
    2359          11 :   return ldp_accept4 (fd, addr, addr_len, 0);
    2360             : }
    2361             : 
    2362             : int
    2363             : shutdown (int fd, int how)
    2364             : {
    2365             :   vls_handle_t vlsh;
    2366           0 :   int rv = 0;
    2367             : 
    2368           0 :   ldp_init_check ();
    2369             : 
    2370           0 :   vlsh = ldp_fd_to_vlsh (fd);
    2371           0 :   if (vlsh != VLS_INVALID_HANDLE)
    2372             :     {
    2373           0 :       LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
    2374           0 :       rv = vls_shutdown (vlsh, how);
    2375             :     }
    2376             :   else
    2377             :     {
    2378           0 :       LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
    2379           0 :       rv = libc_shutdown (fd, how);
    2380             :     }
    2381             : 
    2382           0 :   return rv;
    2383             : }
    2384             : 
    2385             : int
    2386             : epoll_create1 (int flags)
    2387             : {
    2388           1 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    2389             :   vls_handle_t vlsh;
    2390             :   int rv;
    2391             : 
    2392           1 :   ldp_init_check ();
    2393             : 
    2394           1 :   if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
    2395             :     {
    2396             :       /* Make sure workers have been allocated */
    2397           0 :       if (!ldp->workers)
    2398             :         {
    2399           0 :           ldp_alloc_workers ();
    2400           0 :           ldpw = ldp_worker_get_current ();
    2401             :         }
    2402           0 :       rv = libc_epoll_create1 (flags);
    2403           0 :       ldp->vcl_needs_real_epoll = 0;
    2404           0 :       ldpw->vcl_mq_epfd = rv;
    2405           0 :       LDBG (0, "created vcl epfd %u", rv);
    2406           0 :       return rv;
    2407             :     }
    2408             : 
    2409           1 :   vlsh = vls_epoll_create ();
    2410           1 :   if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
    2411             :     {
    2412           0 :       errno = -vlsh;
    2413           0 :       rv = -1;
    2414             :     }
    2415             :   else
    2416             :     {
    2417           1 :       rv = ldp_vlsh_to_fd (vlsh);
    2418             :     }
    2419           1 :   LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
    2420           1 :   return rv;
    2421             : }
    2422             : 
    2423             : int
    2424             : epoll_create (int size)
    2425             : {
    2426           1 :   return epoll_create1 (0);
    2427             : }
    2428             : 
    2429             : int
    2430             : epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
    2431             : {
    2432             :   vls_handle_t vep_vlsh, vlsh;
    2433             :   int rv;
    2434             : 
    2435           4 :   ldp_init_check ();
    2436             : 
    2437           4 :   vep_vlsh = ldp_fd_to_vlsh (epfd);
    2438           4 :   if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
    2439             :     {
    2440             :       /* The LDP epoll_create1 always creates VCL epfd's.
    2441             :        * The app should never have a kernel base epoll fd unless it
    2442             :        * was acquired outside of the LD_PRELOAD process context.
    2443             :        * In any case, if we get one, punt it to libc_epoll_ctl.
    2444             :        */
    2445           0 :       LDBG (1,
    2446             :             "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
    2447             :             " events 0x%x",
    2448             :             epfd, op, fd, event ? event->events : 0);
    2449             : 
    2450           0 :       rv = libc_epoll_ctl (epfd, op, fd, event);
    2451           0 :       goto done;
    2452             :     }
    2453             : 
    2454           4 :   vlsh = ldp_fd_to_vlsh (fd);
    2455             : 
    2456           4 :   LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
    2457             :         vlsh, op);
    2458             : 
    2459           4 :   if (vlsh != VLS_INVALID_HANDLE)
    2460             :     {
    2461           3 :       LDBG (1,
    2462             :             "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
    2463             :             " events 0x%x",
    2464             :             epfd, vep_vlsh, op, vlsh, event ? event->events : 0);
    2465             : 
    2466           3 :       rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
    2467           3 :       if (rv != VPPCOM_OK)
    2468             :         {
    2469           0 :           errno = -rv;
    2470           0 :           rv = -1;
    2471             :         }
    2472             :     }
    2473             :   else
    2474             :     {
    2475             :       int libc_epfd;
    2476           1 :       u32 size = sizeof (epfd);
    2477             : 
    2478           1 :       libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
    2479           1 :       if (!libc_epfd)
    2480             :         {
    2481           1 :           LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
    2482             :                 "EPOLL_CLOEXEC", epfd, vep_vlsh);
    2483             : 
    2484           1 :           libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
    2485           1 :           if (libc_epfd < 0)
    2486             :             {
    2487           0 :               rv = libc_epfd;
    2488           0 :               goto done;
    2489             :             }
    2490             : 
    2491           1 :           rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
    2492             :                          &size);
    2493           1 :           if (rv < 0)
    2494             :             {
    2495           0 :               errno = -rv;
    2496           0 :               rv = -1;
    2497           0 :               goto done;
    2498             :             }
    2499             :         }
    2500           0 :       else if (PREDICT_FALSE (libc_epfd < 0))
    2501             :         {
    2502           0 :           errno = -epfd;
    2503           0 :           rv = -1;
    2504           0 :           goto done;
    2505             :         }
    2506             : 
    2507           1 :       LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
    2508             :             " event %p", epfd, libc_epfd, op, fd, event);
    2509             : 
    2510           1 :       rv = libc_epoll_ctl (libc_epfd, op, fd, event);
    2511             :     }
    2512             : 
    2513           4 : done:
    2514           4 :   return rv;
    2515             : }
    2516             : 
    2517             : static inline int
    2518         248 : ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
    2519             :                  int timeout, const sigset_t * sigmask)
    2520             : {
    2521             :   ldp_worker_ctx_t *ldpw;
    2522         248 :   double time_to_wait = (double) 0, max_time;
    2523         248 :   int libc_epfd, rv = 0;
    2524             :   vls_handle_t ep_vlsh;
    2525             : 
    2526         248 :   ldp_init_check ();
    2527             : 
    2528         248 :   if (PREDICT_FALSE (!events || (timeout < -1)))
    2529             :     {
    2530           0 :       errno = EFAULT;
    2531           0 :       return -1;
    2532             :     }
    2533             : 
    2534         248 :   if (PREDICT_FALSE (vppcom_worker_index () == ~0))
    2535           0 :     vls_register_vcl_worker ();
    2536             : 
    2537         248 :   ldpw = ldp_worker_get_current ();
    2538         248 :   if (epfd == ldpw->vcl_mq_epfd)
    2539           0 :     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
    2540             : 
    2541         248 :   ep_vlsh = ldp_fd_to_vlsh (epfd);
    2542         248 :   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
    2543             :     {
    2544           0 :       LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
    2545           0 :       errno = EBADFD;
    2546           0 :       return -1;
    2547             :     }
    2548             : 
    2549         248 :   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
    2550           1 :     clib_time_init (&ldpw->clib_time);
    2551         248 :   time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
    2552         248 :   max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
    2553             : 
    2554         248 :   libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
    2555         248 :   if (PREDICT_FALSE (libc_epfd < 0))
    2556             :     {
    2557           0 :       errno = -libc_epfd;
    2558           0 :       rv = -1;
    2559           0 :       goto done;
    2560             :     }
    2561             : 
    2562         248 :   LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
    2563             :         "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
    2564             :         libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
    2565             :   do
    2566             :     {
    2567     1374290 :       if (!ldpw->epoll_wait_vcl)
    2568             :         {
    2569     1374040 :           rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
    2570     1374040 :           if (rv > 0)
    2571             :             {
    2572         248 :               ldpw->epoll_wait_vcl = 1;
    2573         248 :               goto done;
    2574             :             }
    2575     1373790 :           else if (rv < 0)
    2576             :             {
    2577           0 :               errno = -rv;
    2578           0 :               rv = -1;
    2579           0 :               goto done;
    2580             :             }
    2581             :         }
    2582             :       else
    2583         247 :         ldpw->epoll_wait_vcl = 0;
    2584             : 
    2585     1374040 :       if (libc_epfd > 0)
    2586             :         {
    2587         144 :           rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
    2588         144 :           if (rv != 0)
    2589           0 :             goto done;
    2590             :         }
    2591             :     }
    2592     1374040 :   while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
    2593             : 
    2594           0 : done:
    2595         248 :   return rv;
    2596             : }
    2597             : 
    2598             : static inline int
    2599           0 : ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
    2600             :                          int maxevents, int timeout, const sigset_t * sigmask)
    2601             : {
    2602           0 :   int libc_epfd, rv = 0, num_ev, libc_num_ev, vcl_wups = 0;
    2603             :   struct epoll_event *libc_evts;
    2604             :   ldp_worker_ctx_t *ldpw;
    2605             :   vls_handle_t ep_vlsh;
    2606             : 
    2607           0 :   ldp_init_check ();
    2608             : 
    2609           0 :   if (PREDICT_FALSE (!events || (timeout < -1)))
    2610             :     {
    2611           0 :       errno = EFAULT;
    2612           0 :       return -1;
    2613             :     }
    2614             : 
    2615             :   /* Make sure the vcl worker is valid. Could be that epoll fd was created on
    2616             :    * one thread but it is now used on another */
    2617           0 :   if (PREDICT_FALSE (vppcom_worker_index () == ~0))
    2618           0 :     vls_register_vcl_worker ();
    2619             : 
    2620           0 :   ldpw = ldp_worker_get_current ();
    2621           0 :   if (epfd == ldpw->vcl_mq_epfd)
    2622           0 :     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
    2623             : 
    2624           0 :   ep_vlsh = ldp_fd_to_vlsh (epfd);
    2625           0 :   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
    2626             :     {
    2627           0 :       LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
    2628           0 :       errno = EBADFD;
    2629           0 :       return -1;
    2630             :     }
    2631             : 
    2632           0 :   libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
    2633           0 :   if (PREDICT_FALSE (!libc_epfd))
    2634             :     {
    2635           0 :       u32 size = sizeof (epfd);
    2636             : 
    2637           0 :       LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
    2638             :             "EPOLL_CLOEXEC", epfd, ep_vlsh);
    2639           0 :       libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
    2640           0 :       if (libc_epfd < 0)
    2641             :         {
    2642           0 :           rv = libc_epfd;
    2643           0 :           goto done;
    2644             :         }
    2645             : 
    2646           0 :       rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
    2647           0 :       if (rv < 0)
    2648             :         {
    2649           0 :           errno = -rv;
    2650           0 :           rv = -1;
    2651           0 :           goto done;
    2652             :         }
    2653             :     }
    2654           0 :   if (PREDICT_FALSE (libc_epfd <= 0))
    2655             :     {
    2656           0 :       errno = -libc_epfd;
    2657           0 :       rv = -1;
    2658           0 :       goto done;
    2659             :     }
    2660             : 
    2661           0 :   if (PREDICT_FALSE (!ldpw->mq_epfd_added))
    2662             :     {
    2663           0 :       struct epoll_event e = { 0 };
    2664           0 :       e.events = EPOLLIN;
    2665           0 :       e.data.fd = ldpw->vcl_mq_epfd;
    2666           0 :       if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
    2667             :           0)
    2668             :         {
    2669           0 :           LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
    2670             :                 epfd, ldpw->vcl_mq_epfd, libc_epfd);
    2671           0 :           rv = -1;
    2672           0 :           goto done;
    2673             :         }
    2674           0 :       ldpw->mq_epfd_added = 1;
    2675             :     }
    2676             : 
    2677             :   /* Request to only drain unhandled to prevent libc_epoll_wait starved */
    2678           0 :   rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
    2679           0 :   if (rv > 0)
    2680             :     {
    2681           0 :       timeout = 0;
    2682           0 :       if (rv >= maxevents)
    2683           0 :         goto done;
    2684           0 :       maxevents -= rv;
    2685             :     }
    2686           0 :   else if (PREDICT_FALSE (rv < 0))
    2687             :     {
    2688           0 :       errno = -rv;
    2689           0 :       rv = -1;
    2690           0 :       goto done;
    2691             :     }
    2692             : 
    2693           0 : epoll_again:
    2694             : 
    2695           0 :   libc_evts = &events[rv];
    2696             :   libc_num_ev =
    2697           0 :     libc_epoll_pwait (libc_epfd, libc_evts, maxevents, timeout, sigmask);
    2698           0 :   if (libc_num_ev <= 0)
    2699             :     {
    2700           0 :       rv = rv >= 0 ? rv : -1;
    2701           0 :       goto done;
    2702             :     }
    2703             : 
    2704           0 :   for (int i = 0; i < libc_num_ev; i++)
    2705             :     {
    2706           0 :       if (libc_evts[i].data.fd == ldpw->vcl_mq_epfd)
    2707             :         {
    2708             :           /* We should remove mq epoll fd from events. */
    2709           0 :           libc_num_ev--;
    2710           0 :           if (i != libc_num_ev)
    2711             :             {
    2712           0 :               libc_evts[i].events = libc_evts[libc_num_ev].events;
    2713           0 :               libc_evts[i].data.u64 = libc_evts[libc_num_ev].data.u64;
    2714             :             }
    2715           0 :           num_ev = vls_epoll_wait (ep_vlsh, &libc_evts[libc_num_ev],
    2716             :                                    maxevents - libc_num_ev, 0);
    2717           0 :           if (PREDICT_TRUE (num_ev > 0))
    2718           0 :             rv += num_ev;
    2719             :           /* Woken up by vcl but no events generated. Accept it once */
    2720           0 :           if (rv == 0 && libc_num_ev == 0 && timeout && vcl_wups++ < 1)
    2721           0 :             goto epoll_again;
    2722           0 :           break;
    2723             :         }
    2724             :     }
    2725             : 
    2726           0 :   rv += libc_num_ev;
    2727             : 
    2728           0 : done:
    2729           0 :   return rv;
    2730             : }
    2731             : 
    2732             : int
    2733             : epoll_pwait (int epfd, struct epoll_event *events,
    2734             :              int maxevents, int timeout, const sigset_t * sigmask)
    2735             : {
    2736           0 :   if (vls_use_eventfd ())
    2737           0 :     return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
    2738             :                                     sigmask);
    2739             :   else
    2740           0 :     return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
    2741             : }
    2742             : 
    2743             : int
    2744             : epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
    2745             : {
    2746         248 :   if (vls_use_eventfd ())
    2747           0 :     return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
    2748             :   else
    2749         248 :     return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
    2750             : }
    2751             : 
    2752             : int
    2753             : poll (struct pollfd *fds, nfds_t nfds, int timeout)
    2754             : {
    2755           0 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    2756           0 :   int rv, i, n_revents = 0;
    2757             :   vls_handle_t vlsh;
    2758             :   vcl_poll_t *vp;
    2759             :   double max_time;
    2760             : 
    2761           0 :   LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
    2762             : 
    2763           0 :   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
    2764           0 :     clib_time_init (&ldpw->clib_time);
    2765             : 
    2766           0 :   max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
    2767           0 :   max_time += clib_time_now (&ldpw->clib_time);
    2768             : 
    2769           0 :   for (i = 0; i < nfds; i++)
    2770             :     {
    2771           0 :       if (fds[i].fd < 0)
    2772           0 :         continue;
    2773             : 
    2774           0 :       vlsh = ldp_fd_to_vlsh (fds[i].fd);
    2775           0 :       if (vlsh != VLS_INVALID_HANDLE)
    2776             :         {
    2777           0 :           fds[i].fd = -fds[i].fd;
    2778           0 :           vec_add2 (ldpw->vcl_poll, vp, 1);
    2779           0 :           vp->fds_ndx = i;
    2780           0 :           vp->sh = vlsh_to_sh (vlsh);
    2781           0 :           vp->events = fds[i].events;
    2782             : #ifdef __USE_XOPEN2K
    2783           0 :           if (fds[i].events & POLLRDNORM)
    2784           0 :             vp->events |= POLLIN;
    2785           0 :           if (fds[i].events & POLLWRNORM)
    2786           0 :             vp->events |= POLLOUT;
    2787             : #endif
    2788           0 :           vp->revents = fds[i].revents;
    2789             :         }
    2790             :       else
    2791             :         {
    2792           0 :           vec_add1 (ldpw->libc_poll, fds[i]);
    2793           0 :           vec_add1 (ldpw->libc_poll_idxs, i);
    2794             :         }
    2795             :     }
    2796             : 
    2797             :   do
    2798             :     {
    2799           0 :       if (vec_len (ldpw->vcl_poll))
    2800             :         {
    2801           0 :           rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
    2802           0 :           if (rv < 0)
    2803             :             {
    2804           0 :               errno = -rv;
    2805           0 :               rv = -1;
    2806           0 :               goto done;
    2807             :             }
    2808             :           else
    2809           0 :             n_revents += rv;
    2810             :         }
    2811             : 
    2812           0 :       if (vec_len (ldpw->libc_poll))
    2813             :         {
    2814           0 :           rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
    2815           0 :           if (rv < 0)
    2816           0 :             goto done;
    2817             :           else
    2818           0 :             n_revents += rv;
    2819             :         }
    2820             : 
    2821           0 :       if (n_revents)
    2822             :         {
    2823           0 :           rv = n_revents;
    2824           0 :           goto done;
    2825             :         }
    2826             :     }
    2827           0 :   while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
    2828           0 :   rv = 0;
    2829             : 
    2830           0 : done:
    2831           0 :   vec_foreach (vp, ldpw->vcl_poll)
    2832             :   {
    2833           0 :     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
    2834           0 :     fds[vp->fds_ndx].revents = vp->revents;
    2835             : #ifdef __USE_XOPEN2K
    2836           0 :     if ((fds[vp->fds_ndx].revents & POLLIN) &&
    2837           0 :         (fds[vp->fds_ndx].events & POLLRDNORM))
    2838           0 :       fds[vp->fds_ndx].revents |= POLLRDNORM;
    2839           0 :     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
    2840           0 :         (fds[vp->fds_ndx].events & POLLWRNORM))
    2841           0 :       fds[vp->fds_ndx].revents |= POLLWRNORM;
    2842             : #endif
    2843             :   }
    2844           0 :   vec_reset_length (ldpw->vcl_poll);
    2845             : 
    2846           0 :   for (i = 0; i < vec_len (ldpw->libc_poll); i++)
    2847             :     {
    2848           0 :       fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
    2849             :     }
    2850           0 :   vec_reset_length (ldpw->libc_poll_idxs);
    2851           0 :   vec_reset_length (ldpw->libc_poll);
    2852             : 
    2853           0 :   return rv;
    2854             : }
    2855             : 
    2856             : #ifdef _GNU_SOURCE
    2857             : int
    2858             : ppoll (struct pollfd *fds, nfds_t nfds,
    2859             :        const struct timespec *timeout, const sigset_t * sigmask)
    2860             : {
    2861           0 :   ldp_init_check ();
    2862             : 
    2863           0 :   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
    2864           0 :   errno = ENOSYS;
    2865             : 
    2866             : 
    2867           0 :   return -1;
    2868             : }
    2869             : #endif
    2870             : 
    2871             : void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
    2872             : 
    2873             : void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
    2874             : 
    2875             : /*
    2876             :  * This function is called when the library is loaded
    2877             :  */
    2878             : void
    2879          13 : ldp_constructor (void)
    2880             : {
    2881          13 :   swrap_constructor ();
    2882          13 :   if (ldp_init () != 0)
    2883             :     {
    2884           0 :       fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
    2885             :                getpid ());
    2886           0 :       _exit (1);
    2887             :     }
    2888          13 :   else if (LDP_DEBUG > 0)
    2889          13 :     clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
    2890          13 : }
    2891             : 
    2892             : /*
    2893             :  * This function is called when the library is unloaded
    2894             :  */
    2895             : void
    2896          13 : ldp_destructor (void)
    2897             : {
    2898             :   /*
    2899             :      swrap_destructor ();
    2900             :      if (ldp->init)
    2901             :      ldp->init = 0;
    2902             :    */
    2903             : 
    2904             :   /* Don't use clib_warning() here because that calls writev()
    2905             :    * which will call ldp_init().
    2906             :    */
    2907          13 :   if (LDP_DEBUG > 0)
    2908          13 :     fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
    2909             :              __func__, __LINE__, getpid ());
    2910          13 : }
    2911             : 
    2912             : 
    2913             : /*
    2914             :  * fd.io coding-style-patch-verification: ON
    2915             :  *
    2916             :  * Local Variables:
    2917             :  * eval: (c-set-style "gnu")
    2918             :  * End:
    2919             :  */

Generated by: LCOV version 1.14