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