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